簡體   English   中英

std::atomic<> 是否保證 store() 操作立即(幾乎)傳播到具有 load() 的其他線程?

[英]Does std::atomic<> gurantee that store() operation is propagated immediately (almost) to other threads with load()?

我有std::atomic<T> atomic_value; (對於類型 T 為 bool、int32_t、int64_t 和任何其他類型)。 如果第一個線程做

atomic_value.store(value, std::memory_order_relaxed);

在第二個線程中我做的某些代碼點

auto value = atomic_value.load(std::memory_order_relaxed);

這個更新的原子值在 CPU 內核之間從第一個線程傳播到第二個線程的速度有多快? (適用於所有 CPU 型號)

它幾乎立即傳播了嗎? 例如 Intel 高速緩存一致性傳播的速度,這意味着 0-2 個周期左右。 對於其他一些 CPU 型號/制造商,可能還有幾個周期。

或者這個值有時可能會在很多周期內都沒有更新?

對於給定的 CPU,atomic 是否保證值在 CPU 內核之間盡可能快地傳播?

也許如果我在第一個線程上做

atomic_value.store(value, std::memory_order_release);

在第二個線程

auto value = atomic_value.load(std::memory_order_acquire);

那么它是否有助於更快地傳播價值? (注意memory訂單的變化)現在有速度保證? 或者它會像放寬訂單一樣保證速度?

作為一個附帶問題——用 release+acquire 替換 relaxed order 是否也會同步其他(非原子)變量中的所有修改?

這意味着在第一個線程中,在存儲和發布之前寫入 memory 的所有內容,在第二個線程中保證整個 memory 在加載和獲取點完全在最終 state(與第一個線程中相同)中,當然在加載值是新值(更新)的情況下。

因此,這意味着對於任何類型的 std::atomic<>(或 std::atomic_flag),一個線程中的 store-with-release 點同步所有 memory 在它之前的寫入與另一個線程中的點同步,該線程執行加載和獲取相同的原子,當然如果在其他線程中更新了原子的值? (當然,如果第二個線程中的值還不是新的,那么我們預計 memory 寫入尚未完成)

附言 為什么會出現問題... 因為根據名稱"atomic" ,很明顯可以得出結論(可能未得出結論)默認情況下(沒有額外的限制,即只是放寬了 memory 順序)std::atomic<> 只是進行任何算術運算原子的,沒有別的,沒有其他關於同步或傳播速度的保證。 這意味着寫入 memory 位置將是完整的(例如,對於 int32_t 一次所有 4 個字節),或者與原子位置交換將以原子方式進行讀寫(實際上以鎖定方式),或者增加一個值將以原子方式執行三個讀取操作- 添加寫入。

C++ 標准只說了這個 [C++20 intro.progress p18]:

實現應確保由原子操作或同步操作分配的最后一個值(按修改順序)在有限的時間內對所有其他線程可見。

從技術上講,這只是一個“應該”,“有限時間”並不是很具體。 但是 C++ 標准足夠廣泛,您不能指望它們指定特定的周期數或納秒數或您擁有的。

實際上,您可以預期調用任何原子存儲 function,即使使用memory_order_relaxed ,也會導致執行實際的機器存儲指令。 該值不僅會保留在寄存器中。 之后,它就脫離了編譯器的控制,交給了 CPU。

(從技術上講,如果您有兩個或多個連續存儲到同一個 object,並且在其間完成了一定數量的其他工作,則允許編譯器優化除最后一個以外的所有存儲,因為您不能無論如何,我已經確定任何給定的負載都會在正確的時刻發生以查看其他值之一。實際上,我不相信目前有任何編譯器這樣做。)

對典型 CPU 架構的合理期望是,存儲將“沒有不必要的延遲”變得全局可見。 存儲可以 go 進入核心的本地存儲緩沖區。 核心將盡快處理存儲緩沖區條目; 它不僅讓他們坐在那里像美酒一樣陳年。 但他們仍然需要一段時間。 例如,如果緩存行當前由另一個核心獨占,則必須等到它被釋放后才能提交存儲。

使用更強的 memory 排序不會加快進程; 機器已經在盡最大努力提交商店。 事實上,更強的 memory 排序實際上可能會減慢速度; 如果存儲是按發布順序創建的,那么它必須等待緩沖區中所有較早的存儲都提交,然后才能自己提交。 在像 x86 這樣的強序架構上,每個存儲都會自動釋放,因此存儲緩沖區始終保持嚴格的順序; 但是在弱排序的機器上,使用寬松的排序可能會讓你的商店“插隊”並比其他方式更快地到達 L1 緩存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM