Clang vs GCC - który produkuje lepsze binaria? [zamknięte]

Obecnie używam GCC, ale niedawno odkryłem Clang i zastanawiam się nad przełączeniem. Jest jednak jeden decydujący czynnik-jakość (szybkość, ślad pamięci, niezawodność) wytwarzanych przez siebie plików binarnych-jeśli gcc -O3 może wytworzyć plik binarny, który działa o 1% szybciej lub zajmuje o 1% mniej pamięci,jest to przełom.

Clang może pochwalić się lepszą prędkością kompilacji i niższym zużyciem pamięci w czasie kompilacji niż GCC, ale naprawdę interesują mnie benchmarki / porównania wynikowego skompilowanego oprogramowania - czy mógłbyś wskazać mnie do niektórych lub opisać swoje doświadczenia?

Author: SF., 2010-07-06

7 answers

Oto kilka aktualnych, choć wąskich ustaleń z GCC 4.7.2 oraz Clang 3.2 Dla C++.

Aktualizacja: GCC 4.8.1 V clang 3.3 porównanie załączone poniżej.

Aktualizacja: GCC 4.8.2 V clang 3.4 porównanie jest dołączony do tego.

Utrzymuję narzędzie OSS, które jest zbudowane dla Linuksa z GCC i Clang, oraz z kompilatorem Microsoftu dla Windows. Narzędzie, coan, jest preprocesorem oraz analizator plików źródłowych C / C++ i kodów takich jak: its profil obliczeniowy zajmuje się rekurencyjnym parsowaniem i obsługą plików. Gałąź rozwoju (do której odnoszą się te wyniki) obejmuje obecnie około 11K LOC w około 90 plikach. Jest zakodowany, teraz, w C++, który jest bogaty w polimorfizm i szablony, a jednak jest pogrążony w wielu łatkach przez swoją nie tak odległą przeszłość w hacked-together C. Semantyka ruchu nie jest wyraźnie wykorzystywana. Jest jednowątkowy. I nie poświęcili żadnego poważnego wysiłku na jego optymalizację, podczas gdy " architektura" pozostaje tak w dużej mierze ToDo.

Używałem Clang przed 3.2 tylko jako kompilator eksperymentalny ponieważ, pomimo doskonałej szybkości kompilacji i diagnostyki, jego Obsługa standardu C++11 opóźniła współczesną wersję GCC w szanuje coan. W przypadku 3.2 luka ta została zamknięta.

Mój test Linuksa dla obecnych procesów rozwoju coan mniej więcej 70K plików źródłowych w mieszaninie testów parsera jednego pliku-przypadki, stres testy zużywające 1000 plików i testy scenariuszy używanie plików time i przechwytuje i sumuje zgłoszone liczby). Czasy schlebiają przez fakt, że dowolna liczba testów, które zajmują 0 mierzalnych czasu, będzie wszystkie sumują się do 0, ale udział takich testów jest znikomy. Na statystyki czasu są wyświetlane na końcu make check tak:

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.

Porównałem wydajność uprzęży testowej z GCC 4.7.2 i Clang 3.2, wszystkie rzeczy są równe z wyjątkiem kompilatorów. Od Clang 3.2, Nie wymagam już różnicowania preprocesora pomiędzy kodem tracts, że GCC będzie kompilować i Clang alternatywy. Zbudowałem do tej samej biblioteki C++ (GCC) w każdym przypadku i wszystkie porównania kolejno w tej samej sesji terminala.

Domyślnym poziomem optymalizacji dla mojej kompilacji wydania jest -O2. I również pomyślnie przetestowane build at-O3. Przetestowałem każdą konfigurację 3 razy Wstecz i średnio 3 wyniki, z następującymi wyniki. Liczba w komórce danych jest średnią liczbą mikrosekundy zużywane przez program wykonywalny coan do przetwarzania każdego z pliki wejściowe ~70k (odczyt, analiza i zapis danych wyjściowych oraz diagnostyka).

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

Każda konkretna aplikacja jest bardzo prawdopodobne, aby mieć cechy, które odgrywają niesłusznie wobec mocnych lub słabych stron kompilatora. Rygorystyczne benchmarking zatrudnia różnorodne zastosowania. Mając to na uwadze, godne uwagi cechy tych danych to:

  1. -optymalizacja O3 była marginalnie szkodliwa dla GCC
  2. -optymalizacja O3 była bardzo korzystna dla Clang
  3. GCC był szybszy niż Clang tylko o Wąsik.]}
  4. optymalizacja At-O3, Clang był znacznie szybszy niż GCC.

Kolejne ciekawe porównanie dwóch kompilatorów pojawiło się przypadkiem krótko po tych ustaleniach. Coan wykorzystuje inteligentne wskaźniki i jeden z nich jest mocno ćwiczony w obsłudze plików. Ten szczególny smart-pointer type był pisany we wcześniejszych wydaniach w celu kompilator-różnicowanie, być std::unique_ptr<X> jeśli skonfigurowany kompilator miał wystarczająco dojrzałe wsparcie dla jego użycia jako to, a poza tym std::shared_ptr<X>. Tendencja do std::unique_ptr była głupoty, ponieważ te wskazówki były faktycznie przenoszone wokół, ale std::unique_ptr wyglądał jak opcja monter do wymiany std::auto_ptr w momencie, gdy warianty C++11 były dla mnie nowatorskie.

W trakcie eksperymentalnych kompilacji, aby ocenić dalsze potrzeby Clang 3.2 dla tego i podobnego zróżnicowania nieumyślnie zbudowałem std::shared_ptr<X> kiedy zamierzałem zbudować std::unique_ptr<X>, i był zaskoczony, aby zauważyć, że wynikający wykonywalny, z domyślnym -O2 optymalizacja, była najszybsza jaką widziałem, czasami osiągając 184 msecs. na plik wejściowy. Z tą jedną zmianą kodu źródłowego, odpowiednie wyniki były takie;

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

The punkty uwagi to:

  1. żaden kompilator nie korzysta teraz z optymalizacji-O3.
  2. Clang bije GCC równie ważne na każdym poziomie optymalizacji.
  3. na wydajność GCC ma tylko niewielki wpływ Typ inteligentnego wskaźnika zmiana.
  4. Na wydajność clanga-O2 ma istotny wpływ Typ inteligentnego wskaźnika zmiana.

Przed i po zmianie typu smart-pointera, Clang jest w stanie zbudować znacznie szybszy coan wykonywalnej optymalizacji at-O3 i może zbudować równie szybszy program wykonywalny W -O2 i-O3, gdy wskaźnik-typ jest najlepszy - std::shared_ptr<X> - dla zadania.

Oczywistym pytaniem, którego nie jestem kompetentny do komentowania jest dlaczego Clang powinien być w stanie znaleźć 25% -O2 speed-up w mojej aplikacji, gdy często używany typ inteligentnego wskaźnika jest zmieniany z unikalnego na współdzielony, podczas gdy GCC jest obojętny na tę samą zmianę. Nie wiem też, czy powinienem cheer or boo the discovery that Optymalizacja Clang-O2 taka ogromna wrażliwość na mądrość moich mądrych wyborów.

Aktualizacja: GCC 4.8.1 v clang 3.3

Odpowiednie wyniki są teraz:

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

Fakt, że wszystkie cztery pliki wykonywalne zajmują teraz znacznie większy średni czas niż wcześniej, aby przetworzyć 1 plik Nie odzwierciedla wydajność najnowszych kompilatorów. Jest to spowodowane fakt, że późniejsza gałąź rozwojowa aplikacji testowej przyjęła na lot z w międzyczasie analizuje wyrafinowanie i płaci za to z szybkością. Tylko współczynniki są znaczące.

Uwaga teraz nie jest zbyt nowatorska:

  • GCC jest obojętne na optymalizację-O3
  • clang korzysta bardzo marginalnie z optymalizacji-O3
  • clang bije GCC o podobnie ważny margines na każdym poziomie optymalizacji.

Porównując te wyniki z wynikami dla GCC 4.7.2 i clang 3.2, wyróżnia się, że GCC ma pazury powrót około jednej czwartej przewagi clang na każdym poziomie optymalizacji. Ale ponieważ aplikacja testowa została w międzyczasie mocno rozwinięta, nie można śmiało przypisuj to do nadrobienia w generowaniu kodu GCC. (Tym razem odnotowałem migawkę aplikacji, z której uzyskano timingi i może użyć go ponownie.)

Aktualizacja: GCC 4.8.2 v clang 3.4

Zakończyłem aktualizację dla GCC 4.8.1 v Clang 3.3 mówiąc, że będę przyklej do tego samego Coan snaphot dla dalsze aktualizacje. Ale zdecydowałem zamiast tego przetestować na tym migawce (Rev. 301) i na najnowszym rozwoju migawka, którą mam, przechodzi swój zestaw testowy (Rev. 619). Daje to wyniki trochę długości i miałem inny motyw:

Mój oryginalny post zauważył, że nie poświęciłem żadnego wysiłku na optymalizację coan dla speed. Tak było do dnia 301 r. Jednak po zbudowaniu aparatura do pomiaru czasu w uprzęży testowej coan, za każdym razem, gdy uruchamiałem zestaw testowy na wpływ najnowszych zmian wpatrywał się we mnie w twarz. Widziałem to. był często zaskakująco duży i że trend był bardziej negatywny niż Czułem, że zasługuję na zyski w funkcjonalności.

Do wersji 308 średni czas przetwarzania na plik wejściowy w zestawie testowym miał cóż więcej niż dwukrotnie od pierwszego postu tutaj. W tym momencie zrobiłem Włącz moją 10-letnią Politykę nie zawracania sobie głowy wydajnością. W intensywnym liczba poprawek do 619 było zawsze uwagę i duża ich liczba poszła wyłącznie do przepisywania kluczowych obciążników na zasadniczo szybsze linie (choć bez użycia w tym celu niestandardowych funkcji kompilatora). Ciekawie byłoby zobaczyć reakcję każdego kompilatora na to U-turn,

Oto znana macierz czasu dla dwóch ostatnich kompilatorów wersji 301:

coan-301 wyników

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

Historia tutaj jest tylko nieznacznie zmieniona od GCC-4.8.1 i Clang-3.3. Pokaz GCC jest trochę lepszy. Clang jest trochę gorszy. Hałas może to tłumaczyć. Clang nadal wychodzi przed -O2 i -O3 marginesy, które nie mają znaczenia w większości aplikacji, ale ma znaczenie dla wielu.

A oto macierz dla Rev. 619.

coan-znaleziono 619 wyników

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

Biorąc 301 i 619 cyfr obok siebie, kilka punktów przemawia.

  • Celowałem aby napisać szybszy kod, a oba Kompilatory dobitnie moje wysiłki. Ale:

  • GCC odwdzięcza się tym wysiłkom znacznie hojniej niż Clang. At -O2 optimization clang 's 619 Build jest o 46% szybszy niż jego 301 build: at -O3 Clang' s poprawa wynosi 31%. Dobry, ale na każdym poziomie optymalizacji GCC 619 build jest ponad dwa razy szybciej niż jego 301.

  • GCC bardziej niż odwraca poprzednią wyższość clanga. I przy każdej optymalizacji poziom GCC teraz bije Clang przez 17%.

  • Clang w kompilacji 301 może uzyskać większą dźwignię niż GCC z optymalizacji -O3 zniknął w 619. Żaden kompilator nie zyskuje sensownie na -O3.

Byłem wystarczająco zaskoczony tym odwróceniem losu, że podejrzewałem mógł przypadkowo zrobić słabą kompilację samego clang 3.4 (ponieważ zbudowałem źródło). Więc ponownie uruchomiłem test 619 z moim distro stock Clang 3.3. Na wyniki były praktycznie takie same jak dla 3.4.

Więc jeśli chodzi o reakcję na U-turn: na liczbach tutaj, Clang zrobił wiele lepsze niż GCC przy wyciskaniu prędkości z mojego kodu C++ kiedy go dawałem nie pomocy. Kiedy skupiłem się na pomaganiu, GCC wykonało znacznie lepszą pracę niż Clang.

Nie podniosę tej obserwacji do zasady, ale biorę lekcja, że " który kompilator produkuje lepsze binaria?"is a question że, nawet jeśli określisz zestaw testów, na które odpowiedź ma być względna, nadal nie jest to kwestia wyczucia czasu na binaria.

Czy twój lepszy binarny jest najszybszym binarnym, czy też tym, który najlepszy rekompensuje tanio wykonany kod? Lub najlepiej zrekompensować kosztownie spreparowany kod, który priorytetyzuje Konserwację i ponowne użycie nad prędkością? To zależy od Natury i względnej wagi waszych motywów do produkcji binarnej, a z ograniczenia, pod którymi to robisz.

I w każdym razie, jeśli głęboko zależy ci na budowaniu " najlepszych" binaries then you lepiej sprawdzaj, jak kolejne iteracje kompilatorów dostarczają na Twoim idea "najlepszego" nad kolejnymi iteracjami Twojego kodu.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-22 08:00:15

Phoronix zrobił kilka benchmarków na ten temat, ale chodzi o migawkową wersję Clang / LLVM sprzed kilku miesięcy. Wyniki są takie, że rzeczy były bardziej lub mniej push; ani GCC ani Clang jest definitywnie lepszy we wszystkich przypadkach.

Skoro używasz najnowszego Clang, to może jest trochę mniej istotne. Z drugiej strony, GCC 4.6 ma mieć kilka głównych optymalizacji dla Core 2 i i7, najwyraźniej.

Myślę, że szybsza kompilacja clanga będzie ładniejsza dla oryginalnych programistów, a po wypchnięciu kodu w świat, Linux distro/BSD / etc. użytkownicy końcowi będą używać GCC dla szybszych plików binarnych.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-13 20:35:11

Fakt, że Clang kompiluje kod szybciej, może nie być tak ważny, jak szybkość wynikowego pliku binarnego. Jednak Oto Seria benchmarków .

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-06 15:14:31

Istnieje bardzo mała ogólna różnica pomiędzy GCC 4.8 i clang 3.3 pod względem prędkości wynikowej binary. W większości przypadków kod generowany przez oba Kompilatory działa podobnie. Żaden z tych dwóch kompilatorów nie dominuje nad drugim.

Benchmarki wskazujące, że istnieje znaczna różnica w wydajności między GCC a clang, są przypadkowe.

Na wydajność programu ma wpływ wybór kompilatora. Jeśli programista lub grupa programistów korzysta wyłącznie z GCC wtedy można oczekiwać, że program będzie działał nieco szybciej z GCC niż z clang i vice versa.

Z punktu widzenia dewelopera, znacząca różnica między GCC 4.8+ A clang 3.3 jest taka, że GCC ma opcję linii poleceń -Og. Ta opcja umożliwia optymalizacje, które nie zakłócają debugowania, więc na przykład zawsze możliwe jest uzyskanie dokładnych śladów stosu. Brak tej opcji w clang sprawia, że clang jest trudniejszy do wykorzystania jako kompilator optymalizujący dla niektórych programistów.

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

Jedyny sposób, aby to ustalić, to spróbować. FWIW widziałem kilka naprawdę dobrych ulepszeń za pomocą Apple LLVM gcc 4.2 w porównaniu do zwykłego gcc 4.2 (Dla kodu x86-64 z dość dużą ilością SSE), ale YMMV dla różnych baz kodu. Zakładając, że pracujesz z x86/x86-64 i że naprawdę zależy ci na ostatnich kilku procentach, powinieneś wypróbować ICC Intela, ponieważ często może to pokonać gcc - możesz uzyskać 30-dniową licencję evaluation od intel.com i spróbuj.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-06 15:11:31

Osobliwą różnicą, jaką zauważyłem na gcc 5.2.1 i clang 3.6.2 jest że jeśli masz pętlę krytyczną jak:

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

Wtedy gcc, przy kompilacji z -O3 lub -O2, spekulacyjnie rozwiń pętlę osiem razy. Clang w ogóle tego nie rozwiąże. Przez metodą prób i błędów odkryłem, że w moim konkretnym przypadku z danymi mojego programu, odpowiednia ilość rozwinięcia to pięć, więc gcc przekroczył i clang / align = "left" / Jednak przekroczenie było bardziej szkodliwe dla peformance, więc gcc wypadło znacznie gorzej proszę.

Mam nie mam pojęcia czy różnica rozwinięcia jest ogólnym trendem lub coś, co było specyficzne dla mojego scenariusza.

Jakiś czas temu napisałem kilka śmieci kolekcjonerzy aby nauczyć się więcej o optymalizacji wydajności w C. a wyniki jakie uzyskałem są w moim umysł na tyle, aby nieco faworyzować clang. Zwłaszcza, że śmieci kolekcja polega głównie na ściganiu wskaźników i kopiowaniu pamięci.

Wyniki są (liczby w sekundach):

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

To jest czystym kodem C i nie roszczę sobie żadnych roszczeń co do kompilatorów wydajność przy kompilacji kodu C++.

Na Ubuntu 15.10, x86. 64 i procesor 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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-12 16:50:40

Zasadniczo, odpowiedź brzmi: to zależy. Istnieje wiele wielu benchmarków skupiających się na różnych rodzajach aplikacji.

Mój benchmark w mojej aplikacji to: gcc > icc > clang.

Istnieją rzadkie IO, ale wiele operacji float procesora i struktury danych.

Flagi kompilacji to-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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-08 12:19:24