コンパイラーは(C ++で)関数をインライン化するタイミングを決定しますか?
-
05-07-2019 - |
質問
inlineキーワードを使用したり、短いctorやgetterメソッドのクラス宣言にメソッドを配置したりできることは理解していますが、コンパイラはいつメソッドをインライン化するかについて最終決定を下しますか?
たとえば:
inline void Foo::vLongBar()
{
//several function calls and lines of code
}
コンパイラがコードを非効率的にすると考える場合、コンパイラはインライン宣言を無視しますか?
副次的な問題として、クラスの外で次のように宣言されたゲッターメソッドがある場合:
void Foo::bar() { std::cout << "baz"; }
コンパイラはこれをカバーの下にインライン化しますか?
解決
機能がインライン化されるかどうかは、一日の終わりに、完全に コンパイラ。通常、フローに関して関数が複雑であればあるほど、コンパイラーがインライン化する可能性は低くなります。再帰関数などの一部の関数は、単にインライン化できません。
関数をインライン化しない主な理由は、コードの全体サイズが大幅に増加し、IoTがプロセッサのキャッシュに保持されないことです。これは、実際には最適化ではなく、悲観的です。
プログラマーに足を踏み入れるか、他の場所で撃つことを決定させるために、関数を自分でインライン化することができます-関数の呼び出しサイトにある関数で実行されるコードを記述します。
他のヒント
はい、コードをインライン化するかどうかの最終決定はC ++コンパイラにあります。インラインキーワードは提案であり、要件ではありません。
Microsoft C ++コンパイラでこの決定がどのように処理されるかについての詳細を次に示します
すでに多くの人が投稿しているように、forceinlineのようなしっかりしたヒントを与えることができたとしても、最終決定は常にコンパイラ次第です。
論理的根拠の一部は、インライン化は自動的に「速くなる」ことではないということです。スイッチ。インライン化が多すぎると、コードが大きくなり、他の最適化に干渉する可能性があります。 インライン関数とパフォーマンスに関するC ++ FAQ Lite 。
他の人が指摘したように、 inline
キーワードは、コンパイラーにコードをインライン化するための単なる提案です。コンパイラーは、 inline
でマークされていないインラインコードではなく、コードを定期的にインライン化するため、キーワードは register
または(pre-C ++ 0x) auto
。
ただし、 inline
キーワードの効果は他にも1つあります。関数の linkage を external (デフォルトの関数)からインラインへ。インラインリンケージにより、各コンパイルユニットにオブジェクトコードの独自のコピーを含めることができ、リンカーに最終的な実行可能ファイルから冗長コピーを削除させることができます。それがテンプレートを思い出させるなら、はい、テンプレートもインラインリンケージを使用します。
はい、コンパイラが最終決定を下します。 VSでは、再帰関数を指定の深さにインライン化することもできます;)
#pragma inline_depth( [0... 255] )
5セントを追加するだけ...
インライン化に関する Guru of Week の記事は非常に便利です。
>覚えている限りでは、オブジェクトファイルをリンクし、リンクされているコードをインライン化できることがわかったときに、リンカでさえインライン化を行う可能性があることをどこかで読みました。
よろしく、
Ovanes
副次的な問題として、クラスの外で次のように宣言されたゲッターメソッドがある場合:
void Foo::bar() { std::cout << "baz"; }
コンパイラはこれをカバーの下にインライン化しますか?
状況によります。同じ翻訳単位( .cpp
ファイルとそのすべての#included定義)内のすべての呼び出し元に対して使用できます。ただし、翻訳ユニットの外部にその関数の呼び出し元が存在する可能性があるため、インライン化されていないバージョンをコンパイルする必要があります。高い最適化レベルで潜在的にこれを実際に見ることができます(実際にコンパイラーが実行できる場合)。 (特に:すべての.cppファイルを1つの.cppに#includeした場合と通常のレイアウトを比較した場合の結果を比較してください。
私の知る限り、for、whileなどのループが見つかった場合、コンパイラはインライン宣言した(またはクラス宣言内に記述した)関数を非インラインにします。 これは、コンパイラーがインライン関数で最後の発言権を持っている1つの例です。
本当に、積極的に、絶対に、コードをインライン化する必要がある場合、マクロは常に存在します。 Cは長年にわたってこれらをサポートしてきましたが、これらはコンパイル前の単なるテキスト置換であるため、実際に、何を書いてもインラインになります。
だからこそ、「インライン」キーワード(および場合によっては強制バリアント)に、標準的な強制方法を持たない余裕があります-いつでもマクロを書くことができます。
とはいえ、関数をインラインにすることが理にかなっているかどうかはコンパイラーがよく知っているので、インラインは他のコンパイラー最適化と相互作用できるため、inlineキーワードの方が良い場合がよくあります。