問題タブ [inlining]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
1 に答える
518 参照

c++ - C++ 関数のインライン化について

グローバル関数を強制的にインライン化するために MS 固有のキーワードを使用していますが、明示的な単純なデストラクタを持つオブジェクトを使用すると、関数がインライン化に失敗することに気付きました。

MSDNからの引用

を使用しても__forceinline、コンパイラはすべての状況でコードをインライン化できるわけではありません。次の場合、コンパイラは関数をインライン化できません。

  • 関数またはその呼び出し元は/Ob0(デバッグ ビルドの既定のオプション) でコンパイルされます。

  • 関数と呼び出し元は、異なるタイプの例外処理を使用します (一方は C++ 例外処理、もう一方は構造化例外処理)。

  • 関数には可変引数リストがあります。

  • /Og関数は、 、/Ox/O1、またはでコンパイルされていない限り、インライン アセンブリを使用します/O2

  • この関数は再帰的で、 を伴いません#pragma inline_recursion(on)。プラグマを使用すると、再帰関数はデフォルトの深さ 16 呼び出しにインライン化されます。インライン化の深さを減らすには、inline_depthpragma を使用します。

  • 関数は仮想であり、仮想的に呼び出されます。仮想関数への直接呼び出しはインライン化できます。

  • プログラムは関数のアドレスを取得し、呼び出しは関数へのポインターを介して行われます。アドレスが取得された関数への直接呼び出しは、インライン化できます。

  • この関数は、naked__declspec修飾子でもマークされています。

動作をテストするために、次の自己完結型プログラムを試しています

自明なデストラクタINLINE ~Spam() {}を配置すると、次の分解が行われます

デストラクタINLINE ~Spam() {}がない場合、次の逆アセンブリがあります

デストラクタが存在する場合、コンパイラが関数のインライン化に失敗する理由を理解できていませんT movz(T& t)

  • : 動作は 2008 年から 2013 年まで一貫しています。
  • 注意cygwin-gcc で確認しましたが、コンパイラはコードをインライン化します。現時点では他のコンパイラを確認できませんが、必要に応じて 12 時間以内に更新します
0 投票する
3 に答える
200 参照

java - 可視性と javac / JVM インライン化

メソッド/フィールドの可視性は、Java でのメソッドのインライン化にどのように影響しますか?

私が念頭に置いているケースは、フィールドのpublicゲッターのようなものです:private

ここでいくつかの問題が発生します。

1 つは、Java コンパイラ自体がインライン展開を行うかどうかです。この質問には、イエスと言う人もいればノーと言う人もいて、さまざまな答えがあるようです。以前はインライン化を行わなかったが、現在はインライン化を行っているためなのか、それとも正しい人もいれば間違っている人もいるというだけなのかはわかりません...

getBlah()さて、インライン化を行う場合、呼び出しをインライン化できない可能性があると考えるのは正しいでしょうか? メソッドは非常に単純であり、メソッドを呼び出すオーバーヘッドはメソッド自体のコードと同じくらい大きいため、これらはインライン化が有用な場所であることは明らかです。privateしかし、コンパイラによってインライン化された場合、フィールドに直接アクセスするバイトコードになってしまいます。そして確かにJVMは文句を言うでしょうか?(これは、このメソッドが であっても適用されstatic finalます。)

第二に、JIT コンパイラーはどうですか? 私が見る限り、そのレベルでのインライン化に関しては、この問題は当てはまりません。ネイティブ コードが生成されると、JVM はすでにチェックを行っており、メソッドを呼び出すことができることを確認しています (これは であるためpublic)。そのため、可視性の問題なしに、呼び出しをインライン化するネイティブ コードを生成できます...はい?

0 投票する
2 に答える
2422 参照

haskell - 関数型言語での部分評価と関数のインライン化の違いは何ですか?

0 投票する
0 に答える
64 参照

haskell - 繰り返し呼び出しのインライン化 (GHC)

GHCは複数回使用される関数をインライン化しますか? 例えば:

を呼び出すg innerLoopと、関数innerLoopは 3 回複製されますか? それともただになるのg stuff...でしょうか?

どうすればinnerLoop複数回インライン化するように強制したり、複数回インライン化されないようにすることができますか?

0 投票する
1 に答える
444 参照

c++ - 関数の定義に先行する呼び出しはインライン化できませんか?

gcc のドキュメントには、次の内容が含まれています。

関数がインラインと静的の両方である場合、関数へのすべての呼び出しが呼び出し元に統合され、関数のアドレスが使用されない場合、関数自体のアセンブラー コードが参照されることはありません。この場合、オプション -fkeep-inline-functions を指定しない限り、GCC は実際には関数のアセンブラー コードを出力しません。一部の呼び出しは、さまざまな理由で統合できません (特に、関数の定義に先行する呼び出しは統合できず、定義内の再帰呼び出しも統合できません)。

それは私にはいつもばかげているように思えました -- なぜ現代のコンパイラはそれほど馬鹿げているのでしょうか? 簡単なテストの後、それは真実ではないようです。

テストコード:

Linux での gcc-4.9.2 の結果には、 のコードが含まれていますが、 のコードは含まれてbar()いませんfoo()foo()統合されていることがわかります。

C++ としてコンパイルすると、名前マングリングを除いて、結果は同じです。

ドキュメントに反して、foo()の呼び出し後に定義されているにもかかわらずbar()foo()は完全に に統合されていbar()ます。

ドキュメントを誤解していますか、それとも間違っていますか? おそらく、より複雑なケースでは正しいでしょうか?

「統合」と「インライン」の間に技術的な違いがあるかどうかはわかりませんが、「統合」はキーワードinlineと区別するために使用されており、関数のインライン化を指しているだけだと思います(したがって、タイトル)。

この質問は C および C++ としてタグ付けされています。これは、gcc ドキュメントのこの部分が「C 言語ファミリー」に関連しており、回答が 2 つの言語で同じであると予想されるためです。

0 投票する
2 に答える
41 参照

c++ - オブジェクトの実際の型をテンプレート パラメーターとして指定できる場合の仮想関数のインライン化

仮想クラスCalculatorとそのクラスの実装例MyCalculatorがあります。

次の関数で示されているように使用すると、コンパイラは仮想であるためop1()、もちろんインライン化できません。op1()

ただし、場合によっては、calcAND の実際の型を知っていて、パフォーマンス上の理由からインライン化したいことがあります。そこで、次の案を考えます。

この関数を次のように呼び出します。

最初の例では、インライン化はできませんが、2 番目の例では、 op1()ofMyCalculatorは 内にインライン化する必要があると思いますcalculate()

私の仮定は本当ですか?

0 投票する
2 に答える
863 参照

c - gcc でパフォーマンスが大幅に低下します。インラインに関連している可能性があります

gcc現在、 (テスト済みバージョン:4.8.4)で奇妙な効果が発生しています。

かなり高速に実行されるパフォーマンス指向のコードがあります。その速度は、多くの小さな関数をインライン化することに大きく依存します。

複数の.cファイルにまたがるインライン化は難しいため (-fltoまだ広く利用できるようにはなっていません)、多くの小さな関数 (通常はそれぞれ 1 行から 5 行のコード) を共通の C ファイルに保存し、そこにコーデックを開発しています。関連するデコーダー。私の標準では「比較的」大きいですが (約 2000 行ですが、多くはコメントと空白行だけです)、小さな部分に分割すると新しい問題が発生するため、可能であればそれを避けたいと思います。

Encoder と Decoder は逆の操作であるため、関連しています。しかし、プログラミングの観点から見ると、これらは完全に分離されており、いくつかの typedef と非常に低レベルの関数 (整列されていないメモリ位置からの読み取りなど) を除いて、共通点はありません。

奇妙な効果はこれです:

fnew最近、エンコーダ側に新しい機能を追加しました。新しい「入り口」です。ファイル内のどこからも使用されず、呼び出されません.c

それが存在するという単純な事実は、デコーダー機能のパフォーマンスをfdec大幅に低下させ、20% 以上低下させます。これは、無視するには多すぎます。

ここで、エンコード操作とデコード操作は完全に分離されており、ほとんど何も共有されておらず、いくつかのマイナーな操作typedef(u32などu16) と関連する操作 (読み取り/書き込み) を除いて覚えておいてください。

新しいエンコーディング関数fnewを として定義するstaticと、デコーダのパフォーマンスがfdec向上し、通常の状態に戻ります。fnewから呼び出されないので.c、存在しないのと同じだと思います (デッド コードの削除)。

static fnewがエンコーダ側から呼び出されるようになった場合、 のパフォーマンスはfdec引き続き強力です。

しかし、fnew変更されるとすぐに、fdecパフォーマンスが大幅に低下します。

変更がしきい値を超えたと仮定して、次のパラメーターfnewを増やしました: (デフォルトでは、その値は 40 であると想定されています) 。gcc--param max-inline-insns-auto=60fdec

fnewそして、このゲームは、小さな変更やその他の類似のもののたびに永遠に続くと思います。さらに微調整が必​​要です.

これは単純に奇妙です。fnewfunction の小さな変更が、まったく関係のない function に影響を与えるという論理的な理由はありませんfdec。これは、関係だけが同じファイルにあるはずです。

これまでのところ、私が考案できる唯一の暫定的な説明は、単に存在するだけで、に影響を与えるfnew何らかの種類の を越えるのに十分であるということです。1. 存在しない、2.しかしどこからも呼び出されない、3 . インライン化できるほど小さい。しかし、それは問題を隠しているだけです。新しい機能を追加できないということですか?global file thresholdfdecfnewstaticstatic

本当に、ネットのどこにも満足のいく説明が見つかりませんでした。

誰かがすでに同等の副作用を経験しており、その解決策を見つけているかどうか知りたいと思っていました.

[編集]

もっとクレイジーなテストに行きましょう。今、私はただ遊ぶためだけに、まったく役に立たない別の関数を追加しています。内容は厳密には のコピペですfnewが、明らかに関数名が違うので としましょうwtf

wtf存在する場合、fnewが静的であるかどうかも、 の値が何であるかも問題ではありませんmax-inline-insns-auto。 のパフォーマンスはfdec正常に戻ります。どこからもwtf使用も呼び出しもされていませんが... :'(

【編集2】inline指示 がありません。すべての機能は通常またはstatic. インライン化の決定は、これまでのところ問題なく機能しているコンパイラの領域内でのみ行われます。

[編集 3] Peter Cordes が示唆したように、この問題はインラインではなく、命令の配置に関係しています。新しい Intel CPU (Sandy Bridge 以降) では、ホット ループは 32 バイト境界に揃えることでメリットがあります。問題は、デフォルトでは、gccそれらを 16 バイト境界に揃えることです。これにより、前のコードの長さに応じて、50% の確率で適切な位置合わせが行われます。したがって、「ランダムに見える」問題を理解するのは困難です。

すべてのループがセンシティブなわけではありません。これはクリティカル ループでのみ重要であり、アライメントが理想的ではない場合に、ループの長さが 32 バイトの命令セグメントをさらに 1 つ超える場合にのみ重要です。

0 投票する
1 に答える
289 参照

postgresql - PostgreSQL は、OFFSET 0 を使用してサブクエリのインライン化を防止します

評価されるたびにテーブル全体をスキャンする where 句にサブクエリがあります。

サブクエリの最後に OFFSET 0 を追加しても、クエリ プランに変更はありません。

この投稿を参照してください。この場合、where 句で最適化フェンス「OFFSET 0」は機能しませんか?