考慮使用 SC 原子進行存盤緩沖區試金石測驗:
// Initial
std::atomic<int> x(0), y(0);
// Thread 1 // Thread 2
x.store(1); y.store(1);
auto r1 = y.load(); auto r2 = x.load();
這個程式可以以兩者結束r1并且r2為零嗎?
我看不出這個結果是通過對描述禁止memory_order_seq_cst在cppreference:
具有這種記憶體順序的加載操作執行獲取操作,存盤執行釋放操作,讀-修改-寫同時執行獲取操作和釋放操作,并且存在一個單一的總順序,其中所有執行緒都觀察到相同的順序
在我看來,這memory_order_seq_cst只是獲取-發布加上全球商店訂單。而且我認為全球商店訂單不會在這個特定的試金石測驗中發揮作用。
uj5u.com熱心網友回復:
SC 的 cppreference 摘要太弱了,實際上還不足以禁止這種重新排序。
它所說的在我看來只與 x86-TSO 一樣強(acq_rel 加上沒有 IRIW 重新排序,即所有讀取器執行緒都可以同意的總存盤順序)。
ISO C 實際上保證所有 SC 操作(和柵欄)的總順序與程式順序一致。順序一致性必須禁止在同一執行緒中的任何兩個 SC 操作之間進行任何重新排序,甚至是 StoreLoad 重新排序。
這意味著昂貴的完整屏障(包括StoreLoad)每個商店之后,或例如AArch64 STLR / LDAR不能StoreLoad與重排序彼此,但否則只能釋放和獲取WRT。與其他操作重新排序。(因此,如果您之后不在同一執行緒中執行任何 SC 加載或 RMW 操作,則AArch64 上的快取命中 SC 存盤可能比 x86 便宜很多。)
請參閱https://el.is/c draft/atomics.order#4這清楚地表明 SC 操作不會重新排序。彼此。在目前的標準草案說:
31.4 [原子.訂單]
- 所有
memory_-order?::?seq_-cst操作(包括圍欄)上都有一個滿足以下約束的全序 S。首先,如果 A 和 B 是memory_-order?::?seq_-cst操作并且 A 強烈發生在 B 之前,那么 A 在 S 中先于 B。 其次,對于物件 M 上的每對原子操作 A 和 B,其中 A 在 B 之前是連貫有序的,以下四個S需要滿足的條件:
- (4.1) 如果 A 和 B 都是 memory_order :: seq_cst 操作,那么 A 在 S 中排在 B 之前;和
- (4.2 .. 4.4) - 對于柵欄來說基本上是一樣的。操作。
4.1是SC存盤的StoreLoad排序的關鍵點,然后是一個執行緒中的SC加載。
這些保證,加上同步/發生之前,足以恢復整個程式的順序一致性,如果它是無資料競爭的(那將是 UB),并且如果您不使用任何較弱的記憶體順序。
如果程式涉及較弱的命令,這些規則仍然適用,但例如,兩個relaxed操作之間的 SC 圍欄不如兩個 SC 負載那么強。例如,在 PowerPC 上,不排除僅使用 SC 操作的方式進行IRIW 重新排序;IIRC PowerPC在SC 加載之前和之后都需要屏障。
因此,進行一些 SC 操作不一定足以在任何地方恢復順序一致性;這是使用較弱操作的重點,但其他操作可以重新排序 wrt 可能有點令人驚訝。SC行動。SC ops 不是 SC 圍欄。另請參閱此問答以獲取具有相同“存盤緩沖區”試金石測驗的示例:將一個存盤從 削弱seq_cst到release允許重新排序。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/372508.html
下一篇:計算給定陣列中元素總和的程式
