Clang vs GCC-qui produit de meilleurs binaires? [fermé]

J'utilise actuellement GCC, mais j'ai découvert Clang récemment et je réfléchis à la commutation. Il y a cependant un facteur décisif - la qualité (vitesse, empreinte mémoire, fiabilité) des binaires qu'il produit - si gcc -O3peut produire un binaire qui s'exécute 1% plus rapidement ou prend 1% de mémoire en moins, c'est un deal-breaker.

Clang bénéficie de meilleures vitesses de compilation et d'une empreinte mémoire inférieure à celle de GCC, mais je suis vraiment intéressé par les benchmarks / comparaisons des logiciels compilés résultants - pourriez-vous pointer moi à certains ou décrire vos expériences?

204
demandé sur SF. 2010-07-06 19:01:50

7 réponses

Voici quelques résultats à jour quoique étroits avec GCC 4.7.2 et Clang 3.2 Pour C++.

Mise à jour: comparaison GCC 4.8.1 v clang 3.3 ci-dessous.

Mise à jour: GCC 4.8.2 V clang 3.4 comparaison est ajouté à cela.

Je maintiens un outil OSS qui est construit pour Linux avec GCC et Clang, et avec le compilateur de Microsoft pour Windows. L'outil, coan, est un préprocesseur et analyseur de fichiers source C / C++ et de lignes de code de tels: its majors de profil de calcul sur l'analyse de descente récursive et la gestion de fichiers. La direction du développement de ces résultats concernent) comprend actuellement environ 11K LOC dans environ 90 fichiers. Il est codé, maintenant, en C++, qui est riche en polymorphisme et modèles, mais il est encore embourbé dans de nombreux patchs par son passé pas si lointain dans hacked-together C. La sémantique de déplacement n'est pas expressément exploitée. Il est mono-thread. Je n'ont consacré aucun effort sérieux à l'optimiser, alors que "l'architecture" le reste en grande partie ToDo.

J'ai utilisé Clang avant 3.2 uniquement comme compilateur expérimental parce que, malgré sa vitesse de compilation et de diagnostic supérieure, son Le support standard C++11 a retardé la version contemporaine de GCC dans le respecte exercé par coan. Avec 3.2, cet écart a été comblé.

Mon harnais de test Linux pour les processus de développement coan actuels à peu près 70K fichiers sources dans un mélange de cas de test d'analyseur d'un fichier, stress tests consommant 1000s de fichiers et de tests de scénario consommer des fichiers time et capture et additionne les chiffres déclarés). Les horaires sont flattés par le fait que n'importe quel nombre de tests qui prennent 0 Temps mesurable sera tous ajoutent jusqu'à 0, mais la contribution de tels tests est négligeable. Le calendrier statistiques sont affichées à la fin de make check comme ceci:

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.

J'ai comparé les performances du harnais d'essai entre GCC 4.7.2 et Clang 3.2, toutes choses étant égales par ailleurs, sauf les compilateurs. À partir de clang 3.2, Je n'ai plus besoin de différenciation de préprocesseur entre le code tracts que GCC compilera et Clang alternatives. J'ai construit à l' même bibliothèque C++ (GCC) dans chaque cas et a exécuté toutes les comparaisons consécutivement dans la même session de terminal.

Le niveau d'optimisation par défaut pour ma Version release est-O2. Je également testé avec succès construit à-O3. J'ai testé chaque configuration 3 fois dos à dos et la moyenne des 3 résultats, avec les éléments suivants résultat. Le nombre dans une cellule de données est le nombre moyen de microsecondes consommées par l'exécutable coan pour traiter chacune des les fichiers d'entrée ~ 70K (lire, analyser et écrire la sortie et les diagnostics).

          | -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|

Toute application particulière est très susceptible d'avoir des traits qui jouent injustement aux forces ou aux faiblesses d'un compilateur. Analyse comparative rigoureuse employer diverses applications. Avec cela bien à l'esprit, le remarquable les caractéristiques de ces données sont:

  1. - l'optimisation O3 était marginalement préjudiciable à GCC
  2. - l'optimisation O3 a été bénéfique pour Clang
  3. optimisation à-O2, GCC était plus rapide que Clang par juste une moustache
  4. optimisation At-O3, Clang était surtout plus rapide que GCC.

Une autre comparaison intéressante des deux compilateurs émergé par hasard peu de temps après ces conclusions. Coan emploie généreusement des pointeurs intelligents et un tel est fortement exercé dans le traitement des fichiers. Ce particulier smart-pointer type avait été typedef'D dans les versions antérieures pour le bien de compilateur-différenciation, pour être un std::unique_ptr<X> si le le compilateur configuré avait un support suffisamment mature pour son utilisation comme cela, et sinon un std::shared_ptr<X>. Le biais de std::unique_ptr était stupide, puisque ces pointeurs ont été en fait transférés autour, mais std::unique_ptr ressemblait à l'option d'Ajustement pour le remplacement std::auto_ptr à un moment où les variantes C++11 étaient nouvelles pour moi.

Au cours des constructions expérimentales pour évaluer le besoin continu de Clang 3.2 pour cette différenciation et similaire, j'ai construit par inadvertance std::shared_ptr<X> quand j'avais l'intention de construire std::unique_ptr<X>, et a été surpris d'observer que l'exécutable résultant, avec défaut-O2 optimisation, était le plus rapide que j'avais vu, atteignant parfois 184 msec. par fichier d'entrée. Avec celui ci changez le code source, les résultats correspondants étaient les suivants;

          | -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 |

Le les points à noter ici sont:

  1. aucun des deux compilateurs ne bénéficie désormais de l'optimisation-O3.
  2. Clang Bat GCC tout aussi important à chaque niveau d'optimisation.
  3. les performances de GCC ne sont que marginalement affectées par le type de pointeur intelligent changement.
  4. les performances de Clang-O2 sont fortement affectées par le type de pointeur intelligent changement.

Avant et après le changement de type smart-pointer, Clang est capable de construire un Coan sensiblement plus rapide exécutable à -O3 optimisation, et il peut construire un exécutable tout aussi rapide à-O2 et-O3 quand cela pointer-type est le meilleur - std::shared_ptr<X> - pour le travail.

Une question évidente que je ne suis pas habilité à commenter est pourquoi Clang devrait être capable de trouver une vitesse de 25% -O2 dans mon application quand un type de pointeur intelligent très utilisé passe de unique à partagé, alors que GCC est indifférent au même changement. Je ne sais pas non plus si je devrais cheer ou boo la découverte que Clang's-ports d'optimisation O2 une telle sensibilité énorme à la sagesse de mes choix de pointeur intelligent.

Mise à jour: GCC 4.8.1 V clang 3.3

, Les résultats correspondants sont maintenant:

          | -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 |

Le fait que les quatre exécutables prennent maintenant un temps moyen beaucoup plus long qu'auparavant pour traiter 1 le fichier ne reflète pas les performances des derniers compilateurs. Elle est due à la fait que la branche de développement ultérieur de l'application de test a pris beaucoup de l'analyse de la sophistication en attendant et paie en vitesse. Seuls les ratios sont significatif.

Les points à noter maintenant ne sont pas étonnamment nouveaux:

  • GCC est indifférent à l'optimisation-O3
  • clang bénéficie très marginalement de l'optimisation-O3
  • clang Bat GCC par une marge tout aussi importante à chaque niveau d'optimisation.

En comparant ces résultats avec ceux de GCC 4.7.2 et clang 3.2, il ressort que GCC a griffé retour environ un quart de l'avance de clang à chaque niveau d'optimisation. Mais puisque l'application de test a été fortement développée dans l'intervalle on ne peut pas attribuez-le en toute confiance à un rattrapage dans la génération de code de GCC. (Cette fois, j'ai noté l'instantané d'application à partir duquel les timings ont été obtenus et peut l'utiliser à nouveau.)

Mise à jour: GCC 4.8.2 V clang 3.4

J'ai terminé la mise à jour pour GCC 4.8.1 V Clang 3.3 en disant que je le ferais coller à la même Coan snaphot pour d'autres mises à jour. Mais j'ai décidé au lieu de tester sur cet instantané (Rev. 301) et sur le dernier développement instantané que j'AI qui passe sa suite de tests (Rev. 619). Cela donne les résultats d'une peu de longitude, et j'avais un autre motif:

Mon message initial indiquait que je n'avais consacré aucun effort à l'optimisation du coan pour vitesse. C'était encore le cas à la rév. 301. Cependant, après avoir construit l'appareil de synchronisation dans le harnais de test coan, chaque fois que j'ai couru la suite de test le l'impact sur les performances des derniers changements m'a regardé en face. J'ai vu que il était souvent étonnamment grand et que la tendance était plus fortement négative que Je me sentais méritée par des gains de fonctionnalité.

Par rev. 308, le temps de traitement moyen par fichier d'entrée dans la suite de tests avait bien plus que doublé depuis la première publication ici. À ce point, j'ai fait un Demi-tour sur ma Politique de 10 ans de ne pas se soucier de la performance. Dans le domaine intensif série de révisions jusqu'à 619 performance a été toujours une considération et un un grand nombre d'entre eux sont allés purement à la réécriture des porteurs de charge clés sur fondamentalement lignes plus rapides (mais sans utiliser de fonctionnalités de compilateur non standard pour le faire). Il serait intéressant de voir la réaction de chaque compilateur à cela Demi-tour,

Voici la matrice de timings maintenant familière pour les versions des deux derniers compilateurs de rev. 301:

coan - rév. 301 résultats

          | -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|

L'histoire ici n'est que marginalement changée de GCC-4.8.1 et Clang-3.3. GCC montre est un peu mieux. Clang's est un peu pire. Le bruit pourrait bien tenir compte de cela. Clang sort toujours en avance par -O2 et -O3 marges qui n'auraient pas d'importance dans la plupart applications, mais importerait à un certain nombre.

Et voici la matrice pour rev.619.

coan - rév. 619 résultats

          | -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|

En prenant les chiffres 301 et 619 côte à côte, plusieurs points s'expriment.

  • Je visais pour écrire du code plus rapide, et les deux compilateurs justifient catégoriquement mes efforts. Mais:

  • GCC rembourse ces efforts beaucoup plus généreusement que Clang. À -O2 optimisation la construction 619 de Clang est 46% plus rapide que sa construction 301: à -O3 Clang l'amélioration est de 31%. Bien, mais à chaque niveau d'optimisation, la construction 619 de GCC est plus de deux fois plus vite que son 301.

  • GCC renverse plus que L'ancienne supériorité de Clang. Et à chaque optimisation niveau GCC bat maintenant Clang par 17%.

  • La capacité de Clang dans la construction 301 à obtenir plus d'effet de levier que GCC à partir de l'optimisation -O3 est parti dans la construction 619. Aucun compilateur ne gagne de manière significative à partir de -O3.

J'ai été suffisamment surpris par ce retournement de fortune que je soupçonnais pourrait avoir accidentellement fait une construction lente de clang 3.4 lui-même (depuis que j'ai construit à partir de la source). J'ai donc relancé le test 619 avec le stock de ma distribution Clang 3.3. Le les résultats sont pratiquement les mêmes que pour 3.4.

Donc, en ce qui concerne la réaction au demi-tour: sur les chiffres ici, Clang a fait beaucoup mieux que GCC à la vitesse d'essorage de mon code C++ quand je lui donnais Non aider. Quand j'ai mis mon esprit à aider, GCC a fait un bien meilleur travail que Clang.

Je n'élève pas cette observation en principe, mais je prends la leçon que " quel compilateur produit les meilleurs binaires?"est une question cela, même si vous spécifiez la suite de tests à laquelle la réponse doit être relative, n'est pas encore une question claire de juste chronométrer les binaires.

Votre meilleur binaire est-il le binaire le plus rapide, ou est-ce celui qui est le meilleur compense le code conçu à moindre coût? Ou mieux compense cher code conçu qui donne la priorité à la maintenabilité et à la réutilisation par rapport à la vitesse? Il dépend de la la nature et les poids relatifs de vos motifs pour produire le binaire, et de les contraintes sous lesquelles vous le faites.

Et en tout cas, si vous vous souciez profondément de construire "le meilleur" les fichiers binaires, alors vous mieux vaut continuer à vérifier comment les itérations successives des compilateurs livrent sur votre idée de "le meilleur" sur les itérations successives de votre code.

210
répondu Mike Kinghan 2016-11-22 08:00:15

Phoronix a fait quelques benchmarks à ce sujet, mais il s'agit d'une version instantanée de Clang/LLVM il y a quelques mois. Les résultats étant que les choses étaient plus ou moins une poussée; ni GCC ni Clang n'est définitivement meilleur dans tous les cas.

Puisque vous utiliseriez Le Dernier Clang, c'est peut-être un peu moins pertinent. Là encore, GCC 4.6 devrait avoir desoptimisations majeures pour Core 2 et i7, apparemment.

Je pense que la vitesse de compilation plus rapide de Clang sera plus agréable pour les développeurs originaux, puis lorsque vous poussez le code dans le monde, Linux distro / BSD / etc. les utilisateurs finaux utiliseront GCC pour les binaires plus rapides.

44
répondu Nietzche-jou 2010-07-13 20:35:11

Le fait que Clang compile le code plus rapidement peut ne pas être aussi important que la vitesse du binaire résultant. Cependant, voici une série de benchmarks .

15
répondu mcandre 2010-07-06 15:14:31

Il y a très peu de différence globale entre GCC 4.8 et clang 3.3 en termes de vitesse du binaire résultant. Dans la plupart des cas, le code généré par les deux compilateurs fonctionne de manière similaire. Aucun de ces deux compilateurs ne domine l'autre.

Les Benchmarks indiquant qu'il existe un écart de performance significatif entre GCC et clang sont coïncidents.

Les performances du programme sont affectées par le choix du compilateur. Si un développeur ou un groupe de développeurs utilise exclusivement GCC ensuite, on peut s'attendre à ce que le programme s'exécute légèrement plus rapidement avec GCC qu'avec clang, et vice versa.

Du point de vue du développeur, une différence notable entre GCC 4.8+ et clang 3.3 est que GCC a l'option de ligne de commande -Og. Cette option permet des optimisations qui n'interfèrent pas avec le débogage, par exemple, il est toujours possible d'obtenir des traces de pile précises. L'absence de cette option dans clang rend clang plus difficile à utiliser comme compilateur d'optimisation pour certains développeurs.

12
répondu 2013-08-29 17:56:26

La seule façon de déterminer cela est de l'essayer. FWIW j'ai vu de très bonnes améliorations en utilisant LLVM gcc 4.2 d'Apple par rapport au gcc 4.2 régulier (pour le code x86-64 avec beaucoup de SSE), mais YMMV pour différentes bases de code. En supposant que vous travaillez avec x86 / x86-64 et que vous vous souciez vraiment des derniers pour cent, alors vous devriez essayer L'ICC D'Intel aussi, car cela peut souvent battre gcc - vous pouvez obtenir une licence d'évaluation de 30 jours de intel.com et essayez-le.

9
répondu Paul R 2010-07-06 15:11:31

Une différence particulière que j'ai notée sur gcc 5.2.1 et clang 3.6.2 est que si vous avez une boucle critique comme:

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

Alors gcc, lors de la compilation avec -O3 ou -O2, spéculativement déroulez la boucle huit fois. Clang ne le déroulera pas du tout. Travers essais et erreurs j'ai trouvé que dans mon cas spécifique avec mes données de programme, la bonne quantité de déroulement est de cinq donc gcc a dépassé et clang prognathisme inférieur. Cependant, le dépassement était plus préjudiciable à peformance ainsi gcc a fait bien pire ici.

J'ai aucune idée si la différence de déroulement est une tendance générale ou juste quelque chose qui était spécifique à mon scénario.

Un temps, j'ai écrit un quelques ordures collectionneurs {[14] } pour m'enseigner plus A propos de l'optimisation des performances en C. et les résultats que j'ai obtenus sont dans mon assez d'esprit pour favoriser légèrement clang. Surtout depuis les ordures la collection concerne principalement la poursuite des pointeurs et la copie de la mémoire.

Les résultats sont (nombres en secondes):

+---------------------+-----+-----+
|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|
+---------------------+-----+-----+

Ce est - ce que tout le code C pur et je ne fais aucune réclamation sur les compilateurs performances lors de la compilation de code C++.

Sur Ubuntu 15.10, x86. 64, et un processeur AMD Phenom(tm) II X6 1090T.

7
répondu Björn Lindqvist 2016-06-12 16:50:40

Fondamentalement parlant, la réponse est: cela dépend. Il existe de nombreux benchmarks axés sur différents types d'applications.

Mon benchmark sur mon application est: gcc > icc > clang.

Il y a des E / S rares, mais de nombreuses opérations de flottement de CPU et de structure de données.

Les drapeaux de compilation sont-Wall-g-DNDEBUG-O3.

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

4
répondu kimi 2014-04-08 12:19:24