Diese Frage ist vielleicht irgendwie seltsam, aber wie kann ich die Kompilierungszeit von g ++ beschleunigen? Mein C ++ - Code verwendet stark Boost und Vorlagen. Ich habe bereits so viel wie möglich aus den Header-Dateien entfernt und die Option -j verwendet, aber das Kompilieren (und Verknüpfen) dauert immer noch eine Weile.
Gibt es Tools, die meinen Code analysieren und auf Engpässe für den Compiler hinweisen? Oder kann man den Compiler, der auf meinem Code läuft, irgendwie profilieren? Das wäre wirklich schön, denn manchmal habe ich den Eindruck, dass ich zu viel Zeit damit verbracht habe, auf das Compiler-Konsolenprotokoll zu starren ...
c++
templates
g++
compilation
Danvil
quelle
quelle
Antworten:
Was war für mich am nützlichsten:
-j3
global zu machen. Stellen Sie jedoch sicher, dass Ihre Abhängigkeitsdiagramme in Ihrem Makefile korrekt sind. Andernfalls können Probleme auftreten.-O0
Sie diese Option, wenn Sie die Ausführungsgeschwindigkeit oder die Codegröße nicht testen (und Ihr Computer schnell genug ist, damit Sie sich nicht um den (wahrscheinlich kleinen) Leistungseinbruch kümmern).quelle
Folgendes habe ich getan, um Builds in einem sehr ähnlichen Szenario zu beschleunigen, das Sie beschreiben (Boost, Vorlagen, GCC).
quelle
ccache
Dies ist sehr hilfreich, wenn Sie DVCS verwenden oder in einem Team arbeiten, da in beiden Fällen die Datei wahrscheinlich bereits kompiliert wurde, obwohl sie von einem anderen Speicherort stammt.Ich gehe davon aus, dass es sich um Minuten zum Kompilieren einer Datei handelt, dh vorkompilierte Header oder lokale Festplattenprobleme sind nicht das Problem.
Lange Kompilierungszeiten mit tiefem Vorlagencode (Boost usw.) basieren häufig auf dem unfreundlichen asymptotischen Verhalten von gcc bei der Instanziierung von Vorlagen, insbesondere wenn verschiedene Vorlagen mit Standardargumenten für Vorlagen emuliert werden.
Hier ist ein Dokument, in dem die reduzierte Kompilierungszeit als Motivation für verschiedene Vorlagen genannt wird:
cpptruths hatte einen Artikel darüber, wie viel besser gcc-4.5 in diesem Zusammenhang ist und wie es mit seinen verschiedenen Vorlagen hervorragend funktioniert:
IIRC dann hat BOOST eine Möglichkeit, die Generierung von Template-Standardparametern für die Pseudovariadics zu begrenzen. Ich denke, 'g ++ -DBOOST_MPL_LIMIT_LIST_SIZE = 10' sollte funktionieren (der Standard ist 20).
UPDATE: Es gibt auch einen schönen Thread mit allgemeinen Techniken, um das Kompilieren hier auf SO zu beschleunigen, was nützlich sein könnte:
UPDATE: Hier geht es um die Leistungsprobleme beim Kompilieren von Vorlagen. In der akzeptierten Antwort wird auch gcc-4.5 empfohlen. Als positives Beispiel wird auch clang genannt:
quelle
Compilation time for code that uses templates should now scale linearly with the number of instantiations rather than quadratically, as template instantiations are now looked up using hash tables.
Wenn Sie viel neu kompilieren, kann Ccache hilfreich sein. Es beschleunigt die Kompilierung nicht wirklich, aber es gibt Ihnen ein zwischengespeichertes Ergebnis, wenn Sie aus irgendeinem Grund eine nutzlose Neukompilierung durchführen. Es mag den Eindruck erwecken, das falsche Problem zu lösen, aber manchmal sind die Wiederherstellungsregeln so kompliziert, dass Sie während eines neuen Builds tatsächlich denselben Kompilierungsschritt ausführen.
Zusätzliche Idee: Wenn Ihr Code mit clang kompiliert wird , verwenden Sie ihn stattdessen. Es ist normalerweise schneller als gcc.
quelle
Zusätzlich zu dem, was alle anderen hinzugefügt haben und was Sie bereits tun (parallelisierter Build, Compileroptionen usw.), sollten Sie Vorlagen in Implementierungsklassen ausblenden, auf die über Schnittstellen zugegriffen wird. Das bedeutet, dass anstelle einer Klasse wie:
// ClsWithNoTemplates.h file, included everywhere class ClsWithTemplates { ComplicatedTemplate<abc> member; // ... public: void FunctionUsingYourMember(); };
du solltest haben:
// ClsWithNoTemplates.h file: class ClsWithTemplatesImplementation; // forward declaration // definition included in the ClsWithNoTemplates.cpp file // this class will have a ComplicatedTemplate<abc> member, but it is only // included in your ClsWithNoTemplates definition file (that is only included once) class ClsWithNoTemplates { ClsWithTemplatesImplementation * impl; // no templates mentioned anywhere here public: void FunctionUsingYourMember(); // call impl->FunctionUsingYourMember() internally };
Dies ändert Ihr OOP-Design ein wenig, ist aber gut so: Die Definition von 'ClsWithNoTemplates' ist jetzt schnell und Sie kompilieren die Definition von 'ClsWithNoTemplates' nur einmal (vor).
Wenn Sie den Implementierungscode ändern, muss der Code, der ClsWithNoTemplates.h enthält, wahrscheinlich nicht neu definiert werden.
Diese Änderung sollte Ihre teilweise Kompilierungszeit drastisch verlängern und hilft auch in dem Fall, in dem Ihre ClsWithNoTemplates eine öffentliche Schnittstelle ist, die aus einer Bibliotheksdatei exportiert wird: Da die Datei nicht geändert wird, wenn Sie nur die Implementierung ändern, wird Ihr abhängiger Clientcode nicht verwendet. Es muss überhaupt nicht neu kompiliert werden.
quelle
Probieren Sie die PIMPL-Technik aus, diese Frage: Welche Techniken können verwendet werden, um die C ++ - Kompilierungszeiten zu beschleunigen?
Dadurch wird verhindert, dass der Compiler jedes Mal, wenn Sie etwas tun müssen, der Kette von Header-Dateien und Implementierungen folgt.
quelle
Wenn viele Dateien vorhanden sind, können Sie die Kompilierung erheblich beschleunigen, indem Sie nur eine CPP-Datei verwenden, die alle anderen CPP-Dateien enthält. Dies erfordert natürlich, dass Sie mit Makros vorsichtiger umgehen und diese bereits pro Datei definiert haben, da sie jetzt für andere CPP-Dateien sichtbar sind.
Wenn viele Dateien vorhanden sind, kann dies die Kompilierungszeit erheblich verkürzen.
quelle
Instanziieren Sie weniger Vorlagen und Inline-Funktionen. Kompilieren Sie so viel wie möglich vor und verknüpfen Sie es einfach, anstatt alles von Grund auf neu zu kompilieren. Stellen Sie sicher, dass Sie die neueste Version von GCC verwenden.
Es ist jedoch eine einfache Tatsache, dass C ++ eine unglaublich komplexe Sprache ist und das Kompilieren einige Zeit in Anspruch nimmt.
quelle
In diesem Dokument wird eine Methode zum Kompilieren von Vorlagencode beschrieben, ähnlich wie bei "herkömmlichen" Nicht-Vorlagen-Objektdateien. Spart Kompilierungs- und Verknüpfungszeit mit nur einer Codezeile pro Vorlageninstanziierung.
quelle
Normalerweise sind die teuersten Teile der Kompilierung (a) das Lesen der Quelldateien ( ALL ) und (b) Laden des Compilers in den Speicher für jede Quelldatei.
Wenn Sie 52 Quelldateien (.cc) haben, von denen jede # 47 # Einschlussdateien (.h) enthält, laden Sie den Compiler 52 Mal und durchsuchen 2496 Dateien. Abhängig von der Dichte der Kommentare in den Dateien verbringen Sie möglicherweise viel Zeit damit, nutzlose Zeichen zu essen. (In einer Organisation, die ich gesehen habe, variierten die Header-Dateien zwischen 66% und 90% der Kommentare, wobei nur 10% bis 33% der Datei "aussagekräftig" waren. Das Beste, was getan werden konnte, um die Lesbarkeit dieser Dateien zu verbessern, war Strip jeden letzten Kommentar auslassen und nur Code hinterlassen.)
Sehen Sie sich genau an, wie Ihr Programm physisch organisiert ist. Prüfen Sie, ob Sie Quelldateien kombinieren und Ihre Hierarchie der # include-Dateien vereinfachen können.
Vor Jahrzehnten haben Unternehmen wie IBM dies verstanden und ihre Compiler so geschrieben, dass dem Compiler eine Liste der zu kompilierenden Dateien übergeben werden konnte, nicht nur eine Datei, und der Compiler nur einmal geladen wurde.
quelle