この質問はおそらくどういうわけか奇妙ですが、どのようにしてg ++のコンパイル時間を短縮できますか?私のC++コードは、ブーストとテンプレートを多用しています。ヘッダーファイルから可能な限り移動し、-jオプションを使用していますが、コンパイル(およびリンク)にはかなり時間がかかります。
コードを分析し、コンパイラのボトルネックを指摘するツールはありますか?または、コードで実行されているコンパイラを何らかの形でプロファイルできますか?コンパイラーコンソールのログをじっと見つめすぎているという印象を受けることがあるので、これは本当にいいことです。
私にとって最も便利だったもの:
-j3
makeのグローバル。ただし、Makefileで依存関係グラフが正しいことを確認してください。正しくない場合、問題が発生する可能性があります。-O0
実行速度やコードサイズをテストしていない場合(そして、コンピューターが(おそらく小さな)パフォーマンスヒットをあまり気にしないほど高速です)。ファイルをコンパイルするためにminutesについて話していると仮定します。つまり、プリコンパイル済みヘッダーまたはローカルディスクの問題は問題ではありません。
深いテンプレートコード(ブーストなど)での長いコンパイル時間は、テンプレートのインスタンス化に関しては、特に可変長テンプレートがテンプレートのデフォルト引数でエミュレートされる場合、gccの非友好的な漸近的な動作に根ざしています。
可変長テンプレートの動機として、コンパイル時間の短縮を挙げたドキュメントを次に示します。
cpptruthsには、gcc-4.5がこのためにどのように優れているか、および可変引数テンプレートでどのように見事に機能するかについての記事がありました。
IIRCの場合、BOOSTには擬似変数のテンプレートのデフォルトパラメータの生成を制限する方法があります。「g ++ -DBOOST_MPL_LIMIT_LIST_SIZE = 10」は機能するはずです(デフォルトは20)
UPDATE:ここでSO
UPDATE:これはテンプレートをコンパイルするときのパフォーマンスの問題に関するもので、受け入れられた答えはgcc-4.5も推奨しています。また、clangは肯定的な例として言及されています:
あなたが説明する非常によく似たシナリオ(ブースト、テンプレート、gcc)でビルドを高速化するために私がやったこと
他の誰もが追加したことやすでに行っていること(並列化ビルド、コンパイラオプションなど)に加えて、インターフェイスを介してアクセスされる実装クラスのテンプレートを非表示にすることを検討してください。つまり、次のようなクラスを持つ代わりに:
// ClsWithNoTemplates.h file, included everywhere
class ClsWithTemplates
{
ComplicatedTemplate<abc> member;
// ...
public:
void FunctionUsingYourMember();
};
あなたが持っている必要があります:
// 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
};
これはOOPデザインを少し変更しますが、それは良いことです: 'ClsWithNoTemplates'の定義を含めるとfastになり、 「ClsWithNoTemplates」を1回。
さらに、実装コードを変更した場合、ClsWithNoTemplates.hを含むコードを再定義する必要はおそらくないでしょう。
この変更により、部分的なコンパイル時間が劇的に長くなります。また、ClsWithNoTemplatesがライブラリファイルからエクスポートされたパブリックインターフェイスの場合にも役立ちます。実装を変更するだけではファイルは変更されないため、依存クライアントコードはまったく再コンパイルする必要があります。
PIMPLテクニックを試してください。この質問: C++のコンパイル時間を短縮するために使用できるテクニックは何ですか?
コンパイラは、何かをする必要があるたびに、ヘッダーファイルと実装のチェーンをたどることを防ぎます。
多くのファイルがある場合、他のすべての.cppファイルを#includeする1つの.cppファイルを用意するだけで、コンパイルを大幅に高速化できます。もちろん、これにはマクロをより注意する必要があり、他のcppファイルから見えるようにファイルごとにすでに定義されている必要があります。
多くのファイルがある場合、これによりコンパイル時間が大幅に短縮されます。
より少ないテンプレートとインライン関数をインスタンス化します。すべてをゼロからコンパイルするのではなく、できる限りプリコンパイルし、リンクするだけです。 GCCの最新バージョンを使用していることを確認してください。
ただし、C++が非常に複雑な言語であり、コンパイルにはかなりの時間がかかるというのは簡単な事実です。
このペーパー は、「従来の」非テンプレートオブジェクトファイルによく似たテンプレートコードのコンパイル方法を説明しています。テンプレートのインスタンス化ごとに1行のコードオーバーヘッドで、コンパイルとリンクの時間を節約します。
複数のコアを使用してg ++でコンパイルする
通常、コンパイルの最も費用のかかる部分は、(a)ソースファイルの読み取り([〜#〜] all [〜#〜])および(b)コンパイラを各ソースのメモリにロードすることです。ファイル。
52個のソース(.cc)ファイルがあり、それぞれが#includes 47個の#include(.h)ファイルを持っている場合、コンパイラーを52回ロードし、2496個のファイルを処理します。ファイル内のコメントの密度によっては、役に立たない文字を食べるのにかなりの時間を費やしている可能性があります。 (私が見たある組織では、ヘッダーファイルのコメントは66%から90%の間で変化し、ファイルの10%から33%のみが「意味のある」ものでした。最後のコメントをすべて削除し、コードのみを残します。)
プログラムがどのように物理的に編成されているかを詳しく見てください。ソースファイルを結合できるかどうかを確認し、#includeファイルの階層を単純化します。
何十年も前、IBMのような企業はこれを理解し、コンパイラーを作成して、1つのファイルだけでなく、コンパイルするファイルのリストをコンパイラーに渡し、コンパイラーを1回だけロードするようにしました。