optimization - Clang vs GCC-qui produit de meilleurs binaires?




compiler-construction benchmarking (7)

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 , déroulera de façon spéculative la boucle huit fois. Clang ne le déroulera pas du tout. Par 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 gcc si dépassée et clang inférieur. Cependant, le dépassement était plus préjudiciable à la performance, donc gcc a fait beaucoup pire ici.

Je n'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.

Il y a quelque temps, j'ai écrit quelques éboueurs pour en apprendre davantage sur l'optimisation des performances en C. Et les résultats que j'ai obtenus me suffisent pour favoriser légèrement le clang. D'autant plus que la collecte des ordures est principalement à propos de la recherche de pointeur et de la copie de la mémoire.

Les résultats sont (nombre 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|
+---------------------+-----+-----+

C'est tout le code C pur et je ne prétends pas aux performances des compilateurs lors de la compilation du code C ++.

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

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

Clang possède de meilleures vitesses de compilation et une plus faible empreinte mémoire à la compilation que GCC, mais je suis vraiment intéressé par les benchmarks / comparaisons des logiciels compilés qui en résultent - pourriez-vous m'en parler ou décrire vos expériences?


Phoronix a fait quelques benchmarks à ce sujet, mais il s'agit d'une version snapshot de Clang / LLVM depuis quelques mois. Les résultats étant que les choses étaient plus ou moins une poussée; ni GCC ni Clang ne sont définitivement meilleurs 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 quelques optimisations majeures pour Core 2 et i7, apparemment.

Je pense que la rapidité de compilation de Clang sera plus agréable pour les développeurs originaux, et quand vous pousserez le code dans le monde, Linux distribuera / BSD / etc. les utilisateurs finaux utiliseront GCC pour les binaires les plus rapides.


La seule façon de déterminer cela est de l'essayer. FWIW J'ai vu de très bonnes améliorations en utilisant le LLVM gcc 4.2 d'Apple comparé au gcc 4.2 normal (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 pourcentages, vous devriez aussi essayer l'ICC d'Intel, car cela peut souvent gcc - vous pouvez obtenir une licence d'évaluation de 30 jours sur intel.com et essayez-le.


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 repères .


Il y a très peu de différence globale entre GCC 4.8 et 3.3 en termes de vitesse du binaire résultant. Dans la plupart des cas, le code généré par les deux compilateurs est 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 une coïncidence.

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, le programme devrait fonctionner 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 le clang plus difficile à utiliser comme un compilateur optimisant pour certains développeurs.


En gros, la réponse est: ça dépend. Il y a beaucoup de points de repère se concentrant sur différents types d'application.

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

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

compiler flags est -Wall -g -DNDEBUG -O3.

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


Si vous êtes certain que la source_references.key identifie les enregistrements en double, vous pouvez assurer un index unique avec l' dropDups:true index creation dans MongoDB 2.6 ou plus ancienne:

db.things.ensureIndex({'source_references.key' : 1}, {unique : true, dropDups : true})

Cela conservera le premier document unique pour chaque valeur source_references.key et supprimera tous les documents ultérieurs qui entraîneraient une violation de clé en double.

Notes importantes :

  • L'option dropDups été supprimée dans MongoDB 3.0 , donc une approche différente sera nécessaire. Par exemple, vous pouvez utiliser l'agrégation comme suggéré sur: MongoDB dupliquer des documents même après avoir ajouté une clé unique .
  • Tout document manquant le champ source_references.key sera considéré comme ayant une valeur nulle , de sorte que les documents suivants manquant le champ clé seront supprimés. Vous pouvez ajouter l'option de création d'index sparse:true afin que l'index ne s'applique qu'aux documents avec un champ source_references.key .

Avertissement évident : effectuez une sauvegarde de votre base de données, et essayez d'abord cela dans un environnement intermédiaire si vous êtes préoccupé par la perte de données involontaire.





optimization gcc compiler-construction clang benchmarking