Le librerie solo per l'intestazione sono più efficienti?

38

Ipotesi

  1. Uno dei vantaggi delle librerie di solo header per C ++ è che non è necessario che siano compilati separatamente.

  2. In C e C ++ inline ha senso solo se la funzione è definita in un file di intestazione *.

  3. Tradizionalmente, in C, .c / .h è stato utilizzato il layout, in cui l'intestazione rappresenta l'interfaccia pubblica minima dell'unità di traduzione. Allo stesso modo, .cpp / hpp.

Domanda

Le librerie di sola intestazione sono generalmente più efficienti in termini di codice e tempi di esecuzione rispetto al layout tradizionale? Se è così, è questo a causa di ampie inlining o altre ottimizzazioni?

* - la definizione della funzione in un'intestazione consente al compilatore di vedere l'implementazione durante la compilazione di qualsiasi unità di traduzione e rende praticamente possibile il codice di inlining

    
posta Vorac 22.12.2015 - 08:22
fonte

2 risposte

39

One of the advantages of header-only libraries for C++ is that they do not need to be compiled separately

No, non è un vantaggio, al contrario - la parte principale della biblioteca deve essere compilata tutte le volte che viene inclusa, non solo una volta. Questo in genere aumenterà i tempi di compilazione. Tuttavia, se ti riferisci ai vantaggi elencati qui in Wikipedia : in questo articolo si parla di riduzione dei costi amministrativi relativi al intero processo di compilazione, confezionamento e distribuzione.

In C and C++ inline makes sense only if the function is defined in a header file*

Dipende dal sistema del compilatore / linker, ma suppongo che per la maggior parte dei compilatori C e C ++ questo sia vero.

Traditionally, in C, .c/.h layout has been used, where the header represents the minimal public interface of the translation unit. Similarly, .cpp/hpp.

Questo è per lo più corretto. Le intestazioni di classe C ++ spesso contengono più dell'interfaccia pubblica minima - in genere contengono anche molte cose private. Per mitigare questo, vengono utilizzate cose come linguaggio PIMPL . Questo è qualcosa come "il contrario" di una libreria di sola intestazione, cerca di minimizzare il contenuto dell'header necessario.

Ma per rispondere alla tua domanda principale: questo è un compromesso. Più il codice di libreria si inserisce nei file di intestazione, più il compilatore ha una possibilità di ottimizzare il codice per la velocità (se ciò accade realmente, o se l'aumento è notevole, è una domanda completamente diversa) . D'altra parte, troppo codice nelle intestazioni aumenta il tempo di compilazione. Soprattutto nei grandi progetti C ++ questo può diventare un problema serio, vedi "Progettazione software C ++ su grande scala" di John Lakos - anche se il libro è un po 'obsoleto e alcuni dei problemi descritti in questo sono indirizzati dai compilatori moderni, le idee / soluzioni generali sono ancora valide.

In particolare, quando non si utilizza una libreria stabile (di terze parti), ma si sviluppano le proprie librerie durante il progetto, i tempi di compilazione diventano evidenti. Ogni volta che cambi qualcosa nella libreria, devi modificare un file di intestazione, che causerà una ricompilazione e un collegamento di tutte le unità dipendenti.

IMHO la popolarità delle librerie di sola intestazione è causata dalla popolarità della meta-programmazione dei template. Per la maggior parte dei compilatori, le librerie di modelli devono essere intestazione-solo perché il compilatore può solo avviare il processo di compilazione principale quando vengono forniti i parametri di tipo, e per la compilazione completa e l'ottimizzazione il compilatore deve vedere "entrambi contemporaneamente" - il codice della libreria più i valori dei parametri del modello. Ciò rende impossibile (o almeno difficile) produrre unità di compilazione "precompilate" per tale libreria.

    
risposta data 22.12.2015 - 08:44
fonte
13

Bene, per prima cosa demoliamo alcune delle tue ipotesi:

  1. One of the advantages of header-only libraries for C++ is that they do not need to be compiled separately.

Compilare le cose separatamente significa potenzialmente non dover ricompilare tutto se cambia solo una parte.
Quindi, uno svantaggio invece di un vantaggio.

  1. In C and C++ inline makes sense only if the function is defined in a header file*.

Sì, l'unico effetto che% co_de ha lasciato è l'eccezione alla regola a una definizione .
Guai a voi se quelle definizioni sono in ogni caso diverse.

Quindi, se una funzione è interna a un'unità di compilazione, contrassegnala inline . Ciò rende anche più probabile l'inlining, in quanto la funzione deve essere disponibile per poterla allineare.
Ancora, dai un'occhiata all'ottimizzazione del link-time, come supportato da almeno MSVC ++, gcc e clang.

  1. Traditionally, in C, .c/.h layout has been used, where the header represents the minimal public interface of the translation unit. Similarly, .cpp/hpp.

Beh, solo la presentazione dell'interfaccia minima è certamente uno degli obiettivi, per raggiungere una stabilità API e ABI più elevata e per ridurre al minimo i tempi di compilazione.

Soprattutto le classi C ++ non sono realmente orientate a questo, dato che tutti i bit privati perdono nell'intestazione, così come quelli protetti se vuoi derivarne o meno.

Il modello di progettazione PIMPL serve a ridurre tali dettagli.

La parte in cui l'interfaccia di separazione e l'implementazione falliscono completamente in C ++ sono comunque i modelli.
Il comitato ha cercato di fare qualcosa con modelli esportati , ma questo è stato abbandonato come troppo complicato e non funziona davvero.

Ora stanno lavorando su un adeguato sistema di moduli , anche se è lento. Ciò riduce drasticamente i tempi di compilazione e dovrebbe anche aumentare la stabilità dell'API e dell'ABI diminuendo la loro superficie.

Are header-only libraries generally more efficient code- and execution time wise than the traditional layout? If so, is this because of extensive inlining or other optimizations?

Le librerie di solo intestazioni possono essere più efficienti in termini di dimensioni del codice e tempi di esecuzione, sebbene ciò dipenda dal fatto che la libreria sia condivisa, da quanta ne viene utilizzata, in che modo e se l'inlining dimostra una vittoria decisiva in quel caso specifico.

E il motivo per cui l'inline è così importante per l'ottimizzazione non è perché l'inlining stesso è un così grande impulso, ma a causa delle opportunità di propagazione costante e dell'ulteriore ottimizzazione si apre.

    
risposta data 22.12.2015 - 11:55
fonte

Leggi altre domande sui tag