Intel x86/x86_64 システムには、lfence、sfence、mfence の 3 種類のメモリ バリアがあります。それらの使用に関する質問。シーケンシャル セマンティック (SC) は、SC セマンティックMOV [addr], reg + MFENCE
を必要とするすべてのメモリ セルに使用するのに十分です。ただし、全体にコードを記述することも、その逆も可能ですMFENCE + MOV reg, [addr]
。どうやら、メモリへのストアの数が通常そこからのロードよりも少ない場合、合計で書き込みバリアを使用する方がコストが少ないと感じました。これに基づいて、シーケンシャル ストアをメモリに使用する必要があるため、別の最適化を行いました - [LOCK] XCHG。これは、「XCHG 内の MFENCE」が使用されるメモリのキャッシュ ラインにのみ適用されるため、おそらく安価です。 XCHG ( 0:28:20 で、MFENCE は XCHG よりも高価であると述べたビデオ)。
http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
C/C++11 オペレーション x86 実装
- Load Seq_Cst: MOV (メモリから)
- Store Seq Cst: (LOCK) XCHG // 代替: MOV (メモリへ),MFENCE
注: C/C++11 から x86 への代替マッピングがあり、Seq Cst ストアをロック (またはフェンシング) する代わりに、Seq Cst ロードをロック/フェンシングします。
- Load Seq_Cst: LOCK XADD(0) // 代替: MFENCE,MOV (メモリから)
- Store Seq Cst: MOV (メモリに)
違いは、ARM と Power のメモリ バリアは LLC (Last Level Cache) のみと対話し、x86 は下位レベルのキャッシュ L1/L2 と対話することです。x86/x86_64 の場合:
lfence
Core1: (CoreX-L1) -> (CoreX-L2) -> L3-> (Core1-L2) -> (Core1-L1)sfence
Core1: (Core1-L1) -> (Core1-L2) -> L3-> (CoreX-L2) -> (CoreX-L1)
アームの場合:
ldr; dmb;
: L3-> (Core1-L2) -> (Core1-L1)dmb; str; dmb;
: (Core1-L1) -> (Core1-L2) -> L3
GCC 4.8.2 でコンパイルされた C++11 コード - x86_64 の GDB:
std::atomic<int> a;
int temp = 0;
a.store(temp, std::memory_order_seq_cst);
0x4613e8 <+0x0058> mov 0x38(%rsp),%eax
0x4613ec <+0x005c> mov %eax,0x20(%rsp)
0x4613f0 <+0x0060> mfence
しかし、なぜx86/x86_64 Sequential Semantic (SC) で through を使用しMOV [addr], reg + MFENCE
、 notを使用するのにMOV [addr], reg + SFENCE
、なぜthereMFENCE
ではなくfull-fence が必要なのSFENCE
でしょうか?