2011-04-06 67 views
6

作爲我以前的question的後續,atomic<T>類用memory_order參數指定了大多數操作。與籬笆相比,這種記憶順序僅影響其操作的原子。大概通過使用幾個這樣的原子,你可以建立一個並行算法,其他內存的排序是不重要的。C++ 0X memory_order無柵欄,應用程序,支持的芯片

所以我有兩個問題:

  1. 有人可以點我的算法/局面,將有利於從各個原子變量的排序和需要圍欄的例子嗎?
  2. 哪些現代處理器支持這種類型的行爲?也就是說,編譯器不會將特定順序轉換爲常規圍欄。

回答

4

內存排序在操作上std::atomic<T>變量參數不影響操作本身的排序,它會影響操作與其他操作產生的排序關係。

例如a.store(std::memory_order_release)自身不能告訴你關於a操作如何相對於別的排序,但從另一個線程a.load(std::memory_order_acquire)通話配對,這則命令其他操作---所有寫入到其他變量(包括非原子的)通過執行加載的線程可以看到存儲到a的線程完成,如果該加載讀取存儲的值。

在現代處理器上,操作上的一些內存排序是空操作。例如在x86上,memory_order_acquire,memory_order_consumememory_order_release隱含在加載和存儲指令中,並且不需要單獨的屏蔽。在這些情況下,排序只會影響編譯器可以執行的指令重新排序。

說明:指令中的隱含柵欄可能意味着如果所有內存排序約束都附加到原子變量上的各個操作,編譯器不需要發出明確的柵欄指令任何。如果你對所有東西都使用memory_order_relaxed,並添加明確的屏蔽,那麼編譯器可能必須明確地將這些屏蔽指定爲指令。

例如在x86上,XCHG指令帶有隱含的memory_order_seq_cst柵欄。因此,存在下面x86上的兩個交換操作生成的代碼之間沒有區別---他們都映射到單一XCHG指令:

std::atomic<int> ai; 
ai.exchange(3,std::memory_order_relaxed); 
ai.exchange(3,std::memory_order_seq_cst); 

不過,我還沒有意識到,擺脫任何編譯在下面的代碼中明確說明圍欄:

std::atomic_thread_fence(std::memory_order_seq_cst); 
ai.exchange(3,std::memory_order_relaxed); 
std::atomic_thread_fence(std::memory_order_seq_cst); 

我希望編譯器將最終處理最優化,但也有其他類似的情況下,隱含的圍牆將允許更好的優化。

另外,std::memory_order_consume可以只有適用於直接操作變量。

+0

是的,我明白這一點,這就是我的意思*這種記憶順序隻影響其操作的原子*。這兩個問題依然存在。 – 2011-04-06 08:02:53

+0

如果通過指定「原子」上的內存順序來保證*關係與*關係的保證,並且保護範圍只能保證與「原子」操作一起工作,那麼爲什麼標準中甚至存在柵欄。只需在變量上使用內存順序就不需要任何圍欄。而且由於你沒有被允許在沒有原子的情況下使用柵欄,所以我看不到你實際上想要柵欄的情況。 – 2011-04-07 04:35:33

+1

有條件的圍欄是您希望使用顯式圍欄的一種情況。例如 'std :: atomic p; (p.load(std :: memory_order_relaxed)){ std :: thread_fence(std :: memory_order_acquire); do_something_with(* p); }' 或旋等待循環後:(!p.load(標準:: memory_order_relaxed)) '而{ 的std :: this_thread ::收率(); } std :: thread_fence(std :: memory_order_acquire);' – 2011-04-07 06:43:17