Clang vs GCC - ¿qué produce mejores binarios? [cerrado]


Actualmente estoy usando GCC, pero descubrí Clang recientemente y estoy reflexionando sobre el cambio. Sin embargo, hay un factor decisivo - la calidad (velocidad, huella de memoria, fiabilidad) de los binarios que produce - si gcc -O3puede producir un binario que se ejecuta un 1% más rápido o toma un 1% menos de memoria, es un factor decisivo.

Clang cuenta con mejores velocidades de compilación y menor huella de memoria en tiempo de compilación que GCC, pero estoy realmente interesado en los puntos de referencia / comparaciones del software compilado resultante - ¿podría señalar yo a algunos o describir sus experiencias?

Author: SF., 2010-07-06

7 answers

Aquí hay algunos hallazgos actualizados, aunque limitados, con GCC 4.7.2 y Clang 3.2 para C++.

ACTUALIZACIÓN: GCC 4.8.1 v clang 3.3 comparación adjunta a continuación.

ACTUALIZACIÓN: GCC 4.8.2 v clang 3.4 comparación se adjunta a eso.

Mantengo una herramienta OSS que está construida para Linux con GCC y Clang, y con el compilador de Microsoft para Windows. La herramienta, coan, es un preprocesador and analyser of C / C++ source files and codelines of such: its computational profile se especializa en análisis de descenso recursivo y manejo de archivos. La subdivisión de desarrollo (a la que pertenecen estos resultados) comprende en la actualidad alrededor de 11K LOC en unos 90 archivos. Está codificado, ahora, en C++ que es rico en polimorfismo y plantillas y pero sigue siendo sumido en muchos parches por su pasado no tan lejano en hacked-together C. La semántica de Move no se explota expresamente. Es de un solo hilo. Me no han dedicado ningún esfuerzo serio a optimizarlo, mientras que la " arquitectura" sigue siendo así en gran parte todo.

Empleé Clang antes de 3.2 solo como compilador experimental porque, a pesar de su velocidad superior de compilación y diagnóstico, su C++11 soporte estándar se retrasó la versión contemporánea GCC en el respeto ejercido por coan. Con 3.2, esta brecha se ha cerrado.

Mi arnés de prueba de Linux para los procesos de desarrollo coan actuales aproximadamente Archivos de fuentes de 70K en una mezcla de casos de prueba de analizador de un solo archivo, estrés pruebas que consumen 1000s de archivos y pruebas de escenarios consumir archivos time y captura y suma los números reportados). Los tiempos son halagados por el hecho de que cualquier número de pruebas que toman 0 tiempo medible será todos suman 0, pero la contribución de tales pruebas es insignificante. El las estadísticas de tiempo se muestran al final de make check así:

coan_test_timer: info: coan processed 70844 input_files.
coan_test_timer: info: run time in coan: 16.4 secs.
coan_test_timer: info: Average processing time per input file: 0.000231 secs.

Comparé el rendimiento del arnés de prueba entre GCC 4.7.2 y Clang 3.2, todas las cosas son iguales excepto los compiladores. A partir de Clang 3.2, I ya no requiere ninguna diferenciación preprocesador entre el código tratados que GCC compilará y Clang alternativas. Construí a la misma biblioteca de C++ (GCC) en cada caso y ejecutó todas las comparaciones consecutivamente en la misma sesión terminal.

El nivel de optimización predeterminado para mi versión es-O2. Me también versiones probadas con éxito en-O3. Probé cada configuración 3 tiempos consecutivos y promediaron los 3 resultados, con lo siguiente resultado. El número en una celda de datos es el número promedio de microsegundos consumidos por el ejecutable coan para procesar cada uno de los ~70K archivos de entrada (leer, analizar y escribir salida y diagnósticos).

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.7.2 | 231 | 237 |0.97 |
----------|-----|-----|-----|
Clang-3.2 | 234 | 186 |1.25 |
----------|-----|-----|------
GCC/Clang |0.99 | 1.27|

Es muy probable que cualquier aplicación en particular tenga rasgos que jueguen injustamente a las fortalezas o debilidades de un compilador. Benchmarking riguroso emplear diversas aplicaciones. Con eso bien en mente, el notable las características de estos datos son:

  1. - La optimización de O3 fue marginalmente perjudicial para GCC
  2. - La optimización de O3 fue muy beneficiosa para Clang
  3. Optimización At-O2, GCC fue más rápido que Clang por solo un bigote
  4. Optimización At-O3, Clang fue más rápido que GCC.

Otra comparación interesante de los dos compiladores surgió por accidente poco después de esos hallazgos. Coan emplea generosamente punteros inteligentes y uno de ellos se ejerce fuertemente en el manejo de archivos. Este particular el tipo smart-pointer había sido typedef'd en versiones anteriores por el bien de diferenciación del compilador, para ser un std::unique_ptr<X> si el el compilador configurado tenía suficiente soporte maduro para su uso como eso, y de lo contrario un std::shared_ptr<X>. El sesgo a std::unique_ptr fue tonto, ya que estos punteros fueron de hecho transferidos alrededor, pero std::unique_ptr parecía la opción más adecuada para reemplazar std::auto_ptr en un momento en que las variantes de C++11 eran nuevas para mí.

En el curso de compilaciones experimentales para medir la necesidad continua de Clang 3.2 para esta diferenciación y similar, construí inadvertidamente std::shared_ptr<X> cuando tenía la intención de construir std::unique_ptr<X>, y se sorprendió al observar que el ejecutable resultante, con default-O2 optimización, fue la más rápida que había visto, a veces logrando 184 msecs. por archivo de entrada. Con este cambio al código fuente, los resultados correspondientes fueron los siguientes;

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.7.2 | 234 | 234 |1.00 |
----------|-----|-----|-----|
Clang-3.2 | 188 | 187 |1.00 |
----------|-----|-----|------
GCC/Clang |1.24 |1.25 |

El los puntos de nota aquí son:

  1. Ninguno de los compiladores ahora se beneficia en absoluto de la optimización-O3.
  2. Clang supera a GCC igual de importante en cada nivel de optimización.
  3. El rendimiento de GCC solo se ve afectado marginalmente por el tipo de puntero inteligente cambio.
  4. El rendimiento de Clang-O2 se ve afectado de manera importante por el tipo de puntero inteligente cambio.

Antes y después del cambio de tipo de puntero inteligente, Clang es capaz de construir un coan sustancialmente más rápido optimización at-O3 ejecutable, y puede construir un ejecutable igualmente más rápido en-O2 y-O3 cuando eso pointer-type es el mejor - std::shared_ptr<X> - para el trabajo.

Una pregunta obvia que no soy competente para comentar es ¿por qué Clang debería ser capaz de encontrar una velocidad de 25% -O2 en mi aplicación cuando un tipo de puntero inteligente muy utilizado se cambia de único a compartido, mientras que el CCG es indiferente al mismo cambio. Ni sé si debería animo o abucheo el descubrimiento que Puertos de optimización de O2 de Clang tal enorme sensibilidad a la sabiduría de mis opciones de puntero inteligente.

ACTUALIZACIÓN: GCC 4.8.1 v clang 3.3

Los resultados correspondientes ahora son:

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.1 | 442 | 443 |1.00 |
----------|-----|-----|-----|
Clang-3.3 | 374 | 370 |1.01 |
----------|-----|-----|------
GCC/Clang |1.18 |1.20 |

El hecho de que los cuatro ejecutables ahora toman un tiempo promedio mucho mayor que antes para procesar 1 el archivo no refleja el rendimiento de los últimos compiladores. Es debido a la hecho de que la rama de desarrollo posterior de la aplicación de prueba ha tomado mucho de analizar la sofisticación en el ínterin y paga por ello en velocidad. Sólo los ratios son significativo.

Los puntos de nota ahora no son sorprendentemente novedosos:{[23]]}

  • GCC es indiferente a la optimización-O3
  • clang se beneficia muy marginalmente de la optimización-O3
  • clang supera a GCC por un margen de importancia similar en cada nivel de optimización.

Comparando estos resultados con los de GCC 4.7.2 y clang 3.2, se destaca que GCC ha arañado de vuelta alrededor de un cuarto de ventaja de clang en cada nivel de optimización. Pero dado que la aplicación de prueba ha sido muy desarrollada en el ínterin, no se puede atribuya esto con confianza a una actualización en la generación de código de GCC. (Esta vez, he notado la instantánea de la aplicación a partir de la cual se obtuvieron los tiempos y puede usarlo de nuevo.)

ACTUALIZACIÓN: GCC 4.8.2 v clang 3.4

Terminé la actualización para GCC 4.8.1 v Clang 3.3 diciendo que lo haría se adhieren a la misma snaphot coan para más actualizaciones. Pero decidí en lugar de probar en esa instantánea (rev. 301) y en el último desarrollo tengo una instantánea que pasa su conjunto de pruebas (rev. 619). Esto da a los resultados un un poco de longitud, y tenía otro motivo:

Mi publicación original señaló que no había dedicado ningún esfuerzo a optimizar coan para velocidad. Este seguía siendo el caso a partir de apocalipsis 301. Sin embargo, después de haber construido el aparato de tiempo en el arnés de prueba coan, cada vez que ejecuté la suite de prueba el el impacto en el rendimiento de los últimos cambios me miró a la cara. Vi que a menudo era sorprendentemente grande y que la tendencia era más abruptamente negativa que Me sentí merecida por las ganancias en funcionalidad.

Por rev. 308 el tiempo promedio de procesamiento por archivo de entrada en el conjunto de pruebas había bueno, más del doble desde la primera publicación aquí. En ese momento hice un U-turn en mi política de 10 años de no preocuparse por el rendimiento. En el intensivo spate of revisions up to 619 performance was siempre una consideración y un gran número de ellos fueron puramente a reescribir portadores de carga clave en fundamentalmente líneas más rápidas(aunque sin usar ninguna característica de compilador no estándar para hacerlo). Sería interesante ver la reacción de cada compilador a esto Vuelta en U,

Aquí está la ya familiar matriz de tiempos para las últimas versiones de los dos compiladores de apocalipsis 301:

coan-rev. 301 resultados

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.2 | 428 | 428 |1.00 |
----------|-----|-----|-----|
Clang-3.4 | 390 | 365 |1.07 |
----------|-----|-----|------
GCC/Clang | 1.1 | 1.17|

La historia aquí solo cambia marginalmente de GCC-4.8.1 y Clang-3.3. GCC muestra es un poco mejor. Clang es un poco peor. El ruido bien podría explicar esto. Clang todavía sale adelante por -O2 y -O3 márgenes que no importarían en la mayoría aplicaciones, pero sería importante para un buen número de.

Y aquí está la matriz para apocalipsis 619.

coan-rev. 619 resultados

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.2 | 210 | 208 |1.01 |
----------|-----|-----|-----|
Clang-3.4 | 252 | 250 |1.01 |
----------|-----|-----|------
GCC/Clang |0.83 | 0.83|

Tomando las figuras 301 y 619 lado a lado, varios puntos hablan.

  • Yo había apuntado escribir código más rápido, y ambos compiladores reivindican enfáticamente mis esfuerzos. Pero:

  • El Consejo de Cooperación del Golfo reembolsa esos esfuerzos con mucha más generosidad que Clang. At -O2 optimización La compilación 619 de Clang es un 46% más rápida que la compilación 301: at -O3 la mejora es del 31%. Bueno, pero en cada nivel de optimización GCC 619 build es más del doble de rápido que su 301.

  • GCC más que invierte la antigua superioridad de Clang. Y en cada optimización nivel GCC ahora supera Clang por 17%.

  • La capacidad de Clang en la compilación 301 para obtener más apalancamiento que GCC de la optimización -O3 se ha ido en la construcción 619. Ninguno de los compiladores gana significativamente de -O3.

Estaba lo suficientemente sorprendido por este cambio de fortuna que sospechaba que podría haber hecho accidentalmente una construcción lenta de clang 3.4 en sí (desde que construí de la fuente). Así que volví a ejecutar la prueba 619 con el Clang 3.3 de mi distribución. El los resultados fueron prácticamente los mismos que para 3.4.

Así que en cuanto a la reacción al giro en U: En los números aquí, Clang ha hecho mucho mejor que GCC a la velocidad de escurrir de mi código C++ cuando le estaba dando no ayudar. Cuando puse mi mente en ayudar, GCC hizo un trabajo mucho mejor que Clang.

No elevo esa observación a un principio, pero tomo la lección de que " ¿Qué compilador produce los mejores binarios?"es una pregunta eso, incluso si especifica el conjunto de pruebas con el que la respuesta será relativa, todavía no es una cuestión clara de solo cronometrar los binarios.

Es su mejor binario el binario más rápido, o es el que mejor ¿compensa el código barato? O mejor compensa caro ¿código diseñado que prioriza el mantenimiento y la reutilización sobre la velocidad? Depende de la naturaleza y pesos relativos de sus motivos para producir lo binario, y de las restricciones bajo las cuales lo hace.

Y en cualquier caso, si te preocupas profundamente por construir " el mejor" binarios entonces será mejor que siga comprobando cómo las iteraciones sucesivas de compiladores idea de "lo mejor" sobre iteraciones sucesivas de tu código.

 210
Author: Mike Kinghan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-22 08:00:15

Phoronix hizo algunos puntos de referencia sobre esto, pero se trata de una versión instantánea de Clang/LLVM de hace unos meses. El resultado fue que las cosas fueron más o menos un empuje; ni GCC ni Clang son definitivamente mejores en todos los casos.

Dado que usarías el último sonido, quizás sea un poco menos relevante. Por otra parte, GCC 4.6 está programado para tener algunas optimizaciones mayores para Core 2 e i7, aparentemente.

Creo que la velocidad de compilación más rápida de Clang será mejor para los desarrolladores originales, y luego cuando se empuja el código hacia fuera en el mundo, Linux distro / BSD / etc. los usuarios finales usarán GCC para los binarios más rápidos.

 44
Author: Nietzche-jou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-13 20:35:11

El hecho de que Clang compile código más rápido puede no ser tan importante como la velocidad del binario resultante. Sin embargo, aquí hay una serie de puntos de referencia.

 15
Author: mcandre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-06 15:14:31

Hay muy poca diferencia general entre GCC 4.8 y clang 3.3 en términos de velocidad del binario resultante. En la mayoría de los casos el código generado por ambos compiladores funciona de manera similar. Ninguno de estos dos compiladores domina al otro.

Los puntos de referencia que indican que hay una brecha de rendimiento significativa entre GCC y clang son coincidentes.

El rendimiento del programa se ve afectado por la elección del compilador. Si un desarrollador o un grupo de desarrolladores está utilizando exclusivamente GCC entonces se puede esperar que el programa se ejecute ligeramente más rápido con GCC que con clang, y viceversa.

Desde el punto de vista del desarrollador, una diferencia notable entre GCC 4.8+ y clang 3.3 es que GCC tiene la opción de línea de comandos -Og. Esta opción habilita optimizaciones que no interfieren con la depuración, por lo que, por ejemplo, siempre es posible obtener trazas de pila precisas. La ausencia de esta opción en clang hace que clang sea más difícil de usar como compilador de optimización para algunos desarrolladores.

 12
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-29 17:56:26

La única manera de determinar esto es probarlo. FWIW He visto algunas mejoras realmente buenas usando LLVM gcc 4.2 de Apple en comparación con el gcc 4.2 normal (para código x86-64 con bastante SSE), pero YMMV para diferentes bases de código. Suponiendo que esté trabajando con x86 / x86-64 y que realmente se preocupe por el último porcentaje, también debe probar el ICC de Intel, ya que a menudo puede vencer al gcc , puede obtener una licencia de evaluación de 30 días de intel.com y pruébalo.

 9
Author: Paul R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-06 15:11:31

Una diferencia peculiar que he observado en gcc 5.2.1 y clang 3.6.2 es que si usted tiene un bucle crítico como:

for (;;) {
    if (!visited) {
        ....
    }
    node++;
    if (!*node) break;
  }

Entonces gcc, al compilar con -O3 o -O2, especulativamente desenrollar el bucle ocho veces. Clang no lo desenrollará en absoluto. Mediante prueba y error Encontré que en mi caso específico con los datos de mi programa, la cantidad correcta de desenrollado es cinco, así que gcc se excedió y clang undershot. Sin embargo, overshotting fue más perjudicial para peformance por lo que gcc tuvo un desempeño mucho peor aqui.

No tengo idea si la diferencia de desenrollamiento es una tendencia general o algo que era específico de mi escenario.

Hace un tiempo escribí un poca basura coleccionistas para enseñarme más acerca de la optimización del rendimiento en C. Y los resultados que obtuve en mi lo suficiente como para favorecer ligeramente a Clang. Especialmente desde la basura la colección se trata principalmente de perseguir punteros y copiar memoria.

Los resultados son (números en segundos):

+---------------------+-----+-----+
|Type                 |GCC  |Clang|
+---------------------+-----+-----+
|Copying GC           |22.46|22.55|
|Copying GC, optimized|22.01|20.22|
|Mark & Sweep         | 8.72| 8.38|
|Ref Counting/Cycles  |15.14|14.49|
|Ref Counting/Plain   | 9.94| 9.32|
+---------------------+-----+-----+

Esto es todo código C puro y no hago ninguna reclamación sobre cualquiera de los compiladores rendimiento al compilar código C++.

En Ubuntu 15.10, x86.64, y un procesador AMD Phenom(tm) II X6 1090T.

 7
Author: Björn Lindqvist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-12 16:50:40

Básicamente hablando, la respuesta es: depende. Hay muchos muchos puntos de referencia que se centran en diferentes tipos de aplicación.

Mi punto de referencia en mi aplicación es: gcc > icc > clang.

Hay pocas E / s, pero muchas operaciones de flotación y estructura de datos de la CPU.

Compile flags is-Wall-g-DNDEBUG-O3.

Https://github.com/zhangyafeikimi/ml-pack/blob/master/gbdt/profile/benchmark

 4
Author: kimi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-08 12:19:24