2012-01-12 81 views
27

我是一個新手,當談到這一點。任何人都可以提供以下內存障礙之間差異的簡單解釋嗎?原子的C++內存障礙

  • 窗戶MemoryBarrier();
  • 圍欄_mm_mfence();
  • 內聯彙編asm volatile ("" : : : "memory");
  • 內在_ReadWriteBarrier();

如果沒有一個簡單的解釋一些鏈接好文章或書籍會可能會幫助我把它弄直。到目前爲止,我只使用包裝這些調用的其他人編寫的對象就可以,但是我希望能夠比我目前的想法更好地理解,這種想法基本上是沿着不同的方式來實現內存中的內存障礙。

+4

你忘了C++ 11s'atomic_thread_fence' – Grizzly 2012-01-12 20:40:08

+0

那麼這就是導致...我們有我們自己的原子模板對象的整型類型,我想切換到C++ 11標準原子。在此之前,我想了解兩者實際工作的底層實現。 – AJG85 2012-01-12 20:42:38

回答

28

MemoryBarrier(MSVC)和_mm_mfence(由多個編譯器支持)都提供了一個硬件內存圍欄,它可以防止處理器跨圍欄移動讀寫操作。

主要區別在於MemoryBarrier具有針對x86,x64和IA64的平臺特定實現,其中_mm_mfence專門使用mfence SSE2指令,因此它並不總是可用的。

在x86和x64上,分別使用xchglock or來實現MemoryBarrier,並且我看到一些聲稱這比mfence更快。然而,我自己的基準測試顯示了相反的情況,顯然它非常依賴處理器模型。

另一個區別是mfence也可以用於排序非臨時存儲/加載(movntq等)。

GCC也有__sync_synchronize它會產生硬件圍欄。

asm volatile ("" : : : "memory") GCC和_ReadWriteBarrier MSVC中只提供編譯器級別的內存圍欄,防止編譯器重新排序內存訪問。這意味着處理器仍然可以自由地重新排序。

編譯器柵欄通常與具有某種隱式硬件柵欄的操作結合使用。例如。在x86/x64上,所有商店都有一個發佈柵欄,並且負載具有收購柵欄,所以在實現負載獲取和存儲發佈時,您只需要一個編譯器柵欄。

+0

完美!謝謝,這有很大幫助。 – AJG85 2012-01-13 16:44:59

3

請參閱我的回答here關於柵欄的硬件級別的語義。沒有提到的是,它們還防止在編譯器級別和硬件級別重新排序加載,存儲或加載存儲區(取決於柵欄)跨越柵欄。