[英]How to understand RELAXED ORDERING in std::memory_order (C++)
[英]C++ atomics and memory_order with RDMA
當在現代 memory 上使用無鎖單側 RDMA 時,問題出現了,如果數據對象跨越多個緩存行,遠程讀取器如何安全地查看他們的傳入數據。
在 Derecho 開源多播和復制日志記錄庫(在https://GitHub.com/Derecho-Project上)中,我們有這種模式。 寫入器 W 被授予在讀取器 R 中寫入范圍 memory 的權限。Memory 已正確固定和映射。 現在,假設寫入涉及某種跨越許多緩存行的數據向量,這很常見。 我們使用一個守衛:一個遞增的計數器(也在 RDMA 中訪問 memory,但在其他一些緩存行中)。 R 旋轉,觀察計數器……當它看到變化時,它告訴 R “你有一條新消息”,然后 R 讀取向量中的數據。 稍后我們有第二種模式,其中 R 對 W 說,“我已經完成了那條消息,你可以再發送一條。”
我的問題:對於現代 memory 模型,應該使用哪種類型的 C++ 原子來寫入向量的 memory? 這會被表示為寬松的一致性嗎? 我希望我的代碼能夠在 ARM 和 AMD 上運行,而不僅僅是具有強大 TSO memory model 的英特爾。
然后對於我的計數器,當 R 旋轉以等待計數器更新時,我希望如何聲明計數器? 是否需要將其聲明為獲取-釋放原子?
最后,在速度或正確性方面,在 R 觀察到計數器增加后,將所有內容都聲明為寬松的,然后在此處使用 memory_order 柵欄是否有任何優點? 我的想法是,使用第二種方法,我在所有 RDMA memory 上使用最小一致性 model(對所有此類內存使用相同的 model),而且我只需要在觀察到計數器遞增后調用成本更高的 memory_order 柵欄。 所以它只發生一次,在訪問我的向量之前,而每次輪詢線程循環時獲取釋放原子計數器都會觸發 memory 防護機制。 對我來說,這聽起來非常昂貴。
最后的想法引出了另一個問題:我是否也必須將這個 memory 聲明為 volatile,以便 C-編譯器意識到數據可以在其腳下改變,或者編譯器本身可以看到 std::atomic 類型是否足夠聲明? 在 Intel 上,對於總商店排序,TSO 加上 volatile 是絕對需要的。
[編輯:新信息](我想在這里吸引一些幫助!)
一種選擇似乎是將 RDMA memory 區域聲明為 std::atomic<relaxed_consistency> 但是每次我們的謂詞評估線程重新測試守衛時都使用鎖(在 RDMA memory 中,將使用相同的松弛屬性聲明). 我們將保留 C++ volatile 注釋。
原因是使用具有獲取-釋放語義的鎖,memory 一致性硬件將被警告它需要屏蔽先前的更新。 鎖本身(互斥量)可以在謂詞線程的本地聲明,然后將存在於本地 DRAM 中,這很便宜,並且由於這不是任何東西都爭用的鎖,因此鎖定它可能與 test_and_set 一樣便宜,並且unlocking 只是寫入 0。如果謂詞為真,我們觸發的代碼主體在訪問鎖后運行(可能在鎖釋放后),因此我們建立所需的順序以確保硬件將獲取受保護的 object使用實際 memory 次讀取。 但是通過我們的謂詞測試的每個循環——每個“自旋”——我們最終都會對每個謂詞進行鎖獲取/釋放。 所以這會導致一些放緩。
選項二,看似開銷較少,也將 RDMA 區域聲明為 std::atomic 並具有寬松的一致性,但省略了鎖並像我們現在所做的那樣進行測試。 然后,當謂詞測試為真時,我們將執行具有語義的顯式內存柵欄 (std::memory-order)。 我們得到了相同的障礙,但只在謂詞評估為真時才支付成本,因此開銷更少。
但現在我們遇到了一個不同類型的問題。 Intel 有總存儲順序 TSO,並且因為任何線程都執行一些先寫后讀操作,Intel 可能出於預防而被迫從 memory 獲取保護變量,擔心 TSO 可能會被違反。 帶有 volatile 的 C++ 肯定包含獲取指令。 但是在 ARM 和 AMD 上,硬件本身是否有可能在硬件寄存器或其他東西中存儲一些保護變量很長時間,從而導致我們的“類自旋”循環出現極度延遲? 對 ARM 和 AMD 一無所知,這似乎令人擔憂。 但也許你們中有人知道的比我多得多?
好吧,目前似乎缺乏這方面的專業知識。 可能是 std::atomics 選項的新穎性以及關於 ARM 和 AMD 將如何實現寬松一致性的普遍不確定性讓人們很難知道答案,猜測也無濟於事。
據我了解,正確的答案似乎是:
我們還需要在 C++ 中將我們的原子標記為 volatile。事實上,C++ 可能應該注意到何時訪問 std::atomic 類型,並將其視為對 volatile 的訪問。 但是,目前尚不清楚 C++ 編譯器是否正在實施此策略。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.