4

私の理解によると、複数のコンパイルユニットを備えたプログラムを作成する主な利点は、コンポーネントの再利用性と、小さな変更を組み込む場合のコンパイル時間の短縮です。

また、(おそらく間違って)これに関連するペナルティがあると思います。独自のコンパイル単位で定義された関数は「インライン」として宣言できません。
[このキーワードは実際にはコンパイラーにインライン展開関数を強制しないことを認識していますが、コンパイラーに最適化の柔軟性を与えるため、可能な限り含める価値があると理解しています。]

ここまでは順調ですね?

私の本当の質問は、プログラムが複雑なモデリングの問題を解決しているときに、費用便益分析が依然として複数のコンパイルユニットを優先するかどうかであり、有用な出力を生成するために、クラスター上でメインループを数か月繰り返す必要があります。

マルチコンパイルユニットプログラムのコンパイルには数分かかりますが、単一コンパイルユニットとして再構成された同じプログラムのコンパイルには数時間かかります...単一コンパイルユニットがすべての関数をインラインとして宣言し、最適化の機会が増える場合、余分なコンパイル時間を補うよりも、実行時間が数パーセント減少する可能性があることを期待するのは合理的だと思います。

このような状況に適した経験則はありますか、それとも状況に大きく依存しますか?

4

3 に答える 3

2

他の人がすでに述べたように、プログラムをさまざまなコンパイル単位に分解することの主な利点は、読みやすさです。コンパイル時間の短縮は、どういうわけかアイデアの素晴らしい副作用です。

インライン化が気になる場合は、リンクタイムコード生成とリンクタイム最適化を利用できます。コンパイル単位とLTOへのプログラム分解の組み合わせは理想的な解決策のように見えますが、関数の完全な定義が利用可能なときにコンパイラーによって実行される最適化の種類がLTOによって実行できるかどうかは明らかではありません。たとえば、LTOがC ++での戻り値の最適化をサポートできるかどうかはわかりません。これは、高レベルの抽象化で行われるためです。パフォーマンステストが必要です。(編集:RVOは、LTOやこのような高度なトリックがなくても、少なくともgccとclangで実行されます[試しました]。ほとんどの場合、この最適化は、関数のABIを変更することによって実行されます。これにより、関数で作成および返される必要のあるオブジェクトへの「非表示ポインター」が取得されます。)

調査する価値のある3番目の解決策は、 sqliteアマルガムのようなものを使用することです。これは、さまざまなコンパイル単位を1つの巨大な.cファイルに入れるプロセスです。とはいえ、ユーザーが作成したかなり重いインフラストラクチャを必要とするもののように見えます。

于 2012-07-26T06:55:24.417 に答える
2

一部のコンパイラ/リンカは、あるコンパイルユニットで定義され、別のコンパイルユニットで使用されている場合でも、関数を自動的にインライン化できます。Microsoftのリンカは確かにこれを行うことができます。

私にとって、コードを個別のコンパイルユニットに分割する主な利点は、コードの全体的な構成であり、私は常に、考慮事項ではなく、この事実に基づいて決定を下します。また、大規模なプログラムは、一度に複数の人が作業することが多いことを忘れないでください。明らかに、コンパイルユニットを分離することは大きなメリットです。

要するに、状況に大きく依存していると思います。しかし、あなたの状況はまれなものだと思います。

于 2012-07-26T06:24:56.263 に答える
0

80-20の法則を忘れないでください。プログラムの実行時間の80%は、コードの20%に費やされています。たぶん、あなたはそれらの20%を単一のコンパイルユニットに入れ、残りをうまく整理することができますか?

また、ソースの編成については、アルゴリズムをヘッダーに(テンプレートまたはインライン関数として)配置し、それらからソースを作成することができます。

于 2012-07-26T06:35:40.667 に答える