私が理解している限り、mfence
はハードウェア メモリ バリアasm volatile ("" : : : "memory")
ですが、 はコンパイラ バリアです。ただし、asm volatile ("" : : : "memory")
mfence の代わりに使用できます。
私が混乱した理由はこのリンクです
私が理解している限り、mfence
はハードウェア メモリ バリアasm volatile ("" : : : "memory")
ですが、 はコンパイラ バリアです。ただし、asm volatile ("" : : : "memory")
mfence の代わりに使用できます。
私が混乱した理由はこのリンクです
メモリ バリアは、メモリの順序付けが弱いアーキテクチャでのみ必要です。x86 と x64 には弱いメモリ順序はありません。x86/x64 では、すべてのストアにリリース フェンスがあり、すべてのロードに取得フェンスがあります。だから、あなたは本当に必要なだけですasm volatile ("" : : : "memory")
Intel と AMD の両方の概要と、関連するメーカーの仕様への参照については、 http: //bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/ を参照してください。
一般に、「揮発性」のようなものはフィールドごとに使用され、そのフィールドへのロードとストアはネイティブにアトミックです。フィールドへのロードとストアがすでにアトミックである場合 (つまり、問題の「操作」は単一フィールドへのロードまたはストアであり、したがって操作全体がアトミックです)、volatile
フィールド修飾子またはメモリ バリアは x86/x64 では必要ありません。それにもかかわらず、移植可能なコード。
アトミックではない「操作」に関しては、たとえば、ネイティブ ワードより大きいフィールドへのロードまたはストア、または「操作」内の複数のフィールドへのロードまたはストアなど、操作を表示できる手段CPUアーキテクチャに関係なく、 アトミックとして必要です。一般に、これはミューテックスのような同期プリミティブによって行われます。ミューテックス (私が使用したもの) には、プロセッサの並べ替えなどの問題を回避するためのメモリ バリアが含まれているため、メモリ バリア命令を追加する必要はありません。私は通常、同期プリミティブを使用しないことは時期尚早の最適化だと考えています。しかし、時期尚早の最適化の性質は、もちろん、97% の時間です :)
同期プリミティブを使用せず、複数フィールドの不変条件を扱っている場合、プロセッサが異なるメモリ位置にストアとロードを並べ替えないようにするメモリ バリアが重要です。
ここで、asm volatile で「mfence」命令を発行するのではなく、clobber リストで「memory」を使用するという点で。読めたものから
アセンブラ命令が予測できない方法でメモリにアクセスする場合は、破壊されたレジスタのリストに「メモリ」を追加します。これにより、GCC はアセンブラー命令全体でレジスターにキャッシュされたメモリー値を保持せず、そのメモリーへのストアまたはロードを最適化しません。
彼らが「GCC」と言ってCPUについて何も言及していない場合、これはコンパイラのみに適用されることを意味します。「mfence」がないということは、CPU メモリ バリアがないことを意味します。これは、結果のバイナリを逆アセンブルすることで確認できます。「mfence」命令が発行されない場合 (ターゲット プラットフォームによって異なります)、CPU がメモリ フェンスを発行するように指示されていないことは明らかです。
使用しているプラットフォームと何をしようとしているのかによって、「より良い」またはより明確な何かがあるかもしれません...移植性は耐えられません。
asm volatile ("" ::: "memory")
単なるコンパイラの障壁です。asm volatile ("mfence" ::: "memory")
コンパイラバリアであり、MFENCE
__sync_synchronize()
コンパイラのバリアであり、完全なメモリのバリアでもあります。したがってasm volatile ("" ::: "memory")
、CPU が独立したデータ命令自体を並べ替えるのを妨げることはありません。指摘したように、x86-64 には強力なメモリ モデルがありますが、StoreLoad の並べ替えは依然として可能です。アルゴリズムが機能するために完全なメモリバリアが必要な場合は、__sync_synchronize
並べ替えには 2 つあり、1 つはコンパイラの並べ替え、もう 1 つは CPU の並べ替えです。
x86/x64 には比較的強力なメモリ モデルがありますが、x86/x64 では StoreLoad の並べ替え (後のロードが以前のストアを通過する) が発生する可能性があります。http://en.wikipedia.org/wiki/Memory_orderingを参照
asm volatile ("" ::: "memory")
単なるコンパイラの障壁です。asm volatile ("mfence" ::: "memory")
コンパイラバリアと CPU バリアの両方です。つまり、コンパイラ バリアのみを使用し、コンパイラの並べ替えを防ぐことはできますが、CPU の並べ替えを防ぐことはできません。つまり、ソース コードのコンパイル時に並べ替えは行われませんが、実行時に並べ替えが発生する可能性があります。
したがって、どちらを使用するかは、ニーズによって異なります。