在Intel x86/x86_64系統中有三種類型的內存障礙:隔離,保護和防護。在使用方面的問題。 對於需要SC語義的所有存儲器單元而言,對於順序語義(SC)足以使用MOV [addr], reg + MFENCE
。但是,您可以在整體中編寫代碼,反之亦然:MFENCE + MOV reg, [addr]
。顯然感覺到,如果存儲器的存儲數量通常小於存儲器的存儲容量,那麼使用寫入存儲器的總成本要低一些。在此基礎上,我們必須使用順序存儲器來進行存儲,並進行了另一種優化 - [LOCK] XCHG,由於「XCHG內部的MFENCE」僅適用於內存中使用的緩存行XCHG(video where on 0:28:20 said that MFENCE more expensive that XCHG)。爲什麼x86/x86_64上的Sequential Semantic通過MOV [addr],reg + MFENCE而不是+ SFENCE使用?
http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
C/C++ 11操作86執行
- 負載Seq_Cst:MOV(從存儲器)
- 商店SEQ Cst中:(LOCK)XCHG // 替代: MOV(進入存儲器),MFENCE
注:有的C/C++ 11〜86的替代映射,而不是鎖定(或擊劍)的SEQ Cst中存儲的鎖,其/圍欄的SEQ Cst中負載:
- 負載Seq_Cst:LOCK XADD(0)//選擇:MFENCE,MOV(從內存中)
- 商店SEQ Cst中:MOV(到內存)
不同的是,ARM和斷電記憶障礙與LLC專門交互(最後Level Cache)和x86進行交互,並與較低級別的緩存L1/L2進行交互。 在86/x86_64的:
lfence
上核心-1:(COREX-L1) - >(COREX-L2) - > L3->(核心-1-L2) - >(核心-1-L1)sfence
上核心-1:(核心-1-L1) - >(核心-1-L2) - > L3->(COREX-L2) - >(COREX-L1)
在ARM:
ldr; dmb;
:L3- >(Core1-L2)→(Core1-L1)dmb; str; dmb;
:(核心-1-L1) - >(核心-1-L2) - > L3
C++ 11代碼由GCC 4.8.2編譯 - 在GDB x86_64的:
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序貫語義(SC)使用通過MOV [addr], reg + MFENCE
而不是MOV [addr], reg + SFENCE
,爲什麼我們需要全圍欄MFENCE
而不是SFENCE
呢?
我認爲商店圍牆只會與其他商店同步,而不會與其他商店同步。順序一致性意味着您需要所有CPU都能觀察到的* total *順序,並且商店柵欄不會暗示多個商店的順序。 –
@Kerrek這對於ARM來說是正確的,但對於x86來說不是這樣,因爲如果我們在第一個CPU內核上創建SFENCE,那麼在訪問這個內存單元之前,我們不再需要在另一個CPU內核上執行LFENCE。因此,如果所有的變量都需要順序語義(SC),我們做SFENCE,而且我們不需要在任何地方有LFENCE。還是你的意思是MFENCE取消了處理器流水線中兩個方向的重新排序(無序執行)? – Alex
首先,我想我想說的是,單獨的保護不能提供被所有CPU所迷惑的* total *排序... –