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 ++ bietet grafische Benutzeroberflächen (GUIs) und ist einfach zu debuggen, aber nicht für Linux-Plattformen geeignet. Daher vergleicht dieses Dokument hauptsächlich GCC mit Clang / LLVM.

GCC ist ein von GNU entwickelter Programmsprachen-Compiler. Es ist eine Reihe freier Software, die unter der GNU General Public License (GPL) und der GNU Lesser General Public License (LGPL) veröffentlicht wird. Es ist ein offizieller Compiler für die GNU- und Linux-Systeme und ein Hauptcompiler zum Kompilieren und Erstellen anderer UNIX-Betriebssysteme.

LLVM enthält eine Reihe von modularisierten Compilerkomponenten und Werkzeugketten. Es kann Programmsprachen und Links während der Kompilierung, Laufzeit und Leerlaufzeit optimieren und Code generieren. LLVM kann als Hintergrund für Compiler in mehreren Sprachen dienen. Clang ist ein C-, C ++ -, Objective-C- oder Objective-C ++ – Compiler, der in C ++ basierend auf LLVM kompiliert und unter der Apache 2.0-Lizenz veröffentlicht wird. Clang wird hauptsächlich verwendet, um eine Leistung zu erzielen, die der von GCC überlegen ist.

Durch langfristige Entwicklung und Iteration sind GCC, Clang und LLVM zu ausgereiften Compilern in der Branche geworden. Welcher Compiler ist dann besser? Welches sollten wir verwenden, um Programme und Systeme zu kompilieren und zu erstellen?

Bedeutung eines guten Compilers

Moderne Prozessoren haben alle superskalare und lange Pipelines sowie komplexe interne Strukturen und unterstützen Vektorerweiterungseinheiten in der Complex Instruction Set Computer (CISC) – oder Reduced Instruction Set Computer (RISC) -Architektur. Für viele Programme, die allgemeine rechenintensive Kernel enthalten, können Programmierer Vektorerweiterungsbefehle verwenden, um die Programmausführungsleistung erheblich zu verbessern. Beispielsweise werden bei Matrix- und Vektoroperationen die kombinierten Multiplikations- und Additionsbefehle verwendet, um die Leistung und Genauigkeit zu verbessern. Bitmaskenbefehle werden für die Verzweigungsverarbeitung in Vektoroperationen verwendet. Um jedoch die höchste Leistung zu erzielen, müssen Programmierer und Compiler immer noch viel Aufwand betreiben, um Aufgaben mit komplexen Speicherzugriffsmodi und nicht standardmäßigen Kerneln zu bewältigen.Darüber hinaus abstrahieren Standards moderner fortgeschrittener Sprachen ständig die Details der zugrunde liegenden Hardware und Datenstrukturen, um allgemeinen Code zu generieren, der logischer und mathematischer ist, anstatt spezifische Betriebsanweisungen und Speicherzugriffspfade. C ++ – Standards werden immer expressiver und abstrakter. Python ist beliebt, weil es lesbarer und ausdrucksvoller ist, selbst auf Kosten einer niedrigeren Laufgeschwindigkeit. Eine höhere Ausdruckskraft erhöht die Belastung des Compilers, guten Assemblercode aus den komplexen Strukturen zu generieren, die von Programmierern kompiliert wurden. Der Compiler muss intelligenter sein und härter arbeiten, um die Leistung mithilfe des Codes zu maximieren. Nicht alle Compiler können das. Bei der Auswahl eines Compilers müssen wir zunächst prüfen, ob dasselbe Codesegment effizientere Assemblerbefehle generieren kann.

Moderne Compiler müssen nicht nur leistungsstarke ausführbare Programme erzeugen, sondern auch selbst über eine hohe Leistung verfügen. Ein großes Softwareprojekt in C ++ kann Hunderte bis Tausende einzelner Übersetzungseinheiten enthalten. Jede Übersetzungseinheit kann Tausende von Codezeilen enthalten. C ++ – Code kann auch eine große Anzahl von vorlagenbasierten Programmiertechnologien verwenden. Diese Technologien erfordern, dass der Compiler relevante Informationen mehrmals überträgt, um eine Zieldatei zu generieren. Die Kompilierung großer C ++ – Projekte kann mehrere Stunden dauern, und während der Entwicklung müssen mehrere voneinander abhängige Änderungen gleichzeitig eingereicht werden. Für jede Einreichung müssen Entwickler die meisten Codebibliotheken neu kompilieren. Daher sind schnellere Compiler (Build-Tools) entscheidend, um eine hohe Produktivität für große Teams zu erreichen.In Bezug auf die Spracherweiterung bieten moderne Computersysteme mit mehreren Kerneln, Vektorverarbeitungsfunktionen und Beschleunigern Funktionen, die den natürlichen Fähigkeiten gängiger Programmiersprachen überlegen sind. Daher können spezielle HPC-Frameworks (High Performance Computing) wie OpenMP und OpenACC diese Lücke schließen. Diese Frameworks bieten Anwendungsprogrammschnittstellen (APIs), mit denen Programmierer Parallelität im Code ausdrücken können. Der Compiler und die entsprechende Laufzeitbibliothek müssen den parallelen Code der Prozessorarchitektur zuordnen. Viele HPC-Projekte hängen von OpenMP- und OpenACC-Standards ab, die von Entwicklern und Hardwareherstellern erweitert werden. Daher müssen die Compiler mit der Entwicklung von Spracherweiterungsstandards Schritt halten.

Abschließend erlaubt uns ein guter Compiler, uns auf den Prozess der Programmierung zu konzentrieren, anstatt gegen seine Mängel zu kämpfen. Es kann die neuesten Sprachstandards unterstützen, optimierte Befehle aus dem abstraktesten Code generieren und den Quellcode in kürzerer Zeit kompilieren.

Entwicklungsgeschichte von GCC

Bevor Sie GCC lernen, müssen Sie zuerst das GNU-Projekt verstehen. Richard Stallman startete 1984 das GNU-Projekt, um ein UNIX-ähnliches Open-Source-Softwaresystem zu entwickeln. Das GNU-Betriebssystem hat sich im Laufe der Zeit nicht umfassend weiterentwickelt. Es hat jedoch viele hervorragende und nützliche Open-Source-Software-Tools wie Make, Sed, Emacs, Glibc, GDB und GCC entwickelt. Diese GNU Open Source Software und Linux Kernel bilden zusammen das GNU/Linux System. Am Anfang stellte GCC stabile und zuverlässige Compiler zur Verfügung, die auf der Programmiersprache C für das GNU-System basierten. Ihr voller Name lautet GNU C Compiler. Später wurden weitere Sprachen (wie Fortran, Obj-C und Ada) unterstützt, und der vollständige Name von GCC wurde in GNU Compiler Collection geändert.

GCC-1.0 wurde 1987 von Richard Stallman veröffentlicht, vor mehr als dreißig Jahren. Aus der Software-Perspektive ist es sehr alt. Jemand sammelte die GCC-Entwicklungsaufzeichnungen zwischen 1989 und 2012 und produzierte ein dreißigminütiges animiertes Video (GNU Compiler Collection dev History 1989-2012), das den Entwicklungsprozess von GCC intuitiv demonstrierte. Wir können etwas über die Entwicklungsgeschichte von GCC aus seinen Versionen lernen:

  • GCC-1.0: veröffentlicht von Richard Stallman im Jahr 1987.
  • GCC-2.0: veröffentlicht 1992 und unterstützt C++. Später wurde die GCC-Gemeinschaft gespalten, weil Richard Stallman GCC als zuverlässigen C-Compiler des GNU-Systems definierte und dachte, dass GCC zu dieser Zeit für das GNU-System ausreichend war und der Entwicklungsfokus von GCC auf das GNU-System selbst verlagert werden sollte. Andere große Entwickler hofften, GCC weiter zu verbessern und radikalere Entwicklungen und Verbesserungen in verschiedenen Aspekten vorzunehmen. Diese aktiven Entwickler verließen 1997 die GCC-Community und entwickelten die EGCS-Gabel.
  • GCC-3.0: Offensichtlich hatten Entwickler im Allgemeinen einen starken Wunsch nach guten Compilern. Die EGCS-Gabel entwickelte sich reibungslos und wurde von immer mehr Entwicklern anerkannt. Schließlich wurde EGCS als neues GCC-Backbone verwendet und GCC-3.0 wurde 2001 veröffentlicht. Die gespaltene Gemeinschaft wurde wieder zusammengeführt, aber Richard Stallmans Einfluss war bis zu einem gewissen Grad geschwächt worden. Darüber hinaus hatte das GCC Industrial Committee begonnen, die Entwicklungsrichtung von GCC zu bestimmen.
  • GCC-4.0: veröffentlicht im Jahr 2005. Diese Version wurde in die Serial Storage Architecture (SSA) integriert, und GCC entwickelte sich zu einem modernen Compiler.
  • GCC-5.0: veröffentlicht im Jahr 2015. Später wurde die GCC-Versionsrichtlinie angepasst und jedes Jahr eine Hauptversion veröffentlicht. Ein unerwarteter Vorteil ist, dass die Versionsnummer dem Jahr entspricht. Beispielsweise wurde GCC-7 2017 und GCC-9 2019 veröffentlicht.

Jetzt ist die GCC-Entwicklung in die „moderne Chronik“ eingetreten. Angesichts des Wettbewerbsdrucks von LLVM hat die GCC-Community aktiv viele Anpassungen vorgenommen, z. B. die Beschleunigung der Kompilierung und die Verbesserung der Kompilierungswarnungsinformationen. In den letzten 30 Jahren hat sich GCC von einem Herausforderer in der Compiler-Branche zu einem Mainstream-Compiler für Linux-Systeme entwickelt und steht nun vor der Herausforderung von LLVM. Glücklicherweise nimmt die GCC-Community Anpassungen vor, um die Entwicklung von GCC zu beschleunigen. Wir können erwarten, dass der Wettbewerb zwischen den beiden Kompilierungstechnologien Softwareentwicklern weiterhin bessere Compiler zur Verfügung stellen wird.

Entwicklungsgeschichte von Clang und LLVM

LLVM entstand aus der Forschung von Chris Lattner über UUIC im Jahr 2000. Chris Lattner wollte eine dynamische Kompilierungstechnologie für alle statischen und dynamischen Sprachen erstellen. LLVM ist eine Art Open-Source-Software, die unter der BSD-Lizenz entwickelt wurde. Die erste Version 1.0 wurde 2003 veröffentlicht. Im Jahr 2005 wurde Apple Inc. stellte Chris Lattner und sein Team ein, um Programmiersprachen und Compiler für Apple-Computer zu entwickeln, woraufhin die Entwicklung von LLVM auf die Überholspur ging. Ab LLVM 2.5 wurden jedes Jahr zwei kleinere LLVM-Versionen veröffentlicht (in der Regel im März und September). Im November 2011 wurde LLVM 3.0 als Standard-XCode-Compiler veröffentlicht. XCode 5 begann standardmäßig mit Clang und LLVM 5.0. Die Versionsrichtlinie wurde für LLVM 5.0 und spätere Versionen angepasst, und jedes Jahr werden zwei Hauptversionen veröffentlicht. Die aktuelle stabile Version ist 8.0.

Der Name LLVM wurde zuerst von Low Level Virtual Machine abgekürzt. Da dieses Projekt nicht auf die Erstellung einer virtuellen Maschine beschränkt ist, wird die Abkürzung LLVM häufig in Frage gestellt. Nach der Entwicklung von LLVM wurde es zu einem Sammelbegriff für viele Kompilierungstools und Low-Level-Tool-Technologien, wodurch der Name weniger angemessen wurde. Die Entwickler beschlossen, die Bedeutung dieser Abkürzung aufzugeben. Jetzt ist LLVM der offizielle Markenname, der für alle Projekte unter LLVM gilt, einschließlich LLVM Intermediate Representation (LLVM IR), LLVM Debugging Tools und LLVM C ++ Standardbibliotheken. LLVM kann als traditioneller Compiler, JIT-Compiler, Assembler, Debugger, statisches Analysetool und für andere Funktionen im Zusammenhang mit Programmiersprachen verwendet werden.Im Jahr 2012 gewann LLVM den Software System Award der Association for Computing Machinery (ACM), zusammen mit traditionellen Systemen wie UNIX, WWW, TCP / IP, TeX und Java. LLVM vereinfacht die Implementierung neuer Programmiersprachen-Toolketten erheblich. In den letzten Jahren haben viele neue Programmiersprachen wie Swift, Rust und Julia LLVM als Kompilierungsframework verwendet. Darüber hinaus ist LLVM zum Standard-Compiler für Mac OS X-, iOS-, FreeBSD- und Android-Systeme geworden.

Clang

Clang wurde entwickelt, um einen Frontend-Compiler bereitzustellen, der GCC ersetzen kann. Apple Inc. (einschließlich NeXT later) hat GCC als offiziellen Compiler verwendet. GCC hat sich als Standard-Compiler in der Open-Source-Community immer gut bewährt. Apple Inc. hat seine eigenen Anforderungen an Kompilierungstools. Auf der einen Seite Apple Inc. es wurden viele neue Funktionen für die Objective-C-Sprache (oder später sogar für die C-Sprache) hinzugefügt. Die GCC-Entwickler akzeptierten diese Funktionen jedoch nicht und wiesen der Unterstützung dieser Funktionen eine niedrige Priorität zu. Später wurden sie einfach in zwei Zweige für die separate Entwicklung unterteilt, und folglich die von Apple Inc. veröffentlichte GCC-Version. ist viel früher als die offizielle Version. Auf der anderen Seite ist der GCC-Code stark gekoppelt und schwer separat zu entwickeln. Darüber hinaus nimmt die Codequalität in späteren Versionen weiter ab. Allerdings sind viele Funktionen von Apple Inc. (wie verbesserte integrierte Entwicklungsumgebung (IDE) Unterstützung) muss GCC als Modul aufrufen, aber GCC bietet nie eine solche Unterstützung. Darüber hinaus schränkt die Befreiung der GCC-Laufzeitbibliothek die Entwicklung von LLVM GCC grundlegend ein. Auch durch die Lizenz beschränkt, Apple Inc. LLVM kann nicht verwendet werden, um die Codegenerierungsqualität basierend auf GCC weiter zu verbessern. Daher hat Apple Inc. beschlossen, das Frontend-Klirren von C, C ++ und Objective-C-Sprachen von Grund auf neu zu schreiben, um GCC vollständig zu ersetzen.

Wie der Name schon sagt, unterstützt Clang nur C, C ++ und Objective-C. Die Entwicklung begann 2007 und der C-Compiler wurde erstmals fertiggestellt. Clang für Objective-C wird 2009 vollständig für die Produktionsumgebung verwendet. Die Unterstützung für C ++ ging ebenfalls schnell voran. Clang 3.3 unterstützte C ++ 11 vollständig, Clang 3.4 unterstützte C ++ 14 vollständig und Clang 5 unterstützte C ++ 17 vollständig und alle waren zu diesem Zeitpunkt GCC deutlich voraus.

Clang/LLVM und GCC-Community

Wie andere Open-Source-Software-Communities wird die GCC-Community von Enthusiasten freier Software und Hackern dominiert. Im Entwicklungsprozess werden die GCC-Community-Management- und Partizipationsmechanismen heute schrittweise gebildet. Derzeit ist die GCC-Community eine relativ stabile und klar definierte Wissensgesellschaft, in der jede Person klare Rollen und Pflichten hat:Richard Stallman und Free Software Foundation (FSF): Obwohl Richard Stallman und die FSF selten in das GCC-Community-Management involviert sind, sind sie in Lizenz- und Rechtsangelegenheiten immer noch getrennt.

  • GCC-Industrieausschuss: Es verwaltet die GCC-Community-Angelegenheiten, technologieunabhängige GCC-Entwicklungsthemen sowie die Ernennung und Ankündigung von Reviewern und Betreuern. Sie hat derzeit 13 Mitglieder.
  • Globale Betreuer: Sie dominieren die GCC-Entwicklungsaktivitäten. Bis zu einem gewissen Grad bestimmen sie den Entwicklungstrend von GCC. Derzeit gibt es 13 globale Betreuer, die nicht alle im GCC Industrial Committee tätig sind.
  • Frontend-, Middle-End- und Backend-Betreuer: Sie sind die Betreuer von Frontend-, Backend- und anderen Modulen. Sie sind für den Code des entsprechenden GCC-Moduls verantwortlich, und viele von ihnen tragen maßgeblich zum Modulcode bei. Es ist erwähnenswert, dass Rezensenten im Allgemeinen in diese Gruppe eingeteilt werden. Der Unterschied besteht darin, dass Reviewer ihren eigenen Patch nicht genehmigen können, während Maintainer ihre eigenen Änderungen in ihrem Verantwortungsbereich ohne Zustimmung der Reviewer einreichen können.
  • Mitwirkende: Sie sind die umfangreichsten Entwicklergruppen in der GCC-Community. Nach der Unterzeichnung der Urheberrechtsvereinbarung kann jeder Entwickler die Erlaubnis zum Schreiben nach Genehmigung durch die Community beantragen und den Code dann selbst einreichen.
  • Wie andere Open-Source-Communities wird die ausgereifte GCC-Community nicht mehr von Hackern dominiert. Kommerzielle Unternehmen spielten eine wichtige Rolle in der Community, z. B. bei der Rekrutierung von Entwicklern und beim Sponsoring von Entwicklungstreffen. Derzeit wird die GCC-Community von den folgenden Arten von kommerziellen Unternehmen dominiert:

    • Systemanbieter, hauptsächlich RedHat und SUSE.
    • Chiphersteller, hauptsächlich Intel, ARM, AMD und IBM (PowerPC).
    • Spezialisierte Anbieter wie CodeSourcery und Tool Chain Service Provider wie AdaCore auf Basis der Ada-Sprache. CodeSourcery hatte eine brillante Geschichte und rekrutierte viele berühmte Entwickler, lehnte jedoch nach der Übernahme durch Mentor ab.

    In der aktuellen GCC-Community dominieren Chiphersteller die Backend-Entwicklung, während Systemanbieter andere Entwicklungsbereiche leiten. In Bezug auf die Community-Entwicklung wird der GCC-Code derzeit auf einem eigenen SVN-Server gehostet. Eine Git-API wird bereitgestellt, um die Entwicklung und Einreichung zu erleichtern. Die Patch-Überprüfung ähnelt der in der Linux-Kernel-Community und verwendet das Mailinglistenformular. Wie oben erwähnt, ist die GCC-Community eine relativ stabile (oder geschlossene) bekannte Gesellschaft. Die Community hat im Grunde genommen jedes Jahr 150 bis 200 aktive Mitwirkende und veranstaltet jedes Jahr im September eine Entwicklerkonferenz. Im September 2019 findet die Entwicklerkonferenz in Montreal, Kanada, statt.

    LLVM-Community

    Die LLVM-Community ist eine noob-freundliche Compiler-Community. Es reagiert schnell auf die Fragen neuer Benutzer und Patch-Reviews. Dies ist auch die Grundlage und Quelle für nachfolgende Diskussionen der LLVM Foundation und die Verabschiedung des LLVM Community Code of Conduct und führt zu einer Reihe politisch korrekter Diskussionen.

    Alle LLVM-Projekte und -Probleme werden über die DevExpress-E-Mail-Liste besprochen, und die Codeeinreichung wird über die Commits-E-Mail-Liste benachrichtigt. Alle Fehler und Funktionsänderungen werden über die Fehlerliste verfolgt. Die eingereichten Patches werden für die Master-Branches empfohlen. Der Stil entspricht den LLVM-Codierungsstandards und die Codeüberprüfung wird über Phabricator durchgeführt. Derzeit wurde das LLVM-Code-Repository nach GitHub migriert.

    Im Gegensatz zur GCC-Community hat die LLVM-Community nur die LLVM Foundation. Die LLVM-Stiftung hat acht Mitglieder. Neben der Verwaltung von LLVM-Community-Angelegenheiten muss jedes Mitglied der LLVM-Stiftung LLVM-Entwicklungsfragen im Zusammenhang mit Technologie leiten. Derzeit ist der Präsident Tanya Lattner, die Frau von Chris Lattner. Chris Lattner selbst ist ebenfalls Mitglied der Stiftung und hat eine starke Kontrolle über die LLVM-Community und die Entwicklungsrichtung von LLVM.

    Die Richtlinien zur Codeüberprüfung in der LLVM-Community sind im Grunde die gleichen wie in der GCC-Community. Der Unterschied besteht darin, dass aufgrund der schnellen Entwicklung von LLVM viele Mitwirkende keine Commit-Zugriffsberechtigung haben und ihren Code über die Betreuer einreichen müssen. Derzeit haben die Clang- und LLVM-Communities jedes Jahr mehr als 1.000 Mitwirkende. Im Allgemeinen finden Entwicklerkonferenzen jährlich im April und Oktober statt. Die Entwicklerkonferenz im Oktober 2019 findet in San Jose, USA, statt.

    Die LLVM-Lizenz wird von der UIUC-Lizenz zur Apache 2.0-Lizenz mit LLVM-Ausnahmen geändert. Es wird hauptsächlich verwendet, um das Problem zu lösen, dass die LLVM-Laufzeitbibliothek auf einer MIT-Lizenz basiert und die für das Projekt erforderliche Patentgenehmigung zu umfangreich ist. Unter dieser Lizenz erlaubt LLVM jedem, kommerzielle Produkte ohne Einschränkungen von LLVM abzuleiten, und erfordert nicht, dass Derivate Open-Source-Code bereitstellen, wodurch die umfassende Verwendung von LLVM gefördert wird, einschließlich:Das Herunterladen oder die Verwendung von LLVM ganz oder teilweise für persönliche, interne oder kommerzielle Zwecke. Die Möglichkeit, LLVM-Code zu ändern, ohne ihn wieder zum Projekt beizutragen.

  • Die Erstellung eines Pakets oder einer Release-Version, die LLVM enthält. Die Assoziation von LLVM mit Code, der von allen anderen wichtigen Open-Source-Lizenzen (einschließlich BSD, MIT, GPLv2 und GPLv3) autorisiert wurde.
  • Wenn Sie LLVM erneut verteilen, müssen Sie den Copyright-Hinweis beibehalten. Sie können den Copyright-Header nicht löschen oder ersetzen. Die Binärdatei, die LLVM enthält, muss den Copyright-Hinweis enthalten.
  • Leistung Vergleich zwischen GCC und LLVM

    Architektur: x86_64
    Prozessor: Intel (R) Xeon (R) Platin 8163 CPU @ 2,50 GHz
    L1 daten cache: 32 KB
    L2 cache: 1,024 KB
    L3 cache: 33,792 KB
    Speicher: 800 GB
    Betriebs system: 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 ist eine Reihe von CPU-Subsystem-Test-Tools zum Testen der CPU, Cache, Speicher und Compiler. Es enthält 43 Tests von vier Kategorien, einschließlich SPECspeed 2017 INT und FP, die die Integer-Geschwindigkeit und Gleitkomma-Betriebsgeschwindigkeit und SPECrate 2017 INT und FP testen, die die Integer-Parallelitätsrate und die Gleitkomma-Parallelitätsrate testen. Clang unterstützt die Fortran-Sprache nicht. Daher werden in diesem Beispiel die C / C ++ – Programme im SPEC Speed Test Set verwendet, um den Single-Core-Leistungsunterschied zwischen den von Clang und GCC generierten Binärprogrammen zu testen. Die folgende Tabelle listet die SPEZIFIKATION CPU2017 C und C ++ Sets:

    CINT2017 SpeedCFP2017 Speed600.perlbench_s619.lbm_s602.gcc_s644.nab_s605.mcf_s620.omnetpp_s623.in: xalancbmk_s625.x264_s631.deepsjeng_s641.leela_s657.xz_s

    Testmethoden

    Das LLVM-lnt-Automatisierungsframework wird verwendet, um den Test durchzuführen und die Leistung zu vergleichen. Es läuft auf die gleiche Weise wie runcpu der SPEC CPU. Bevor LLVM-lnt ausgeführt wird, wird der Cache (echo 3 > /proc/sys/vm/drop_caches) gelöscht und dann der Testdatensatz ausgeführt. Als nächstes wird der Reflex dreimal ausgeführt. Als Endergebnis wird der Mittelwert der drei ref-Testlaufergebnisse verwendet. Um Leistungsschwankungen durch CPU-Migration oder Kontextwechsel zu reduzieren, werden Prozesse, die auf dem Test-Dataset und dem Ref-Dataset ausgeführt werden, mithilfe des CPU-Affinitäts-Tools an einen CPU-Kern gebunden. Für den Kompilierzeittest verwendet diese Methode Thread 1, um das Testprogramm zu erstellen und die Testelemente zu vergleichen, die für eine lange Zeit kompiliert wurden. Die Kompilierungszeit enthält nicht die Ausführungszeit des Linkers. Es enthält nur die Zeit, zu der alle Quelldateien in allen Testprogrammen generiert werden.

    Vergleich der Kompilierungsleistung

    Der GCC-Kompilierungsprozess ist wie folgt: lesen Sie die Quelldatei, verarbeiten Sie die Quelldatei vor, konvertieren Sie sie in eine IR, optimieren Sie und generieren Sie eine Assemblydatei. Dann generiert der Assembler eine Objektdatei. Clang und LLVM sind nicht auf unabhängige Compiler angewiesen, sondern integrieren selbst implementierte Compiler im Backend. Das Generieren von Assemblydateien entfällt beim Generieren von Objektdateien. Die Objektdatei wird direkt aus dem IR generiert. Außerdem ist die Datenstruktur von LLVM IR im Vergleich zum GCC IR übersichtlicher. Es belegt weniger Speicher während der Kompilierung und unterstützt eine schnellere Durchquerung. Daher sind Clang und LLVM in Bezug auf die Kompilierungszeit vorteilhaft, was durch die aus der Spezifikationszusammenstellung erhaltenen Daten belegt wird, wie in der folgenden Abbildung gezeigt. Clang reduziert die Single-Thread-Kompilierungszeit im Vergleich zu GCC um 5% bis 10%. Daher bietet Clang mehr Vorteile für den Bau von Großprojekten.

    Vergleich kompilierungszeit

    Vergleich der Ausführungsleistung

    Die meisten Cloud-Workloads erfordern, dass die Anwendungen in verschiedenen Clustern ausgeführt werden können. Geben Sie beim Erstellen dieser Anwendungen keine maschinenbezogenen Parameter an. Um sich an die schnelle Iteration anzupassen, die durch Nachfrageänderungen verursacht wird, müssen auch externe Workloads debuggbar sein. Daher hat die Arbeitslast selbst neben einigen stabilen und gängigen Bibliotheken, die hohe Kompilierungsoptimierungsstufen ermöglichen, eine niedrige Kompilierungs- und Optimierungsstufe (O2 oder darunter). Um diese Anforderung zu erfüllen, vergleicht dieses Dokument die Leistung verschiedener Compiler auf den Optimierungsstufen O2 und O3 für INT-Speed-Programme, wie in der folgenden Abbildung dargestellt:

    Leistungsvergleich der SPEC CPU2017 INT Speed

    GCC hat für die meisten Programme auf O2- und O3-Ebene einen Leistungsvorteil von 1% bis 4% gegenüber Clang und LLVM und im Durchschnitt einen Leistungsvorteil von ungefähr 3% für die CPU2017 INT Speed. In Bezug auf 600.perlbench_s und 602.gcc_s / O2, GCC hat einen großen Leistungsvorteil (mehr als 10%). Diese beiden Testelemente haben keine herausragenden Hotspots und können den umfassenden Optimierungseffekt des Compilers widerspiegeln. Die Testergebnisse zeigen, dass GCC bei der Leistungsoptimierung immer von Vorteil ist. Allerdings für zwei AI-bezogene Programme, darunter 631.deepsjeng_s und 641.leela_s, die neu zum SPEC-Test hinzugefügt wurden, Clang und LLVM verbessern die Leistung im Vergleich zu GCC um mehr als 3%. Dies spiegelt auch den rasanten Fortschritt der LLVM in Bezug auf die Optimierung wider. Für die 625. x264_s O2-Optimierung, LLVM verbessert die Leistung um 40%, da der Hotspot des Gehäuses den vektorisierten Regeln entspricht. Clang und LLVM optimieren jedoch die Vektoren auf O2-Ebene, während GCC die Vektoren auf O3-Ebene optimiert. Mit Ausnahme von vektorisierten Programmen verbessert GCC die Leistung auf O3-Ebene im Vergleich zu O2-Ebene nicht wesentlich. Mit anderen Worten, die Programme reagieren nicht empfindlich auf die GCC O3-Optimierung. Im Gegensatz dazu verbessern Clang und LLVM die Leistung einiger Programme (z. B. 600. perlbench_s und 602. gcc_s) auf O3-Ebene.

    HPC-Programme wie FP Speed laufen in der Regel auf High-End-Servern. Sie verfügen über stabile Kernalgorithmen, hohe Anforderungen an die leistungsbezogene Vektorisierung und Parallelität und ermöglichen einen hohen Optimierungsgrad (O3 oder höher). Daher vergleicht dieses Dokument die Leistung auf der Optimierungsebene O3 + march = native (skylake-avx512), wie unten gezeigt:

    Leistungsvergleich von SPEC CPU2017 FP Geschwindigkeit

    Für die zwei FP programme, GCC auch können verbessern die leistung durch über 3%. Clang und LLVM sind in der Schleifenoptimierung konservativ und daher in der Leistung nicht vorteilhaft. Das Polly-Teilprojekt von Clang und LLVM bietet jedoch einen High-Level-Schleifen- und Datenlokalitätsoptimierer, der im maschinellen Lernen, im Hochleistungsrechnen und in der heterogenen Rechenoptimierung weit verbreitet ist. Ich glaube, dass Polly die Leistung von Programmen, die Hotspot-Schleifen enthalten, die den Vektorisierungs- und Parallelitätsregeln entsprechen, erheblich verbessern kann. Ich werde auch die Leistung von Polly in einer Reihe von Benchmarks und Workloads analysieren.

    Abschließende Bemerkungen

    Aus den obigen Benchmarking-Tests können wir sehen, dass Clang mehr Vorteile für die Konstruktion großer Projekte bietet, während GCC bei der Leistungsoptimierung immer von Vorteil ist. Die bla hängt von Ihrer spezifischen Anwendung ab

    Zusätzlich zum Leistungsvergleich möchte ich die Vor- und Nachteile von GCC und Clang und LLVM teilen:

    Vorteile von GCC

    • GCC unterstützt traditionellere Sprachen als Clang und LLVM, wie Ada, Fortran und Go.
    • GCC unterstützt mehr weniger populäre Architekturen und unterstützte RISC-V früher als Clang und LLVM.
    • GCC unterstützt mehr Spracherweiterungen und mehr Assemblersprachenfunktionen als Clang und LLVM. GCC ist immer noch die einzige Option zum Kompilieren des Linux-Kernels. Obwohl in der Branche auch über Forschungen zur Kernelkompilierung mit Clang und LLVM berichtet wird, kann der Kernel nicht kompiliert werden, ohne den Quellcode und die Kompilierungsparameter zu ändern.

    Vorteile von Clang und LLVM

    • Aufstrebende Sprachen verwenden die LLVM-Frameworks wie Swift, Rust, Julia und Ruby.
    • Clang und LLVM entsprechen den C- und C ++ – Standards strenger als GCC. GNU Inline und andere Probleme während des GCC-Upgrades treten nicht auf.
    • Clang unterstützt auch einige Erweiterungen, z. B. Attribute für die Thread-Sicherheitsprüfung.
    • Clang bietet zusätzliche nützliche Tools wie Scan-Build und clang static Analyzer für die statische Analyse, Clang-format und clang-tidy für die Syntaxanalyse sowie das Editor-Plug-in Clangd.
    • Clang bietet genauere und benutzerfreundlichere Diagnoseinformationen und hebt Fehlermeldungen, Fehlerzeilen, Fehlerzeilenaufforderungen und Reparaturvorschläge hervor. Clang betrachtet die Diagnoseinformationen als ein Merkmal. Die Diagnoseinformationen wurden erst ab GCC 5.0 verbessert und in GCC 8 ausgereift.

    (Originalartikel von Ma jun马骏)

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.