Introducing GNU Compiler Collection (GCC) and Clang/Low Level Virtual Machine (LLVM); comparing the performance of both 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++ biedt grafische gebruikersinterfaces (GUI ‘ s) en is gemakkelijk te debuggen, maar het is niet geschikt voor Linux-platforms. Daarom vergelijkt dit document voornamelijk GCC met Clang/LLVM.
GCC is een programmataal compiler ontwikkeld door GNU. Het is een verzameling vrije software die is uitgebracht onder de GNU General Public License (GPL) en de GNU Lesser General Public License (LGPL). Het is een officiële compiler voor de GNU-en Linux-systemen, en een belangrijkste compiler voor het compileren en maken van andere UNIX-besturingssystemen.
LLVM bevat een reeks gemodulariseerde compilercomponenten en gereedschapsketens. Het kan programmatalen en koppelingen optimaliseren tijdens compilatie, runtime en inactieve tijd en code genereren. LLVM kan dienen als achtergrond voor compilers in meerdere talen. Clang is een C, C++, Objective-C, of Objective-C++ compiler die is gecompileerd in C++ op basis van LLVM en uitgebracht onder de Apache 2.0 licentie. Clang wordt voornamelijk gebruikt om prestaties te leveren die superieur zijn aan die van GCC.
door ontwikkeling en iteratie op lange termijn zijn GCC, Clang en LLVM volwassen compilers in de industrie geworden. Welke compiler is dan beter? Welke moeten we gebruiken om programma ‘ s en systemen te compileren en te bouwen?
Betekenis van een goede Compiler
moderne processoren hebben allemaal superscalaire en lange pijpleidingen, en complexe interne structuren, en ze ondersteunen vectoruitbreidingseenheden in de complexe Instructiesetcomputer (CISC) of Reduced instructions Set Computer (RISC) architectuur. Voor veel programma ’s die algemene computing-intensieve kernels bevatten, kunnen programmeurs vectorextensiecommando’ s gebruiken om de uitvoeringsprestaties van programma ‘ s sterk te verbeteren. Bijvoorbeeld, in matrix en vector operaties, worden de gecombineerde vermenigvuldiging en toevoeging commando ‘ s gebruikt om de prestaties en nauwkeurigheid te verbeteren. Bit mask commando ‘ s worden gebruikt voor branch verwerking in vector operaties. Echter, om de hoogste prestaties te bereiken, moeten programmeurs en compilers nog steeds veel moeite doen om taken met complexe geheugentoegang modi en niet-standaard kernels af te handelen.
bovendien abstraheren standaarden van moderne geavanceerde talen voortdurend de details van onderliggende hardware en datastructuren om algemene code te genereren die logischer en mathematisch is, in plaats van specifieke bedieningsinstructies en geheugentoegangspaden. C++ standaarden worden steeds expressiever en abstracter. Python is populair omdat het leesbaarder en expressief is, zelfs ten koste van een lagere loopsnelheid. Hogere expressiviteit verhoogt de last van de compiler om goede assemblage code te genereren uit de complexe structuren gecompileerd door programmeurs. De compiler moet slimmer zijn en harder werken om de prestaties te maximaliseren met behulp van de code. Niet alle compilers kunnen dit. Bij het selecteren van een compiler, moeten we eerst overwegen of hetzelfde codesegment efficiëntere assembly commando ‘ s kan genereren.
naast het genereren van uitvoerbare programma ‘ s met hoge prestaties, moeten moderne compilers ook zelf hoge prestaties leveren. Een groot softwareproject in C++ kan honderden tot duizenden individuele vertaaleenheden bevatten. Elke vertaaleenheid kan duizenden regels code bevatten. C++ code kan ook gebruik maken van een groot aantal template-gebaseerde programmeertechnologieën. Deze technologieën vereisen dat de compiler meerdere keren relevante informatie overbrengt om een doelbestand te genereren. De compilatie van grote C++ projecten kan enkele uren duren, en meerdere onderling afhankelijke wijzigingen moeten gelijktijdig worden ingediend tijdens de ontwikkeling. Elke inzending vereist dat ontwikkelaars de meeste codebibliotheken opnieuw compileren. Daarom zijn snellere compilers (build tools) van cruciaal belang voor het bereiken van een hoge productiviteit voor grote teams.
in termen van taaluitbreiding bieden moderne computersystemen met meerdere kernels, vectorverwerkingsmogelijkheden en versnellers mogelijkheden die superieur zijn aan de natuurlijke mogelijkheden van gemeenschappelijke programmeertalen. Daarom kunnen specifieke high-performance computing (HPC) frameworks, zoals OpenMP en OpenACC, deze leemte opvullen. Deze frameworks bieden application program interfaces (API ‘ s) die programmeurs kunnen gebruiken om parallellisme in code uit te drukken. De compiler en de bijbehorende runtime library moeten de parallelle code toewijzen aan de processorarchitectuur. Veel HPC-projecten zijn afhankelijk van OpenMP-en OpenACC-standaarden, die worden uitgebreid door ontwikkelaars en hardwarefabrikanten. Daarom moeten de compilers gelijke tred houden met de ontwikkeling van taaluitbreidingsnormen.
concluderend, een goede compiler stelt ons in staat om ons te concentreren op het proces van programmeren, in plaats van te vechten tegen de tekortkomingen. Het kan de nieuwste taalstandaarden ondersteunen, geoptimaliseerde opdrachten genereren uit de meest abstracte code en de broncode in minder tijd compileren.
GCC-ontwikkelingsgeschiedenis
voordat u GCC leert, moet u eerst het GNU-Project begrijpen. Richard Stallman lanceerde het GNU-Project in 1984 om een UNIX-achtig open source softwaresysteem te bouwen. Het GNU-besturingssysteem is in de loop van de tijd niet uitgebreid geëvolueerd. Echter, het heeft vele uitstekende en nuttige open source software tools geïncubeerd, zoals Make, Sed, Emacs, Glibc, GDB, en GCC ook. Deze GNU open source software en Linux kernels vormen samen het GNU / Linux systeem. In het begin leverde GCC stabiele en betrouwbare compilers, gebaseerd op de programmeertaal C, voor het GNU-systeem. De volledige naam is GNU C Compiler. Later werden meer talen (zoals Fortran, Obj-C en Ada) ondersteund en veranderde de volledige naam van GCC in GNU Compiler Collection.
GCC-1.0 werd uitgebracht door Richard Stallman in 1987, meer dan dertig jaar geleden. Vanuit het software perspectief is het erg oud. Iemand verzamelde de GCC-ontwikkelingsrecords van tussen 1989 en 2012, en produceerde een dertig minuten durende geanimeerde video (GNU Compiler Collection dev history 1989-2012), die intuïtief het ontwikkelingsproces van GCC demonstreerde. We kunnen de ontwikkelingsgeschiedenis van GCC leren uit de versies:
- GCC-1.0: uitgebracht door Richard Stallman in 1987.
- GCC-2.0: uitgebracht in 1992 en ondersteund C++. Later werd de GCC-gemeenschap gesplitst omdat Richard Stallman GCC definieerde als een betrouwbare C-compiler van het GNU-systeem en dacht dat GCC op dat moment voldoende was voor het GNU-systeem en de ontwikkelingsfocus moest worden verschoven van GCC naar het GNU-systeem zelf. Andere grote ontwikkelaars hoopten om GCC te blijven verbeteren en radicalere ontwikkelingen en verbeteringen in verschillende aspecten te maken. Deze actieve ontwikkelaars verlieten de GCC gemeenschap in 1997 en ontwikkelden de EGCS fork.
- GCC-3.0: uiteraard hadden ontwikkelaars over het algemeen een sterk verlangen naar goede compilers. De egcs vork ontwikkelde zich soepel en werd erkend door meer en meer ontwikkelaars. Uiteindelijk werd EGCS gebruikt als de nieuwe GCC backbone en GCC-3.0 werd uitgebracht in 2001. De gesplitste gemeenschap werd opnieuw samengevoegd, maar de invloed van Richard Stallman was tot op zekere hoogte verzwakt. Daarnaast was het industrieel Comité van de GCC begonnen met het bepalen van de ontwikkelingsrichting van de GCC.
- GCC-4.0: uitgebracht in 2005. Deze versie werd geà ntegreerd in de Tree Serial Storage Architecture (SSA), en GCC evolueerde naar een moderne compiler.
- GCC-5.0: uitgebracht in 2015. Later werd het GCC-versiebeleid aangepast en werd elk jaar een belangrijke versie uitgebracht. Een onverwacht voordeel is dat het versienummer overeenkomt met het jaartal. Bijvoorbeeld, GCC-7 werd uitgebracht in 2017, en GCC-9 werd uitgebracht in 2019.
nu is de ontwikkeling van GCC de “moderne kroniek”ingegaan. Geconfronteerd met de concurrentiedruk van LLVM heeft de GCC-gemeenschap actief veel aanpassingen doorgevoerd, zoals het versnellen van de compilatie en het verbeteren van de waarschuwingsinformatie voor de compilatie. In de afgelopen 30 jaar is GCC geëvolueerd van een uitdager in de compilerindustrie naar een mainstream compiler voor Linux-systemen, en staat nu voor de uitdaging van LLVM. Gelukkig maakt de GCC-gemeenschap aanpassingen om de ontwikkeling van GCC te versnellen. We kunnen verwachten dat de concurrentie tussen de twee compilatietechnologieën softwareontwikkelaars betere compilers zal blijven bieden.
ontwikkelingsgeschiedenis van Clang en LLVM
LLVM is ontstaan uit het onderzoek van Chris Lattner over UUIC in 2000. Chris Lattner wilde een dynamische compilatietechnologie creëren voor alle statische en dynamische talen. LLVM is een type open source software ontwikkeld onder de BSD-licentie. De eerste versie 1.0 werd uitgebracht in 2003. In 2005 Werd Apple Inc. hij huurde Chris Lattner en zijn team in om programmeertalen en compilers voor Apple computers te ontwikkelen, waarna de ontwikkeling van LLVM de snelle weg inging. Vanaf LLVM 2.5, twee kleine LLVM versies werden elk jaar uitgebracht (over het algemeen in Maart en September). In November 2011 werd LLVM 3.0 uitgebracht als de standaard Xcode compiler. XCode 5 begon standaard Clang en LLVM 5.0 te gebruiken. Het versiebeleid werd aangepast voor LLVM 5.0 en latere versies, en twee belangrijke versies worden elk jaar uitgebracht. De huidige stabiele versie is 8.0.
de naam van LLVM werd voor het eerst afgekort van Low Level Virtual Machine. Aangezien dit project niet beperkt is tot het maken van een virtuele machine, wordt de afkorting LLVM vaak in vraag gesteld. Nadat LLVM werd ontwikkeld, werd het een verzamelnaam voor veel compilatietools en low-level tooltechnologieën, waardoor de naam Minder toepasselijk werd. Ontwikkelaars besloten om de betekenis achter deze afkorting te verlaten. Nu is LLVM de officiële merknaam geworden, die van toepassing is op alle projecten onder LLVM, inclusief LLVM Intermediate Representation (LLVM IR), LLVM debugging tools en LLVM C++ standaardbibliotheken. LLVM kan worden gebruikt als een traditionele compiler, JIT compiler, assembler, debugger, statische analyse tool, en voor andere functies met betrekking tot programmeertalen.in 2012 won LLVM de software system award van Association for Computing Machinery (ACM), samen met traditionele systemen zoals UNIX, WWW, TCP/IP, Tex en Java. LLVM vereenvoudigt de implementatie van nieuwe programmeertaal tool ketens aanzienlijk. In de afgelopen jaren hebben veel nieuwe programmeertalen zoals Swift, Rust en Julia LLVM gebruikt als hun compilatiekader. Daarnaast is LLVM de standaard compiler geworden voor Mac OS X, iOS, FreeBSD en Android systemen.
Clang
Clang is ontworpen om een frontend compiler te bieden die GCC kan vervangen. Apple Inc. (inclusief volgende later) gebruikt GCC als de officiële compiler. GCC heeft altijd goed gepresteerd als een standaard compiler in de open source gemeenschap. Echter, Apple Inc. heeft zijn eigen vereisten voor compilatietools. Aan de ene kant, Apple Inc. toegevoegd veel nieuwe functies voor de doelstelling-c taal (of zelfs, later, de C taal). GCC-ontwikkelaars accepteerden deze functies echter niet en gaven een lage prioriteit aan ondersteuning voor deze functies. Later werden ze gewoon verdeeld in twee takken voor aparte ontwikkeling, en bijgevolg de GCC-versie uitgebracht door Apple Inc. is veel eerder dan de officiële versie. Aan de andere kant is de GCC-code sterk gekoppeld en moeilijk afzonderlijk te ontwikkelen. Bovendien blijft de kwaliteit van de code in latere versies afnemen. Echter, veel functies vereist door Apple Inc. (zoals improved Integrated Development Environment (IDE) ondersteuning) moet GCC aanroepen als een module, maar GCC biedt nooit dergelijke ondersteuning. Bovendien, de GCC Runtime Library vrijstelling fundamenteel beperkt de ontwikkeling van LLVM GCC. Ook beperkt door de licentie, Apple Inc. kan LLVM niet gebruiken om de codegeneratiekwaliteit op basis van GCC verder te verbeteren. Daarom Is Apple Inc. besloten om de frontend Clang van C, C++ en Objective-C talen vanaf nul te schrijven om GCC volledig te vervangen.
zoals de naam al doet vermoeden, ondersteunt Clang alleen C, C++ en Objective-C. De ontwikkeling begon in 2007 en de C-compiler werd voor het eerst voltooid. Clang voor Objective-C cloud volledig worden gebruikt voor de productie-omgeving in 2009. Ondersteuning voor C++ vorderde ook snel. Clang 3.3 volledig ondersteund C++ 11, Clang 3.4 volledig ondersteund C++ 14, en Clang 5 volledig ondersteund C++ 17, en alle waren aanzienlijk voorsprong op GCC op dat moment.
Clang / LLVM en GCC gemeenschap
net als andere open source software gemeenschappen, wordt de GCC gemeenschap gedomineerd door vrije software liefhebbers en hackers. In het ontwikkelingsproces worden de GCC-gemeenschapsmanagement-en participatiemechanismen vandaag geleidelijk gevormd. Momenteel is de GCC-Gemeenschap een relatief stabiele en goed gedefinieerde kennismaatschappij waarin elke persoon duidelijke rollen en plichten heeft: Richard Stallman en Free Software Foundation (FSF): hoewel zelden betrokken bij het GCC-gemeenschapsbeheer, zijn Richard Stallman en FSF nog steeds los van elkaar in licentie-en juridische zaken.
net als andere open source communities wordt de volwassen GCC-Gemeenschap niet langer gedomineerd door hackers. Commerciële bedrijven begonnen een belangrijke rol te spelen in de Gemeenschap, zoals het werven van ontwikkelaars en het sponsoren van ontwikkelingsbijeenkomsten. Momenteel wordt de GCC-gemeenschap gedomineerd door de volgende soorten commerciële bedrijven:
- Systeemverkopers, met name RedHat en SUSE.
- Chipverkopers, voornamelijk inclusief Intel, ARM, AMD en IBM (PowerPC).
- gespecialiseerde leveranciers, zoals CodeSourcery en tool chain service providers zoals AdaCore gebaseerd op de ADA taal. CodeSourcery had een briljante geschiedenis en rekruteerde veel beroemde ontwikkelaars, maar daalde nadat het werd overgenomen door Mentor.
in de huidige GCC-gemeenschap domineren chipverkopers de ontwikkeling van backend, terwijl systeemverkopers andere ontwikkelingsgebieden begeleiden. In termen van community development, de GCC code wordt momenteel gehost op zijn eigen SVN server. Een GIT API wordt geleverd om de ontwikkeling en indiening te vergemakkelijken. Patch review is vergelijkbaar met die in de Linux Kernel gemeenschap en gebruikt het Mailing List formulier. Zoals hierboven vermeld, is de GCC-Gemeenschap een relatief stabiele (of gesloten) kennismaatschappij. De Gemeenschap heeft in principe 150 tot 200 actieve contribuanten per jaar en houdt elk jaar in September een conferentie over ontwikkelaars. In September 2019 vindt de developer conference plaats in Montreal, Canada.
LLVM Community
De LLVM community is een noob-vriendelijke compiler community. Het reageert snel op de vragen van nieuwe gebruikers en patch reviews. Dit is ook de basis en bron voor de daaropvolgende discussies van de LLVM-Stichting en de goedkeuring van de gedragscode van de LLVM-Gemeenschap, en leidt tot een reeks politiek correcte discussies.
alle LLVM projecten en problemen worden besproken via de DevExpress email lijst, en code indiening wordt gemeld via de commits email lijst. Alle bugs en functie wijzigingen worden gevolgd door de bugs lijst. De ingediende patches worden aanbevolen voor de master branches. De stijl voldoet aan de LLVM-coderingsnormen en de codebeoordeling wordt uitgevoerd via Phabricator. Momenteel is de LLVM code repository gemigreerd naar GitHub.
In tegenstelling tot de GCC-Gemeenschap heeft de LLVM-gemeenschap alleen de LLVM-Stichting. De LLVM Foundation telt acht leden. Naast het beheren van LLVM-gemeenschapszaken, moet elk lid van de LLVM-Stichting LLVM-ontwikkelingsproblemen met betrekking tot technologie begeleiden. Momenteel is de president Tanya Lattner, de vrouw van Chris Lattner. Chris Lattner zelf is ook lid van de stichting en heeft sterke controle over de LLVM-gemeenschap en de ontwikkelingsrichting van LLVM.
het codebeoordelingsbeleid in de LLVM-gemeenschap is in principe hetzelfde als dat in de GCC-gemeenschap. Het verschil is dat, vanwege de snelle ontwikkeling van LLVM, veel bijdragers geen toegangsrechten hebben voor commit, en hun code moeten indienen via de beheerders. Momenteel hebben de Clang-en LLVM-gemeenschappen meer dan 1.000 bijdragers per jaar. Over het algemeen worden Ontwikkelaar conferenties jaarlijks gehouden in April en oktober. De developer conference in oktober 2019, zal worden gehouden in San Jose, USA.
De LLVM-licentie wordt gewijzigd van UIUC-Licentie naar Apache 2.0-licentie met LLVM-uitzonderingen. Het wordt voornamelijk gebruikt om het probleem op te lossen dat de LLVM Runtime library is gebaseerd op MIT-licentie en de patentvergunning die vereist is voor het project te uitgebreid is. Onder deze licentie, LLVM staat iedereen toe om commerciële producten af te leiden van LLVM zonder enige beperkingen, en vereist niet dat alle derivaten bieden open source code, dus het bevorderen van het uitgebreide gebruik van LLVM, met inbegrip van:
- het downloaden of gebruiken van LLVM geheel of gedeeltelijk voor persoonlijke, interne of commerciële doeleinden. De mogelijkheid om LLVM-code te wijzigen zonder deze bij te dragen aan het project.
- het aanmaken van een pakket of release versie die LLVM bevat. De associatie van LLVM met code geautoriseerd door alle andere belangrijke open source licenties (inclusief BSD, MIT, GPLv2 en GPLv3).
- wanneer u LLVM opnieuw distribueert, moet u de copyright notice behouden. U kunt de koptekst van het auteursrecht Niet verwijderen of vervangen. Het binaire bestand met LLVM moet de copyright notice bevatten.
prestatievergelijking tussen GCC en LLVM
architectuur: x86_64
Processor: Intel (R) Xeon (R) Platinum 8163 CPU @ 2,50 GHz
L1 gegevenscache: 32 KB
L2 cache: 1,024 KB
L3 cache: 33,792 KB
geheugen: 800 GB
besturingssysteem: Alibaba Group Enterprise Linux Server release 7.2 (Paladin)
Kernel: 4.9.151–015.ali3000.alios7.x86_64
Compiler: Clang / LLVM 8.0 GCC8. 3.1
Benchmark
SPEC CPU 2017 is een set van CPU subsysteem testtools voor het testen van de CPU, cache, geheugen en compiler. Het bevat 43 tests van vier categorieën, waaronder SPECspeed 2017 int en FP die de gehele snelheid en drijvende komma operatie snelheid testen en SPECrate 2017 int en FP die de gehele concurrency rate en drijvende komma concurrency rate testen. Clang ondersteunt de taal Fortran niet. Daarom worden in dit voorbeeld de C/C ++ programma ’s in de spec Speed test set gebruikt om het single-core performance verschil te testen tussen de binaire programma’ s gegenereerd door Clang en GCC. De volgende tabel geeft een overzicht van de CPU2017 C en c++ sets:
CINT2017 SpeedCFP2017 Speed600.perlbench_s619.lbm_s602.gcc_s644.nab_s605.mcf_s620.omnetpp_s623.xalancbmk_s625.x264_s631.deepsjeng_s641.leela_s657.Xz_s
testmethoden
het LLVM-lnt automatiseringskader wordt gebruikt om de test uit te voeren en de prestaties te vergelijken. Het draait op dezelfde manier als runcpu van SPEC CPU. Voordat LLVM-lnt wordt uitgevoerd, wordt cache (echo 3 > /proc/sys/vm/drop_caches) gewist en dan wordt de testdataset uitgevoerd. Vervolgens draait de Ref-dataset drie keer. De gemiddelde waarde van de drie ref-testresultaten wordt als eindresultaat gebruikt. Om prestatiefluctuaties veroorzaakt door CPU-migratie of context switch te verminderen, worden processen die op de test-dataset en ref-dataset worden uitgevoerd, aan een CPU-kern gebonden met behulp van het hulpprogramma CPU-affiniteit. Voor de compileertijdtest gebruikt deze methode thread 1 om het testprogramma te bouwen en de testitems te vergelijken die al lang zijn gecompileerd. De compilatietijd omvat niet de linker uitvoeringstijd. Het bevat alleen de tijd wanneer alle bronbestanden in alle testprogramma ‘ s worden gegenereerd.
Compilatieprestatie vergelijking
het compilatieproces van GCC is als volgt: lees het bronbestand, preprocess het bronbestand, converteer het in een IR, optimaliseer en genereer een assembly-bestand. Vervolgens genereert de assembler een objectbestand. Clang en LLVM vertrouwen niet op onafhankelijke compilers, maar integreren zelf-geà mplementeerde compilers aan de backend. Het proces van het genereren van assembly bestanden wordt weggelaten in het proces van het genereren van object bestanden. Het objectbestand wordt direct vanuit de IR gegenereerd. Bovendien, vergeleken met GCC IR, is de gegevensstructuur van LLVM IR beknopter. Het neemt minder geheugen in tijdens de compilatie en ondersteunt snellere traversal. Daarom zijn Clang en LLVM voordelig in termen van de compilatietijd, die wordt bewezen door de gegevens die zijn verkregen uit de SPEC-compilatie, zoals weergegeven in de onderstaande figuur. Clang vermindert de compilatietijd met één draad met 5% tot 10% in vergelijking met GCC. Daarom biedt Clang meer voordelen voor de bouw van grote projecten.