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++ fornisce interfacce utente grafiche (GUI) ed è facile da eseguire il debug, ma non è adatto per piattaforme Linux. Pertanto, questo documento confronta principalmente GCC con Clang / LLVM.

GCC è un compilatore di linguaggio di programma sviluppato da GNU. Si tratta di un insieme di software libero rilasciato sotto la GNU General Public License (GPL) e GNU Lesser General Public License (LGPL). È un compilatore ufficiale per i sistemi GNU e Linux e un compilatore principale per la compilazione e la creazione di altri sistemi operativi UNIX.

LLVM contiene una serie di componenti modularizzati del compilatore e catene di strumenti. Può ottimizzare i linguaggi di programmazione e i collegamenti durante la compilazione, il runtime e il tempo di inattività e generare codice. LLVM può servire come sfondo per i compilatori in più lingue. Clang è un compilatore C, C++, Objective-C o Objective-C++ compilato in C++ basato su LLVM e rilasciato sotto licenza Apache 2.0. Clang pricipalmente è usato per fornire la prestazione superiore a quella di GCC.

Attraverso lo sviluppo e l’iterazione a lungo termine, GCC, Clang e LLVM sono diventati compilatori maturi nel settore. Quindi, quale compilatore è migliore? Quale dovremmo usare per compilare e costruire programmi e sistemi?

Significato di un buon compilatore

I processori moderni hanno tutti pipeline superscalari e lunghe e strutture interne complesse e supportano unità di estensione vettoriale nell’architettura CISC (Complex Instruction Set Computer) o RISC (Reduced Instruction Set Computer). Per molti programmi che contengono kernel ad alta intensità di calcolo generale, i programmatori possono utilizzare i comandi di estensione vettoriale per migliorare notevolmente le prestazioni di esecuzione del programma. Ad esempio, nelle operazioni di matrice e vettore, i comandi di moltiplicazione e addizione combinati vengono utilizzati per migliorare le prestazioni e la precisione. I comandi Bit mask vengono utilizzati per l’elaborazione delle diramazioni nelle operazioni vettoriali. Tuttavia, per ottenere le massime prestazioni, programmatori e compilatori devono ancora impiegare un grande sforzo per gestire attività con modalità di accesso alla memoria complesse e kernel non standard.

Inoltre, gli standard dei moderni linguaggi avanzati astraggono costantemente i dettagli dell’hardware e delle strutture dati sottostanti per generare codice generale più logico e matematico, invece di istruzioni operative specifiche e percorsi di accesso alla memoria. Gli standard C++ sono sempre più espressivi e astratti. Python è popolare perché è più leggibile ed espressivo, anche a costo di una velocità di esecuzione inferiore. Una maggiore espressività aumenta il carico del compilatore per generare un buon codice assembly dalle strutture complesse compilate dai programmatori. Il compilatore deve essere più intelligente e lavorare di più per massimizzare le prestazioni utilizzando il codice. Non tutti i compilatori possono farlo. Quando si seleziona un compilatore, dobbiamo prima considerare se lo stesso segmento di codice può generare comandi di assemblaggio più efficienti.

Oltre a generare programmi eseguibili ad alte prestazioni, i compilatori moderni devono anche avere prestazioni elevate. Un progetto software di grandi dimensioni in C++ può contenere da centinaia a migliaia di unità di traduzione individuali. Ogni unità di traduzione può contenere migliaia di righe di codice. Il codice C++ può anche utilizzare un gran numero di tecnologie di programmazione basate su modelli. Queste tecnologie richiedono al compilatore di trasferire più volte le informazioni rilevanti per generare un file di destinazione. La compilazione di progetti C++ di grandi dimensioni può richiedere diverse ore e durante lo sviluppo devono essere presentate contemporaneamente più modifiche reciprocamente dipendenti. Ogni invio richiede agli sviluppatori di ricompilare la maggior parte delle librerie di codice. Pertanto, compilatori più veloci (strumenti di compilazione) sono fondamentali per ottenere un’elevata produttività per i team di grandi dimensioni.

In termini di estensione del linguaggio, i moderni sistemi di calcolo con più kernel, capacità di elaborazione vettoriale e acceleratori forniscono capacità superiori alle capacità naturali dei comuni linguaggi di programmazione. Pertanto, specifici framework di calcolo ad alte prestazioni (HPC), come OpenMP e OpenACC, possono colmare questa lacuna. Questi framework forniscono API (Application Program Interfaces) che i programmatori possono utilizzare per esprimere il parallelismo nel codice. Il compilatore e la libreria di runtime corrispondente devono mappare il codice parallelo all’architettura del processore. Molti progetti HPC dipendono dagli standard OpenMP e OpenACC, che vengono estesi dagli sviluppatori e dai produttori di hardware. Pertanto, i compilatori devono tenere il passo con lo sviluppo di standard di estensione del linguaggio.

In conclusione, un buon compilatore ci consente di concentrarci sul processo di programmazione, piuttosto che combattere contro le sue carenze. Può supportare gli standard linguistici più recenti, generare comandi ottimizzati dal codice più astratto e compilare il codice sorgente in meno tempo.

GCC Development History

Prima di imparare GCC, è necessario prima capire il Progetto GNU. Richard Stallman lanciò il Progetto GNU nel 1984 per costruire un sistema software open source simile a UNIX. Il sistema operativo GNU non si è evoluto ampiamente nel tempo. Tuttavia, ha incubato molti strumenti software open source eccellenti e utili, come Make, Sed, Emacs, Glibc, GDB e GCC. Questi software GNU open source e kernel Linux insieme costituiscono il sistema GNU / Linux. All’inizio, GCC forniva compilatori stabili e affidabili, basati sul linguaggio di programmazione C, per il sistema GNU. Il suo nome completo è GNU C Compiler. In seguito, furono supportati altri linguaggi (come Fortran, Obj-C e Ada) e il nome completo di GCC cambiò in GNU Compiler Collection.

GCC-1.0 è stato rilasciato da Richard Stallman nel 1987, più di trent’anni fa. Dal punto di vista del software è molto vecchio. Qualcuno ha raccolto i record di sviluppo di GCC tra il 1989 e il 2012 e ha prodotto un video animato di trenta minuti (GNU Compiler Collection dev history 1989-2012), dimostrando intuitivamente il processo di sviluppo di GCC. Possiamo conoscere la storia dello sviluppo di GCC dalle sue versioni:

  • GCC-1.0: rilasciato da Richard Stallman nel 1987.
  • GCC-2.0: rilasciato nel 1992 e supportato C++. Più tardi, la comunità GCC fu divisa perché Richard Stallman definì GCC come un compilatore C affidabile del sistema GNU e pensò che GCC in quel momento fosse sufficiente per il sistema GNU e che l’attenzione allo sviluppo dovesse essere spostata da GCC al sistema GNU stesso. Altri importanti sviluppatori speravano di continuare a migliorare GCC e fare sviluppi più radicali e miglioramenti in vari aspetti. Questi sviluppatori attivi hanno lasciato la comunità GCC nel 1997 e hanno sviluppato il fork EGCS.
  • GCC-3.0: Ovviamente, gli sviluppatori avevano generalmente un forte desiderio di buoni compilatori. La forcella EGCS si è sviluppata senza problemi ed è stata riconosciuta da sempre più sviluppatori. Alla fine, EGCS è stato utilizzato come nuovo backbone GCC e GCC-3.0 è stato rilasciato nel 2001. La comunità divisa fu nuovamente fusa, ma l’influenza di Richard Stallman era stata indebolita in una certa misura. Inoltre, il Comitato industriale del CCG aveva iniziato a decidere la direzione di sviluppo del CCG.
  • GCC-4.0: rilasciato nel 2005. Questa versione è stata integrata in Tree Serial Storage Architecture (SSA), e GCC si è evoluto per essere un compilatore moderno.
  • GCC-5.0: rilasciato nel 2015. Successivamente, la politica di versione GCC è stata modificata e una versione principale è stata rilasciata ogni anno. Un vantaggio inaspettato è che il numero di versione corrisponde all’anno. Ad esempio, GCC-7 è stato rilasciato nel 2017 e GCC-9 è stato rilasciato nel 2019.

Ora, lo sviluppo di GCC è entrato nella “cronaca moderna”. Di fronte alla pressione competitiva di LLVM, la comunità GCC ha apportato attivamente molti aggiustamenti, come accelerare la compilazione e migliorare le informazioni di avviso di compilazione. Negli ultimi 30 anni, GCC si è evoluto da uno sfidante nel settore dei compilatori a un compilatore mainstream per sistemi Linux, e ora affronta la sfida di LLVM. Fortunatamente, la comunità GCC sta apportando modifiche per accelerare lo sviluppo di GCC. Possiamo aspettarci che la concorrenza tra le due tecnologie di compilazione continuerà a fornire agli sviluppatori di software compilatori migliori.

Storia di sviluppo di Clang e LLVM

LLVM è stato originato dalla ricerca di Chris Lattner su UUIC nel 2000. Chris Lattner voleva creare una tecnologia di compilazione dinamica per tutti i linguaggi statici e dinamici. LLVM è un tipo di software open source sviluppato sotto la licenza BSD. La versione iniziale 1.0 è stata rilasciata nel 2003. Nel 2005, Apple Inc. assunto Chris Lattner e il suo team per sviluppare linguaggi di programmazione e compilatori per i computer Apple, dopo di che lo sviluppo di LLVM è entrato nella corsia di sorpasso. A partire da LLVM 2.5, due versioni minori di LLVM sono state rilasciate ogni anno (generalmente a marzo e settembre). Nel novembre 2011, LLVM 3.0 è stato rilasciato per diventare il compilatore XCode predefinito. XCode 5 ha iniziato a utilizzare Clang e LLVM 5.0 per impostazione predefinita. Il criterio di versione è stato modificato per LLVM 5.0 e versioni successive e due versioni principali vengono rilasciate ogni anno. L’attuale versione stabile è 8.0.

Il nome di LLVM è stato inizialmente abbreviato da Macchina virtuale di basso livello. Poiché questo progetto non si limita alla creazione di una macchina virtuale, l’abbreviazione LLVM viene spesso messa in discussione. Dopo che LLVM è stato sviluppato, è diventato un termine collettivo per molti strumenti di compilazione e tecnologie di strumenti di basso livello, rendendo il nome meno appropriato. Gli sviluppatori hanno deciso di abbandonare il significato dietro questa abbreviazione. Ora LLVM è diventato il marchio ufficiale, applicabile a tutti i progetti sotto LLVM, tra cui LLVM Intermediate Representation (LLVM IR), LLVM debugging tools e LLVM C++ librerie standard. LLVM può essere utilizzato come compilatore tradizionale, compilatore JIT, assemblatore, debugger, strumento di analisi statica e per altre funzioni relative ai linguaggi di programmazione.

Nel 2012, LLVM ha vinto il software system Award of Association for Computing Machinery (ACM), insieme a sistemi tradizionali come UNIX, WWW, TCP / IP, TEX e Java. LLVM semplifica enormemente l’implementazione di nuove catene di strumenti per linguaggi di programmazione. Negli ultimi anni, molti nuovi linguaggi di programmazione come Swift, Rust e Julia hanno utilizzato LLVM come framework di compilazione. Inoltre, LLVM è diventato il compilatore predefinito per i sistemi Mac OS X, iOS, FreeBSD e Android.

Clang

Clang è progettato per fornire un compilatore frontend che può sostituire GCC. Apple Inc. (incluso il prossimo dopo) ha usato GCC come compilatore ufficiale. GCC ha sempre funzionato bene come compilatore standard nella comunità open source. Tuttavia, Apple Inc. ha i suoi requisiti per gli strumenti di compilazione. Da un lato, Apple Inc. aggiunte molte nuove funzionalità per il linguaggio Objective-C (o anche, più tardi, il linguaggio C). Tuttavia, gli sviluppatori di GCC non hanno accettato queste funzionalità e hanno assegnato una priorità bassa al supporto per queste funzionalità. Successivamente, sono stati semplicemente divisi in due rami per lo sviluppo separato, e di conseguenza la versione GCC rilasciata da Apple Inc. è molto prima della versione ufficiale. D’altra parte, il codice GCC è altamente accoppiato e difficile da sviluppare separatamente. Inoltre, nelle versioni successive, la qualità del codice continua a diminuire. Tuttavia, molte funzioni richieste da Apple Inc. (come il supporto IDE (Integrated Development Environment) migliorato) deve chiamare GCC come modulo, ma GCC non fornisce mai tale supporto. Inoltre, l’esenzione della libreria di runtime GCC limita fondamentalmente lo sviluppo di LLVM GCC. Anche limitato dalla licenza, Apple Inc. impossibile utilizzare LLVM per migliorare ulteriormente la qualità di generazione del codice basata su GCC. Pertanto, Apple Inc. ha deciso di scrivere il Clang frontend dei linguaggi C, C++ e Objective-C da zero per sostituire completamente GCC.

Come suggerisce il nome, Clang supporta solo C, C++ e Objective-C. Lo sviluppo è iniziato nel 2007 e il compilatore C è stato completato per la prima volta. Clang per Objective-C cloud essere completamente utilizzato per l’ambiente di produzione nel 2009. Anche il supporto per C++ è progredito rapidamente. Clang 3.3 pienamente supportato C++ 11, Clang 3.4 pienamente supportato C++ 14, e Clang 5 pienamente supportato C++ 17, e tutti erano significativamente più avanti di GCC in quel momento.

Clang/LLVM e Comunità GCC

Come altre comunità di software open source, la comunità GCC è dominata da appassionati di software libero e hacker. Nel processo di sviluppo, i meccanismi di gestione e partecipazione della comunità GCC si formano gradualmente oggi. Attualmente, la comunità GCC è una società di conoscenza relativamente stabile e ben definita in cui ogni persona ha ruoli e doveri chiari:

  • Richard Stallman e Free Software Foundation (FSF): Sebbene raramente coinvolti nella gestione della comunità GCC, Richard Stallman e FSF sono ancora distaccati negli affari legali e di licenza.
  • Comitato Industriale del CCG: Gestisce gli affari della comunità GCC, argomenti di sviluppo GCC indipendenti dalla tecnologia, e la nomina e l’annuncio di revisori e manutentori. Attualmente ha 13 membri.
  • Manutentori globali: dominano le attività di sviluppo del GCC. In una certa misura, determinano il trend di sviluppo di GCC. Attualmente, ci sono 13 manutentori globali, che non tutti detengono l’ufficio nel Comitato industriale GCC.
  • Frontend, middle-end e backend manutentori: sono i manutentori di frontend, backend e altri moduli. Sono responsabili del codice del modulo GCC corrispondente e molti di loro sono i principali contributori al codice del modulo. Vale la pena notare che i revisori sono generalmente classificati in questo gruppo. La differenza è che i revisori non possono approvare la propria patch, mentre i manutentori possono inviare le proprie modifiche all’interno del loro ambito di responsabilità senza l’approvazione dei revisori.
  • Contributori: sono i gruppi di sviluppatori più estesi nella comunità GCC. Dopo aver firmato il contratto di copyright, tutti gli sviluppatori possono richiedere il permesso di scrittura dopo l’approvazione da parte della comunità e quindi inviare il codice da soli.

Come altre comunità open source, la comunità GCC matura non è più dominata dagli hacker. Le aziende commerciali hanno iniziato a svolgere ruoli importanti nella comunità, come il reclutamento di sviluppatori e la sponsorizzazione di incontri di sviluppo. Attualmente, la comunità GCC è dominata dai seguenti tipi di società commerciali:

  • Fornitori di sistemi, tra cui principalmente RedHat e SUSE.
  • Fornitori di chip, tra cui principalmente Intel, ARM, AMD e IBM (PowerPC).
  • Fornitori specializzati, come CodeSourcery e fornitori di servizi di catena di strumenti come AdaCore basati sul linguaggio Ada. CodeSourcery ha avuto una storia brillante e ha reclutato molti sviluppatori famosi, ma ha rifiutato dopo che è stato acquisito da Mentor.

Nell’attuale comunità GCC, i fornitori di chip dominano lo sviluppo del back-end, mentre i fornitori di sistemi guidano altre aree di sviluppo. In termini di sviluppo della comunità, il codice GCC è attualmente ospitato sul proprio server SVN. Viene fornita un’API Git per facilitare lo sviluppo e l’invio. La revisione delle patch è simile a quella nella comunità del kernel Linux e utilizza il modulo della Mailing List. Come accennato in precedenza, la comunità GCC è una società di conoscenza relativamente stabile (o chiusa). La comunità ha fondamentalmente 150 a 200 contributori attivi ogni anno e tiene una conferenza degli sviluppatori nel mese di settembre di ogni anno. A settembre 2019, la conferenza degli sviluppatori si terrà a Montreal, in Canada.

Comunità LLVM

La comunità LLVM è una comunità compilatore noob-friendly. Risponde rapidamente alle domande dei nuovi utenti e alle recensioni delle patch. Questa è anche la base e la fonte per le successive discussioni della Fondazione LLVM e l’adozione del Codice di condotta comunitario LLVM, e provoca una serie di discussioni politicamente corrette.

Tutti i progetti e i problemi di LLVM vengono discussi tramite l’elenco e-mail DevExpress e l’invio del codice viene notificato tramite l’elenco e-mail commit. Tutti i bug e le modifiche alle funzionalità sono tracciati attraverso l’elenco dei bug. Le patch inviate sono consigliate per i rami master. Lo stile è conforme agli standard di codifica LLVM e la revisione del codice viene eseguita tramite Phabricator. Attualmente, il repository di codice LLVM è stato migrato a GitHub.

A differenza della comunità GCC, la comunità LLVM ha solo la Fondazione LLVM. La Fondazione LLVM ha otto membri. Oltre a gestire gli affari della comunità LLVM, ogni membro della Fondazione LLVM deve guidare le questioni di sviluppo LLVM relative alla tecnologia. Attualmente, il presidente è Tanya Lattner, la moglie di Chris Lattner. Chris Lattner stesso è anche un membro della fondazione e ha un forte controllo sulla comunità LLVM e la direzione di sviluppo di LLVM.

La politica di revisione del codice nella comunità LLVM è fondamentalmente la stessa di quella nella comunità GCC. La differenza è che, a causa del rapido sviluppo di LLVM, molti contributori non hanno il permesso di accesso al commit e devono inviare il loro codice attraverso i manutentori. Attualmente, le comunità Clang e LLVM hanno più di 1.000 contributori ogni anno. Generalmente, le conferenze degli sviluppatori si tengono ogni anno in aprile e ottobre. La conferenza degli sviluppatori di ottobre 2019 si terrà a San Jose, negli Stati Uniti.

La licenza LLVM viene modificata dalla licenza UIUC alla licenza Apache 2.0 con eccezioni LLVM. Viene utilizzato principalmente per risolvere il problema che la libreria di runtime LLVM è basata su licenza MIT e l’autorizzazione di brevetto richiesta per il progetto è troppo ampia. Sotto questa licenza, LLVM consente a chiunque di derivare prodotti commerciali da LLVM senza alcuna restrizione e non richiede che eventuali derivati forniscano codice open source, promuovendo così l’ampio uso di LLVM, tra cui:

  1. Il download o l’utilizzo di LLVM in tutto o in parte per scopi personali, interni o commerciali. La possibilità di modificare il codice LLVM senza contribuire di nuovo al progetto.
  2. La creazione di un pacchetto o versione di rilascio contenente LLVM. L’associazione di LLVM con il codice autorizzato da tutte le altre principali licenze open source (tra cui BSD, MIT, GPLv2, e GPLv3).
  3. Quando si distribuisce nuovamente LLVM, è necessario conservare l’avviso di copyright. Non è possibile eliminare o sostituire l’intestazione del copyright. Il file binario contenente LLVM deve contenere l’avviso di copyright.

Confronto di Prestazioni tra GCC e LLVM

Architettura: x86_64
Processore: Intel (R) Xeon (R) Platinum 8163 CPU @ 2.50 GHz
cache L1 dati: 32 KB
L2 cache: 1.024 KB
cache L3: 33,792 KB
Memoria: 800 GB
sistema Operativo: Alibaba Group Enterprise Linux Server release 7.2 (Paladino)
Kernel: 4.9.151–015.ali3000.alios7.x86_64
Compilatore: Clang/LLVM 8.0 GCC8.3.1

Benchmark

SPEC CPU 2017 è un insieme di strumenti di test sottosistema CPU per testare la CPU, cache, memoria e compilatore. Contiene 43 test di quattro categorie, tra cui SPECspeed 2017 INT e FP che testano la velocità intera e la velocità di funzionamento in virgola mobile e SPECrate 2017 INT e FP che testano il tasso di concorrenza intero e il tasso di concorrenza in virgola mobile. Clang non supporta il linguaggio Fortran. Pertanto, in questo esempio, i programmi C / C ++ nel set di test di velocità SPEC vengono utilizzati per testare la differenza di prestazioni single-core tra i programmi binari generati da Clang e GCC. La seguente tabella elenca le SPECIFICHE CPU2017 C e C++ set:

CINT2017 SpeedCFP2017 Speed600.perlbench_s619.lbm_s602.gcc_s644.nab_s605.mcf_s620.omnitpp_s623.xalancbmk_s625.x264_s631.deepsjeng_s641.leela_s657.xz_s

Metodi di test

Il framework di automazione LLVM-lnt viene utilizzato per eseguire il test e confrontare le prestazioni. Funziona allo stesso modo di runcpu della CPU SPECIFICA. Prima dell’esecuzione di LLVM-lnt, la cache (echo 3> /proc/sys/vm/drop_caches) viene cancellata e quindi viene eseguito il set di dati di test. Successivamente, il set di dati ref viene eseguito tre volte. Il valore medio dei tre risultati dell’esecuzione del test ref viene utilizzato come risultato finale. Per ridurre le fluttuazioni delle prestazioni causate dalla migrazione della CPU o dal cambio di contesto, i processi in esecuzione sul set di dati di test e sul set di dati ref sono associati a un core della CPU utilizzando lo strumento Affinità CPU. Per il test del tempo di compilazione, questo metodo utilizza il thread 1 per creare il programma di test e confrontare gli elementi di test che sono stati compilati per un lungo periodo. Il tempo di compilazione non include il tempo di esecuzione del linker. Include solo il momento in cui vengono generati tutti i file di origine in tutti i programmi di test.

Confronto delle prestazioni di compilazione

Il processo di compilazione GCC è il seguente: leggere il file di origine, pre-elaborare il file di origine, convertirlo in un IR, ottimizzare e generare un file di assieme. Quindi l’assemblatore genera un file oggetto. Clang e LLVM non si basano su compilatori indipendenti, ma integrano compilatori auto-implementati nel back-end. Il processo di generazione dei file assembly viene omesso nel processo di generazione dei file oggetto. Il file oggetto viene generato direttamente dall’IR. Inoltre, rispetto al GCC IR, la struttura dei dati di LLVM IR è più concisa. Occupa meno memoria durante la compilazione e supporta l’attraversamento più veloce. Pertanto, Clang e LLVM sono vantaggiosi in termini di tempo di compilazione, che è dimostrato dai dati ottenuti dalla compilazione delle SPECIFICHE, come mostrato nella figura seguente. Clang riduce il tempo di compilazione a thread singolo dal 5% al 10% rispetto a GCC. Pertanto, Clang offre più vantaggi per la costruzione di grandi progetti.

Confronto dei SPEC tempo di compilazione

il Confronto tra le Prestazioni di Esecuzione

la Maggior parte dei cloud carichi di lavoro richiedono che le applicazioni possono essere eseguite in diversi gruppi. Durante la creazione di queste applicazioni, non specificare i parametri relativi alla macchina. Per adattarsi alla rapida iterazione causata dalle variazioni della domanda, i carichi di lavoro fuori sede devono essere debuggabili. Pertanto, a parte alcune librerie stabili e comuni che consentono livelli di ottimizzazione della compilazione elevati, il carico di lavoro stesso ha un livello di compilazione e ottimizzazione basso (O2 o inferiore). Per soddisfare questo requisito, questo documento confronta le prestazioni di diversi compilatori ai livelli di ottimizzazione O2 e O3 per i programmi INT Speed, come mostrato nella figura seguente:

confronto delle Prestazioni di SPEC CPU2017 INT Velocità

GCC è un 1% al 4% il vantaggio di prestazioni rispetto Clang e LLVM per la maggior parte dei programmi di O2 e O3 livelli, e, in media, ha circa 3% di rendimento in vantaggio per SPEC CPU2017 INT Velocità. In termini di 600.perlbench_s e 602.gcc_s / O2, GCC ha un grande vantaggio prestazionale (oltre il 10%). Questi due elementi di test non hanno hotspot in sospeso e possono riflettere l’effetto di ottimizzazione completo del compilatore. I risultati dei test mostrano che GCC è sempre vantaggioso nell’ottimizzazione delle prestazioni. Tuttavia, per due programmi AI-correlati, tra cui 631.deepsjeng_s e 641.leela_s, che sono appena aggiunti al test delle SPECIFICHE, Clang e LLVM migliorano le prestazioni di oltre il 3% rispetto a GCC. Ciò riflette anche il rapido progresso di LLVM in termini di ottimizzazione. Per il 625. ottimizzazione x264_s O2, LLVM migliora le prestazioni del 40% perché l’hotspot del caso è conforme alle regole vettorializzate. Ma Clang e LLVM ottimizzano i vettori a livello O2, mentre GCC ottimizza i vettori a livello O3. Ad eccezione dei programmi vettorializzati, GCC non migliora notevolmente le prestazioni a livello O3 rispetto a quelle a livello O2. In altre parole, i programmi non sono sensibili all’ottimizzazione GCC O3. Al contrario, Clang e LLVM migliorano significativamente le prestazioni di alcuni programmi (come 600. perlbench_s e 602. gcc_s) a livello O3.

I programmi HPC, come la velocità FP, generalmente vengono eseguiti su server di fascia alta. Hanno algoritmi core stabili, requisiti elevati per la vettorizzazione e il parallelismo correlati alle prestazioni e consentono elevati livelli di ottimizzazione (O3 o superiore). Pertanto, questo documento confronta le prestazioni al livello di ottimizzazione O3 + march = native (skylake-avx512), come mostrato di seguito:

confronto delle Prestazioni di SPEC CPU2017 FP Velocità

Per i due FP programmi, GCC può anche migliorare le prestazioni di circa il 3%. Clang e LLVM sono conservativi nell’ottimizzazione del ciclo e quindi non vantaggiosi nelle prestazioni. Tuttavia, il sottoprogetto Polly di Clang e LLVM fornisce un ottimizzatore di loop e località di dati di alto livello che è stato ampiamente applicato nell’apprendimento automatico, nel calcolo ad alte prestazioni e nell’ottimizzazione del calcolo eterogeneo. Credo che Polly possa migliorare notevolmente le prestazioni dei programmi che contengono loop hotspot conformi alle regole di vettorizzazione e parallelismo. Analizzerò anche le prestazioni di Polly in una serie di benchmark e carichi di lavoro.

Osservazioni conclusive

Dai test di benchmarking di cui sopra, possiamo vedere che Clang offre più vantaggi per la costruzione di grandi progetti mentre GCC è sempre vantaggioso nell’ottimizzazione delle prestazioni. Il bla dipende dalla tua applicazione specifica

Oltre al confronto delle prestazioni, vorrei condividere i vantaggi e gli svantaggi di GCC e Clang e LLVM:

Vantaggi di GCC

  • GCC supporta linguaggi più tradizionali di Clang e LLVM, come Ada, Fortran e Go.
  • GCC supporta più architetture meno popolari e supporta RISC-V prima di Clang e LLVM.
  • GCC supporta più estensioni del linguaggio e più funzioni del linguaggio assembly rispetto a Clang e LLVM. GCC è ancora l’unica opzione per la compilazione del kernel Linux. Sebbene la ricerca sulla compilazione del kernel utilizzando Clang e LLVM sia riportata anche nel settore, il kernel non può essere compilato senza modificare il codice sorgente e i parametri di compilazione.

I vantaggi di Clang e LLVM

  • Le lingue emergenti utilizzano i framework LLVM, come Swift, Rust, Julia e Ruby.
  • Clang e LLVM sono conformi agli standard C e C ++ in modo più rigoroso rispetto a GCC. GNU Inline e altri problemi durante l’aggiornamento GCC non si verificano.
  • Clang supporta anche alcune estensioni, come gli attributi per il controllo di sicurezza del thread.
  • Clang fornisce ulteriori strumenti utili, come scan-build e clang static analyzer per l’analisi statica, clang-format e clang-tidy per l’analisi della sintassi, così come l’editor plug-in Clangd.
  • Clang fornisce informazioni diagnostiche più accurate e amichevoli e mette in evidenza messaggi di errore, righe di errore, prompt di riga di errore e suggerimenti di riparazione. Clang considera le informazioni diagnostiche come una caratteristica. Le informazioni diagnostiche iniziarono a essere migliorate solo da GCC 5.0 e divennero mature in GCC 8.

(Articolo originale di Ma Jun马骏)

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *