2016-08-10 10 views
0

x86 envでコンパイル・バリア(gcc)を使用した場合の副作用/実行時間のオーバーヘッドを調べていました。x86プロセッサ用のgccでコンパイル・バリアの実行時オーバーヘッド

コンパイラバリア:ASM揮発性(::: "メモリ")

GCCのドキュメントは、何か面白いもの(https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.htmlを)伝える

抜粋:

"メモリ" クロバーは、そのコンパイラに指示しますアセンブリコード は、入力オペランドと出力オペランドを にリストされているもの以外の項目にメモリの読み取りまたは書き込みを行います(たとえば、メモリのうちがputパラメーター)。 メモリに の正しい値が含まれていることを確認するには、asmを実行する前にGCCが特定のレジスタ値を メモリにフラッシュする必要があります。さらに、コンパイラは、 がasmの後に変更されずに残っていると仮定しません。必要に応じて再ロードします。 "メモリ"クローバーの使用 は、効果的にコンパイラの読み書きメモリバリアを形成します。

質問:

1)レジスタの値がフラッシュされますか?

2)なぜフラッシュする必要がありますか?

3)例?

4)レジスタフラッシュとは別のオーバーヘッドはありますか?

+1

実際に同じページを読むと、関連する例が表示されます。どのレジスタがメモリにフラッシュされる必要があるかは、実際にレジスタに何が行われているかによって異なります。 –

+2

最大限のパフォーマンスを得るために、コンパイラは可能な限りレジスタに値を保持する(理想的には範囲外になるまで)値を保持するコードを生成しようとします。レジスタがなくなるとメモリにフラッシュするだけです。 (考える:fwrite)、または明示的にそれらをフラッシュするように指示されたとき(メモリクローバー、関数呼び出しなど)この '呼び出し'から実際のアセンブラ命令が生成されないことに注意してください。たとえその方法が最も効率的であるとコンパイラには見えないとしても、その時点でコードを特定の方法で編成する必要があることをコンパイラに伝えるだけです。 –

答えて

2

別のスレッドがバリアを開く前に最新のものにする必要があるすべてのメモリロケーションが、その後にリロードされます。だからレジスタに生きているそのような値は、(汚れていれば)保存する必要があり、レジスタ内の値がまだメモリに残っているもののコピーであるならば、ちょうど "忘れてしまいました"。

は、GCC DEVからこの引用ためthis gcc non-bug reportを参照:"memory"クロバーは間接的にのみアクセス可能なメモリを含む(従ってアドレス取らこのまたは別のコンパイル単位であってもよい)

任意でありレジスタのフラッシュとは別のオーバヘッド?

障壁は、ループの外に店を沈没のような最適化を防ぐことができますが、それはあなたが障壁を使用し、通常は理由です。ループカウンターとループ変数は、コンパイラーが見ることができない関数にアドレスを渡されていない地方自治体であることを確認してください。そうでなければ、ループの中にこぼれ落ち/再ロードする必要があります。参照をあなたの関数から逃れることは、常に最適化にとって潜在的な問題ですが、それは障壁を伴うより悪いコードの保証です。


なぜ?

これはバリアの全ポイントです。値はメモリに同期され、コンパイル時の並べ替えを防止します。

asm volatile(::: "memory")は、atomic_signal_fence(memory_order_seq_cst)(正確には?)であり、atomic_thread_fenceではありません(x86では実装するにはmfence命令が必要です)。


例:

理由、および実際のx86 ASMで例の詳細を参照してくださいジェフPreshingのMemory Ordering at Compile Time記事。

関連する問題