6

速度のみを最適化しようとしていることを考えると、関数をインライン化するかどうかを決定するための優れたヒューリスティックは何ですか? 明らかにコードサイズは重要ですが、(たとえば) gcc または icc が関数呼び出しをインライン化するかどうかを決定するときに通常使用される他の要因はありますか? この分野で重要な学術研究はありましたか?

4

4 に答える 4

8

ウィキペディアにはこれに関する いくつかの段落があり、下部にいくつかのリンクがあります。

  • メモリ サイズとキャッシュの問題に加えて、もう 1 つの考慮事項はレジスタ プレッシャです。コンパイラの観点からは、「インライン化されたプロシージャから追加された変数は、追加のレジスタを消費する可能性があり、レジスタのプレッシャーがすでに高い領域では、これによりスピルが強制され、追加の RAM アクセスが発生する可能性があります。」

仮想メソッドは静的に認識されないため、JIT コンパイラとランタイム クラス ロードを備えた言語には他のトレードオフがありますが、JIT はメソッド呼び出し頻度などのランタイム プロファイリング情報を収集できます。

  • ジャストインタイム コンパイラでの最適化の設計、実装、および評価 (Java 用) では、静的メソッドと動的に読み込まれるクラスのメソッドのインライン化と、そのパフォーマンスの向上について説明しています。

  • Practice JUDO: Java Under Dynamic Optimizationsは、「インライン化ポリシーはコード サイズとプロファイリング情報に基づいている」と主張しています。メソッド エントリの実行頻度が特定のしきい値を下回ると、コールドと見なされるため、メソッドはインライン化されません。メソッド. コードの爆発を避けるため、バイトコード サイズが 25 バイトを超えるメソッドはインライン化しません. . . 深い呼び出しチェーンに沿ったインライン化を避けるため、呼び出しチェーンに沿ったインライン化されたバイトコード サイズの累積が 40 バイトを超えると、インライン化は停止します." ランタイム プロファイリング情報 (メソッド呼び出しの頻度) はありますが、肥大化を防ぐために、大きな関数や関数のチェーンをインライン化しないように注意しています。

Google Scholar で検索すると、次のような多数の論文が見つかります。

Google ブックスで検索すると、さまざまなコンテキストでの関数のインライン化に関する論文や章を含むかなりの数の本が見つかります。

  • Compiler Design Handbook: Optimizations and Machine Code Generationには、Compiler Design の統計的および機械学習手法に関する章があり、ヒューリスティックを使用してさまざまなパラメーターを設定し、結果をプロファイリングします。この章では、Vaswani らの論文Microarchitecture Sensitive Empirical Models for Compiler Optimizationsを参照して、「コンパイラー最適化のためのマイクロアーキテクチャーに敏感なモデルを構築するための経験的モデリング手法の使用」を提案しています。

  • ( C++ for Game Programmersなど、プログラマーの観点から inling について説明している本もあります。この本では、関数を頻繁にインライン展開することの危険性と、インライン展開とマクロの違いについて説明しています。コンパイラーは、プログラマーのインライン要求を判断できる場合、しばしば無視します良いことよりも悪いことの方が多いので、これは最後の手段としてマクロで無効にすることができます。)

于 2010-01-25T16:03:27.657 に答える
0

.NETでは、主にサイズに基づいています。親関数と子関数のサイズをコンパイル済みバイト単位で測定します。次に、結合された関数のサイズを測定します。組み合わせた関数が小さい場合は、インライン化をお勧めします。

これは、CPUのキャッシュにできるだけ多くのコードを押し込めるようにするためです。キャッシュミスは、最新のCPUの関数呼び出しよりもはるかにコストがかかります。

于 2010-01-25T05:28:26.380 に答える
0

私が見た限り、コンパイラがインラインを決定するために使用する唯一の要素は関数サイズです。ただし、ガイド付き最適化 (PGO) のプロファイルを実行する場合、コンパイラは呼び出し数/呼び出しセットアップ時間などの他の変数を使用できると思います。

于 2010-01-25T05:02:31.670 に答える
0

関数呼び出しは、いくつかの追加コードを意味します (新しいスタック フレームが設定される関数プロローグと、クリーンアップされる関数エピローグ)。プロローグやエピローグに比べて関数コードが小さいとコンパイラが判断した場合、コンパイラは実際の呼び出しを行う価値がないと判断し、関数をインライン化します。

関数をインライン化する代わりに呼び出すことの唯一の利点は、サイズに関連することです。関数をインライン化してからループを展開すると、サイズが大幅に増加する可能性があると思います。

于 2010-01-25T04:54:28.250 に答える