GCC vs. Clang/LLVM: An In-Depth Comparison of C/C++ Compilers

Visual C++, GNU Compiler Collection (GCC), and Clang/Low Level Virtual Machine (LLVM) are three mainstream C/C++ compilers in the industry. Visual C++ zapewnia graficzne interfejsy użytkownika (GUI) i jest łatwy do debugowania, ale nie jest odpowiedni dla platform Linuksowych. Dlatego dokument ten porównuje głównie GCC z Clang / LLVM.

GCC jest kompilatorem języka programowania opracowanym przez GNU. Jest to zbiór wolnego oprogramowania wydany na licencji GNU General Public License (GPL) oraz GNU Lesser General Public License (LGPL). Jest oficjalnym kompilatorem dla systemów GNU i Linux oraz głównym kompilatorem do kompilacji i tworzenia innych systemów operacyjnych UNIX.

LLVM zawiera szereg modularnych komponentów kompilatora i łańcuchów narzędzi. Może optymalizować języki programów i linki podczas kompilacji, wykonywania i bezczynności oraz generować kod. LLVM może służyć jako tło dla kompilatorów w wielu językach. Clang jest kompilatorem C, C++, Objective-C lub Objective-C++, który został skompilowany w C++ w oparciu o LLVM i wydany na licencji Apache 2.0. Clang jest używany głównie do zapewnienia wydajności wyższej niż GCC.

poprzez długoterminowy rozwój i iterację, GCC, Clang i LLVM stały się dojrzałymi kompilatorami w branży. Więc który kompilator jest lepszy? Którego z nich powinniśmy używać do kompilowania i budowania programów i systemów?

znaczenie dobrego kompilatora

nowoczesne procesory mają superscalar i długie potoki oraz złożone struktury wewnętrzne i wspierają jednostki rozszerzeń wektorowych w architekturze Complex Instruction Set Computer (CISC) lub Reduced Instruction Set Computer (RISC). W przypadku wielu programów, które zawierają jądra o dużej intensywności obliczeniowej, programiści mogą używać poleceń rozszerzeń wektorowych, aby znacznie poprawić wydajność wykonywania programu. Na przykład, w operacjach na macierzach i wektorach, kombinowane polecenia mnożenia i dodawania są używane do poprawy wydajności i dokładności. Polecenia maski bitowej są używane do przetwarzania gałęzi w operacjach wektorowych. Jednak aby osiągnąć najwyższą wydajność, Programiści i kompilatory nadal muszą włożyć wiele wysiłku w obsługę zadań ze złożonymi trybami dostępu do pamięci i niestandardowymi jądrami.

dodatkowo, standardy nowoczesnych zaawansowanych języków stale abstrakcyjne szczegóły bazowych struktur sprzętowych i danych do generowania ogólnego kodu, który jest bardziej logiczny i matematyczny, zamiast konkretnych instrukcji operacyjnych i ścieżek dostępu do pamięci. Standardy C++ są coraz bardziej ekspresyjne i abstrakcyjne. Python jest popularny, ponieważ jest bardziej czytelny i wyrazisty, nawet kosztem mniejszej prędkości pracy. Wyższa ekspresja zwiększa obciążenie kompilatora do generowania dobrego kodu asemblera ze złożonych struktur skompilowanych przez programistów. Kompilator musi być mądrzejszy i pracować ciężej, aby zmaksymalizować wydajność przy użyciu kodu. Nie wszystkie Kompilatory mogą to zrobić. Wybierając kompilator, musimy najpierw zastanowić się, czy ten sam segment kodu może generować wydajniejsze polecenia assembly.

oprócz generowania wysokowydajnych programów wykonywalnych, nowoczesne Kompilatory muszą również mieć wysoką wydajność. Duży projekt oprogramowania w C++ może zawierać setki do tysięcy pojedynczych jednostek tłumaczeniowych. Każda jednostka tłumaczenia może zawierać tysiące linii kodu. Kod C++ może również korzystać z wielu technologii programowania opartych na szablonach. Technologie te wymagają od kompilatora wielokrotnego przesyłania istotnych informacji w celu wygenerowania pliku docelowego. Kompilacja wielkogabarytowych projektów C++ może potrwać kilka godzin, a wiele wzajemnie zależnych zmian musi być zgłaszanych jednocześnie podczas tworzenia. Każde zgłoszenie wymaga od programistów przekompilowania większości bibliotek kodu. Dlatego szybsze Kompilatory (narzędzia do budowania) mają kluczowe znaczenie dla osiągnięcia wysokiej wydajności dla dużych zespołów.

jeśli chodzi o rozszerzenie języka, nowoczesne systemy obliczeniowe z wieloma jądrami, możliwościami przetwarzania wektorowego i akceleratorami zapewniają możliwości przewyższające naturalne możliwości popularnych języków programowania. Dlatego specyficzne ramy obliczeniowe o wysokiej wydajności (HPC), takie jak OpenMP i OpenACC, mogą wypełnić tę lukę. Frameworki te zapewniają interfejsy aplikacji (API), których programiści mogą używać do wyrażania równoległości w kodzie. Kompilator i odpowiednia biblioteka uruchomieniowa muszą odwzorować kod równoległy na architekturę procesora. Wiele projektów HPC opiera się na standardach OpenMP i OpenACC, które są rozszerzane przez programistów i producentów sprzętu. Dlatego Kompilatory muszą nadążać za rozwojem standardów rozszerzeń języka.

podsumowując, dobry kompilator pozwala nam skupić się na procesie programowania, zamiast walczyć z jego wadami. Może obsługiwać najnowsze standardy językowe, generować zoptymalizowane polecenia z najbardziej abstrakcyjnego kodu i kompilować kod źródłowy w krótszym czasie.

historia rozwoju GCC

zanim nauczysz się GCC, musisz najpierw zrozumieć projekt GNU. Richard Stallman uruchomił projekt GNU w 1984 roku w celu zbudowania UNIKSOPODOBNEGO systemu oprogramowania open source. System operacyjny GNU nie ewoluował w znacznym stopniu z biegiem czasu. Jednak, to inkubuje wiele doskonałych i użytecznych narzędzi open source, takich jak Make, Sed, Emacs, Glibc, GDB i GCC, jak również. Te otwarte oprogramowanie GNU i jądra Linuksa razem tworzą system GNU / Linux. Na początku GCC dostarczało stabilne i niezawodne Kompilatory, oparte na języku programowania C,dla systemu GNU. Jego pełna nazwa to GNU C Compiler. Później wspierano więcej języków (takich jak Fortran, Obj-C i Ada), a pełna nazwa GCC została zmieniona na GNU Compiler Collection.

GCC-1.0 został wydany przez Richarda Stallmana w 1987 roku, ponad trzydzieści lat temu. Z punktu widzenia oprogramowania jest bardzo stary. Ktoś zebrał zapisy rozwojowe GCC z lat 1989-2012 i wyprodukował trzydziestominutowy Film animowany (GNU Compiler Collection dev history 1989-2012), intuicyjnie demonstrując proces rozwoju GCC. O historii rozwoju GCC możemy dowiedzieć się z jego wersji:

  • GCC-1.0: wydany przez Richarda Stallmana w 1987 roku.
  • GCC-2.0: wydany w 1992 roku i obsługiwany przez C++. Później społeczność GCC została podzielona, ponieważ Richard Stallman zdefiniował GCC jako niezawodny kompilator C systemu GNU i uważał, że GCC w tym czasie było wystarczające dla systemu GNU, a nacisk na rozwój powinien zostać przesunięty z GCC na sam system GNU. Inni główni deweloperzy mieli nadzieję na dalsze ulepszanie GCC i Dokonywanie bardziej radykalnych zmian i ulepszeń w różnych aspektach. Ci aktywni Programiści opuścili społeczność GCC w 1997 roku i stworzyli fork EGCS.
  • GCC-3.0: oczywiście Programiści na ogół mieli silne pragnienie dobrych kompilatorów. Widelec EGCS rozwijał się płynnie i zyskał uznanie coraz większej liczby programistów. Ostatecznie EGCS został użyty jako nowy szkielet GCC, a GCC-3.0 został wydany w 2001 roku. Rozłam wspólnoty został ponownie połączony, ale wpływy Richarda Stallmana zostały do pewnego stopnia osłabione. Ponadto Komitet przemysłowy GCC zaczął decydować o kierunku rozwoju GCC.
  • GCC-4.0: wydany w 2005 roku. Wersja ta została zintegrowana z architekturą drzewiastej pamięci szeregowej (SSA), a GCC ewoluowała do roli nowoczesnego kompilatora.
  • GCC-5.0: wydany w 2015 roku. Później Polityka wersji GCC została dostosowana i co roku wydawana była główna wersja. Nieoczekiwaną korzyścią jest to, że Numer wersji odpowiada rokowi. Na przykład GCC-7 został wydany w 2017 roku, a GCC-9 został wydany w 2019 roku.

teraz rozwój GCC wszedł do „nowoczesnej kroniki”. W obliczu presji konkurencyjnej LLVM, społeczność GCC aktywnie wprowadziła wiele zmian, takich jak przyspieszanie kompilacji i ulepszanie informacji ostrzegawczych o kompilacji. W ciągu ostatnich 30 lat GCC ewoluowało od konkurenta w branży kompilatorów do głównego nurtu kompilatora dla Systemów Linux, a teraz stoi przed wyzwaniem LLVM. Na szczęście społeczność GCC wprowadza poprawki, aby przyspieszyć rozwój GCC. Możemy się spodziewać, że konkurencja pomiędzy obiema technologiami kompilacji będzie nadal zapewniać programistom lepsze Kompilatory.

historia rozwoju Clang i LLVM

LLVM pochodzi z badań Chrisa Lattnera nad UUIC w 2000 roku. Chris Lattner chciał stworzyć dynamiczną technologię kompilacji dla wszystkich języków statycznych i dynamicznych. LLVM to rodzaj oprogramowania open source rozwijanego na licencji BSD. Pierwsza wersja 1.0 została wydana w 2003 roku. W 2005 Roku Apple Inc. zatrudnił Chrisa Lattnera i jego zespół do opracowania języków programowania i kompilatorów dla komputerów Apple, po czym rozwój LLVM wszedł na szybki tor. Począwszy od LLVM 2.5, co roku wydawano dwie mniejsze wersje LLVM (zazwyczaj w marcu i wrześniu). W listopadzie 2011 roku LLVM 3.0 został wydany jako domyślny kompilator XCode. XCode 5 zaczął używać clang i LLVM 5.0 domyślnie. Polityka wersji została dostosowana do LLVM 5.0 i późniejszych wersji, a co roku wydawane są dwie główne wersje. Aktualna stabilna wersja to 8.0.

nazwa LLVM została po raz pierwszy skrócona od maszyny Wirtualnej niskiego poziomu. Ponieważ projekt ten nie ogranicza się do stworzenia maszyny wirtualnej, Skrót LLVM jest często kwestionowany. Po opracowaniu LLVM stało się zbiorczym terminem dla wielu narzędzi kompilacyjnych i niskopoziomowych technologii narzędziowych, przez co nazwa ta stała się mniej odpowiednia. Deweloperzy postanowili porzucić znaczenie tego skrótu. Teraz LLVM stał się oficjalną marką, mającą zastosowanie do wszystkich projektów w ramach LLVM, w tym LLVM Intermediate Representation (LLVM IR), LLVM debugging tools i LLVM C++ standard libraries. LLVM może być używany jako tradycyjny kompilator, kompilator JIT, asembler, debugger, narzędzie do analizy statycznej i inne funkcje związane z językami programowania.

w 2012 roku LLVM zdobył nagrodę software system award of Association for Computing Machinery (ACM), wraz z tradycyjnymi systemami, takimi jak UNIX, WWW, TCP/IP, TeX i Java. LLVM znacznie upraszcza implementację nowych łańcuchów narzędzi języka programowania. W ostatnich latach wiele nowych języków programowania, takich jak Swift, Rust i Julia, używało LLVM jako struktury kompilacji. Dodatkowo LLVM stał się domyślnym kompilatorem dla Systemów Mac OS X, iOS, FreeBSD i Android.

Clang

Clang jest zaprojektowany, aby zapewnić kompilator frontend, który może zastąpić GCC. Apple Inc. (w tym następny później) używa GCC jako oficjalnego kompilatora. GCC zawsze dobrze radził sobie jako standardowy kompilator w społeczności open source. Jednak Apple Inc. ma własne wymagania dotyczące narzędzi kompilacyjnych. Z jednej strony Apple Inc. dodano wiele nowych funkcji dla języka Objective-C (a nawet później języka C). Jednak programiści GCC nie zaakceptowali tych funkcji i przypisali niski priorytet obsłudze tych funkcji. Później zostały one po prostu podzielone na dwie gałęzie dla oddzielnego rozwoju, a w konsekwencji wersja GCC wydana przez Apple Inc. jest znacznie wcześniejsza niż wersja oficjalna. Z drugiej strony, Kod GCC jest wysoce sprzężony i trudny do rozwinięcia osobno. Ponadto w późniejszych wersjach jakość kodu nadal spada. Jednak wiele funkcji wymaganych przez Apple Inc. (takie jak ulepszona obsługa zintegrowanego środowiska programistycznego (IDE)) musi wywoływać GCC jako moduł, ale GCC nigdy nie zapewnia takiego wsparcia. Co więcej, wyłączenie Biblioteki uruchomieniowej GCC zasadniczo ogranicza rozwój LLVM GCC. Również ograniczona przez licencję, Apple Inc. nie można używać LLVM do dalszej poprawy jakości generowania kodu w oparciu o GCC. W Związku Z Tym Apple Inc. postanowiłem napisać od podstaw Klan frontendowy języków C, C++ i Objective-C, aby całkowicie zastąpić GCC.

jak sama nazwa wskazuje, Clang obsługuje tylko C, C++ i Objective-C. rozwój rozpoczął się w 2007 roku, a kompilator C został po raz pierwszy ukończony. Clang dla Objective-C cloud być w pełni wykorzystane w środowisku produkcyjnym w 2009 roku. Wsparcie dla C++ również postępuje szybko. Clang 3.3 w pełni obsługiwał C++ 11, Clang 3.4 w pełni obsługiwał C++ 14, A Clang 5 w pełni obsługiwał C++ 17, i wszystkie były znacznie wyprzedzające GCC w tym czasie.

Clang/LLVM i społeczność GCC

podobnie jak inne społeczności oprogramowania open source, społeczność GCC jest zdominowana przez entuzjastów wolnego oprogramowania i hakerów. W procesie rozwoju, zarządzanie społecznością GCC i mechanizmy uczestnictwa są stopniowo tworzone dzisiaj. Obecnie społeczność GCC jest stosunkowo stabilnym i dobrze zdefiniowanym społeczeństwem, w którym każda osoba ma jasne role i obowiązki:

  • Richard Stallman i Free Software Foundation (FSF): chociaż rzadko angażują się w zarządzanie społecznością GCC, Richard Stallman i FSF nadal są niezwiązani w sprawach licencyjnych i prawnych.
  • Komitet Przemysłowy GCC: Zarządza sprawami społeczności GCC, tematami rozwoju GCC niezależnymi od technologii oraz powoływaniem i ogłaszaniem recenzentów i opiekunów. Obecnie liczy 13 członków.
  • globalni opiekunowie: zdominowali działania rozwojowe GCC. W pewnym stopniu determinują one trend rozwojowy GCC. Obecnie istnieje 13 globalnych opiekunów, którzy nie wszyscy pełnią funkcje w Komitecie przemysłowym GCC.
  • opiekunowie Frontend, middle-end i backend: są opiekunami frontend, backend i innych modułów. Są one odpowiedzialne za Kod odpowiedniego modułu GCC, a wielu z nich jest Głównymi współtwórcami kodu modułu. Warto zauważyć, że recenzenci są zazwyczaj klasyfikowani do tej grupy. Różnica polega na tym, że recenzenci nie mogą zatwierdzić własnej poprawki, podczas gdy opiekunowie mogą zgłaszać własne modyfikacje w ramach swojej odpowiedzialności bez zgody recenzentów.
  • Contributors: są to najszersze grupy programistów w społeczności GCC. Po podpisaniu umowy o prawach autorskich, Każdy programista może ubiegać się o pozwolenie na zapis po zatwierdzeniu przez społeczność, a następnie przesłać kod samodzielnie.

podobnie jak inne społeczności open source, Dojrzała społeczność GCC nie jest już zdominowana przez hakerów. Firmy komercyjne zaczęły odgrywać ważną rolę w społeczności, jak rekrutacja deweloperów i sponsorowanie spotkań deweloperskich. Obecnie społeczność GCC jest zdominowana przez następujące rodzaje spółek handlowych:

  • dostawcy systemów, głównie RedHat i SUSE.
  • producenci chipów, w tym głównie Intel, ARM, AMD i IBM (PowerPC).
  • wyspecjalizowani dostawcy, tacy jak CodeSourcery i dostawcy usług łańcucha narzędzi, tacy jak AdaCore, bazujący na języku Ada. CodeSourcery miał wspaniałą historię i rekrutował wielu znanych programistów, ale odmówił po tym, jak został przejęty przez mentora.

w obecnej społeczności GCC dostawcy chipów dominują nad rozwojem backendów, podczas gdy dostawcy systemów kierują innymi obszarami rozwoju. Jeśli chodzi o rozwój społeczności, kod GCC jest obecnie hostowany na własnym serwerze SVN. Git API jest dostarczany w celu ułatwienia tworzenia i przesyłania. Patch review jest podobny do tego w społeczności jądra Linuksa i używa formularza listy dyskusyjnej. Jak wspomniano powyżej, społeczność GCC jest stosunkowo stabilnym (lub zamkniętym) społeczeństwem znajomości. Społeczność ma od 150 do 200 aktywnych współpracowników każdego roku i organizuje konferencję dla programistów we wrześniu każdego roku. We wrześniu 2019 r.odbędzie się konferencja deweloperów w Montrealu w Kanadzie.

społeczność LLVM

społeczność LLVM jest przyjazną dla Noob ’ ów społecznością kompilatorów. Szybko reaguje na pytania nowych użytkowników i recenzje łatek. Jest to również podstawa i źródło późniejszych dyskusji Fundacji LLVM oraz przyjęcia kodeksu postępowania społeczności LLVM i powoduje serię poprawnych politycznie dyskusji.

wszystkie projekty i problemy LLVM są omawiane za pośrednictwem listy e-mailowej DevExpress, a przesyłanie kodu jest powiadamiane za pośrednictwem listy e-mail zatwierdzeń. Wszystkie błędy i modyfikacje funkcji są śledzone przez listę błędów. Przesłane poprawki są zalecane dla gałęzi master. Styl jest zgodny ze standardami kodowania LLVM, a przegląd kodu odbywa się za pomocą Phabricatora. Obecnie repozytorium kodu LLVM zostało przeniesione do GitHub.

w przeciwieństwie do społeczności GCC, społeczność LLVM ma tylko fundację LLVM. Fundacja LLVM ma ośmiu członków. Oprócz zarządzania sprawami społeczności LLVM, każdy członek fundacji LLVM musi kierować kwestiami rozwoju LLVM związanymi z technologią. Obecnie prezydentem jest Tanya Lattner, żona Chrisa Lattnera. Sam Chris Lattner jest również członkiem Fundacji i ma silną kontrolę nad społecznością LLVM i kierunkiem rozwoju LLVM.

Polityka przeglądu kodu w społeczności LLVM jest zasadniczo taka sama jak w społeczności GCC. Różnica polega na tym, że ze względu na szybki rozwój LLVM, wielu współpracowników nie ma uprawnień dostępu do commitów i musi przesłać swój kod za pośrednictwem opiekunów. Obecnie społeczności Clang i LLVM mają ponad 1000 współpracowników każdego roku. Ogólnie rzecz biorąc, konferencje dla programistów odbywają się w kwietniu i październiku każdego roku. Konferencja deweloperów w październiku 2019 r. odbędzie się w San Jose w USA.

licencja LLVM zostaje zmieniona z licencji UIUC na licencję Apache 2.0 z wyjątkami LLVM. Jest on używany głównie do rozwiązania problemu, że biblioteka uruchomieniowa LLVM jest oparta na licencji MIT, a autoryzacja patentowa wymagana dla projektu jest zbyt obszerna. Na mocy tej licencji LLVM pozwala każdemu czerpać komercyjne produkty z LLVM bez żadnych ograniczeń i nie wymaga, aby jakiekolwiek pochodne dostarczały otwarty kod źródłowy, promując w ten sposób szerokie wykorzystanie LLVM, w tym:

  1. pobieranie lub korzystanie z LLVM w całości lub w części do celów osobistych, wewnętrznych lub komercyjnych. Możliwość modyfikacji kodu LLVM bez wnoszenia go z powrotem do projektu.
  2. Tworzenie pakietu lub wersji wydania zawierającej LLVM. Powiązanie LLVM z kodem autoryzowanym przez wszystkie inne główne licencje open source (w tym BSD, MIT, GPLv2 i GPLv3).
  3. przy ponownej dystrybucji LLVM musisz zachować informację o prawach autorskich. Nie można usunąć ani zastąpić nagłówka praw autorskich. Plik binarny zawierający LLVM musi zawierać informację o prawach autorskich.

porównanie wydajności między GCC i LLVM

Architektura: x86_64
Procesor: Intel (r) Xeon (R) Platinum 8163 CPU @ 2.50 GHz
Pamięć podręczna L1: 32 KB
Pamięć podręczna L2: 1,024 KB
Pamięć podręczna L3: 33,792 KB
System Operacyjny: Alibaba Group Enterprise Linux Server release 7.2 (Paladin)
jądro: 4.9.151–015.ali3000alios7x86_64
Compiler: Clang/LLVM 8.0 Gcc8.3.1

Benchmark

SPEC CPU 2017 to zestaw narzędzi testowych podsystemu CPU do testowania procesora, pamięci podręcznej, pamięci i kompilatora. Zawiera testy 43 z czterech kategorii, w tym SPECSPEED 2017 INT i FP, które testują prędkość całkowitą i zmiennoprzecinkową oraz SPECrate 2017 INT i FP, które testują współbieżność całkowitą i współbieżność zmiennoprzecinkową. Clang nie obsługuje języka Fortran. Dlatego w tym przykładzie programy C/C ++ w zestawie Spec Speed test są używane do testowania różnicy wydajności jednordzeniowej między programami binarnymi generowanymi przez Clang i GCC. Poniższa tabela zawiera listę zestawów SPEC CPU2017 C i c++:

Cint2017 SpeedCFP2017 Speed600.perlbench_s619lbm_s602gcc_s644nab_s605mcf_s620omnetpp_s623xalancbmk_s625x264_s631deepsjeng_s641leela_s657xz_s

metody testowania

Framework automatyzacji LLVM-LNT służy do przeprowadzenia testu i porównania wydajności. Działa w taki sam sposób jak runcpu procesora SPEC. Przed uruchomieniem LLVM-lnt, Cache (echo 3 > /proc/sys/vm/drop_caches) jest wyczyszczony, a następnie uruchamia się testowy zestaw danych. Następnie zestaw danych ref działa trzy razy. Średnia wartość trzech wyników testu ref jest używana jako wynik końcowy. Aby zmniejszyć wahania wydajności spowodowane migracją PROCESORA lub przełącznikiem kontekstowym, procesy uruchomione na zestawie danych testowych i zestawie danych ref są powiązane z rdzeniem procesora za pomocą narzędzia powinowactwo procesora. Do testu czasu kompilacji ta metoda wykorzystuje wątek 1 do zbudowania programu testowego i porównania elementów testowych, które zostały skompilowane przez długi czas. Czas kompilacji nie obejmuje czasu wykonania linkera. Obejmuje tylko Czas generowania wszystkich plików źródłowych we wszystkich programach testowych.

porównanie wydajności kompilacji

proces kompilacji GCC wygląda następująco: odczytaj plik źródłowy, przetworz plik źródłowy, przekonwertuj go na IR, zoptymalizuj i wygeneruj plik złożenia. Następnie asembler generuje plik obiektowy. Clang i LLVM nie polegają na niezależnych kompilatorach, ale integrują samodzielnie zaimplementowane Kompilatory w backendzie. Proces generowania plików asemblacji jest pomijany w procesie generowania plików obiektowych. Plik obiektowy jest generowany bezpośrednio z IR. Poza tym, w porównaniu z GCC IR, struktura danych LLVM IR jest bardziej zwięzła. Zajmuje mniej pamięci podczas kompilacji i obsługuje szybsze przechodzenie. Dlatego Clang i LLVM są korzystne pod względem czasu kompilacji, co potwierdzają dane uzyskane z kompilacji SPEC, jak pokazano na poniższym rysunku. Clang skraca czas kompilacji jednowątkowej o 5% do 10% w porównaniu z GCC. Dlatego Clang oferuje więcej korzyści przy budowie dużych projektów.

porównanie czasu kompilacji Spec

porównanie wydajności wykonania

większość obciążeń w chmurze wymaga, aby aplikacje mogły działać w różnych klastrach. Podczas tworzenia tych aplikacji nie określaj parametrów związanych z maszyną. Aby dostosować się do szybkiej iteracji spowodowanej zmianami popytu, Obciążenia zewnętrzne muszą być również debugowalne. Dlatego, oprócz pewnych stabilnych i popularnych bibliotek, które umożliwiają wysoki poziom optymalizacji kompilacji, samo obciążenie ma niski poziom kompilacji i optymalizacji (O2 lub niższy). Aby spełnić ten wymóg, niniejszy dokument porównuje wydajność różnych kompilatorów na poziomach optymalizacji O2 i O3 dla programów prędkości INT, jak pokazano na poniższym rysunku:

porównanie wydajności Spec cpu2017 int Speed

gcc ma 1% do 4% przewagi wydajności nad clang i LLVM dla większości programów na poziomie O2 i O3, a średnio ma około 3% przewagi wydajności dla spec cpu2017 int Speed. Miejscu pod względem liczby ludności, natomiast pod względem powierzchni na miejscu 600.perlbench_s oraz 602.gcc_s / O2, GCC ma dużą przewagę wydajności (ponad 10%). Te dwa elementy testowe nie mają wyjątkowych hotspotów i mogą odzwierciedlać wszechstronny efekt optymalizacji kompilatora. Wyniki testów pokazują, że GCC jest zawsze korzystne w optymalizacji wydajności. Jednak dla dwóch programów związanych z AI, w tym 631.deepsjeng_s oraz 641.leela_s, które są nowo dodane do testu SPEC, Clang i LLVM poprawiają wydajność o ponad 3% w porównaniu do GCC. Odzwierciedla to również szybki postęp LLVM w zakresie optymalizacji. Dla 625. optymalizacja x264_s O2, LLVM poprawia wydajność o 40%, ponieważ hotspot sprawy jest zgodny z regułami wektoryzowanymi. Ale clang i LLVM optymalizują wektory na poziomie O2, podczas gdy GCC optymalizuje wektory na poziomie O3. Z wyjątkiem programów wektoryzowanych, GCC nie poprawia znacznie wydajności na poziomie O3 w porównaniu z poziomem O2. Innymi słowy, programy nie są wrażliwe na optymalizację GCC O3. Natomiast Clang i LLVM znacznie poprawiają wydajność niektórych programów (np. 600. perlbench_s oraz 602. gcc_s) na poziomie O3.

programy HPC, takie jak FP Speed, generalnie działają na serwerach high-end. Mają stabilne podstawowe algorytmy, wysokie wymagania dotyczące wektoryzacji i równoległości wydajności oraz umożliwiają wysoki poziom optymalizacji (O3 lub wyższy). Dlatego ten dokument porównuje wydajność na poziomie optymalizacji O3 + march = native (skylake-avx512), jak pokazano poniżej:

porównanie wydajności Spec cpu2017 FP speed

w przypadku dwóch programów FP gcc może również poprawić wydajność o około 3%. Clang i LLVM są konserwatywne w optymalizacji pętli, a zatem nie są korzystne pod względem wydajności. Jednak podprojekt Polly clang i LLVM zapewnia wysokopoziomowy optymalizator pętli i lokalizacji danych, który jest szeroko stosowany w uczeniu maszynowym, obliczeniach o wysokiej wydajności i heterogenicznej optymalizacji obliczeń. Uważam, że Polly może znacznie poprawić wydajność programów, które zawierają pętle hotspot zgodne z regułami wektoryzacji i równoległości. Przeanalizuję również wydajność Polly w szeregu benchmarków i obciążeń.

Uwagi końcowe

z powyższych testów porównawczych widać, że Clang oferuje więcej korzyści przy budowie dużych projektów, podczas gdy GCC jest zawsze korzystny w optymalizacji wydajności. Bla zależy od konkretnej aplikacji

oprócz porównania wydajności, chciałbym podzielić się zaletami i wadami GCC i clang i LLVM:

zalety GCC

  • GCC obsługuje więcej tradycyjnych języków niż clang i LLVM, takich jak Ada, Fortran i Go.
  • GCC obsługuje więcej mniej popularnych architektur i obsługuje RISC-V wcześniej niż clang i LLVM.
  • GCC obsługuje więcej rozszerzeń języka i więcej funkcji języka asemblera niż clang i LLVM. GCC jest nadal jedyną opcją kompilacji jądra Linuksa. Chociaż badania nad kompilacją jądra przy użyciu Clang i LLVM są również zgłaszane w branży, jądro nie może być skompilowane bez modyfikacji kodu źródłowego i parametrów kompilacji.

zalety Clang i LLVM

  • nowe języki używają frameworków LLVM, takich jak Swift, Rust, Julia i Ruby.
  • Clang i LLVM są bardziej zgodne ze standardami C i C ++ niż GCC. GNU Inline i inne problemy podczas aktualizacji GCC nie występują.
  • Clang obsługuje również niektóre rozszerzenia, takie jak atrybuty sprawdzania bezpieczeństwa wątków.
  • Clang zapewnia dodatkowe przydatne narzędzia, takie jak scan-build i clang static analyzer do analizy statycznej, clang-format i clang-tidy do analizy składniowej, a także wtyczkę edytora Clangd.
  • Clang zapewnia dokładniejsze i bardziej przyjazne informacje diagnostyczne oraz podkreśla komunikaty o błędach, linie błędów, monity o błędach i sugestie dotyczące napraw. Clang traktuje informacje diagnostyczne jako cechę. Informacje diagnostyczne zaczęły być ulepszane tylko z GCC 5.0, a dojrzały w GCC 8.

(oryginalny artykuł Ma Jun)

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *