簡體   English   中英

在實踐中,無鎖原子是否無地址?

[英]Are lock-free atomics address-free in practice?

Boost.Interprocess是一個很棒的庫,可以簡化不同進程之間共享內存的使用。 它提供互斥鎖,條件變量和信號量,允許在從共享內存中寫入和讀取時進行同步。

但是,在某些情況下,這些(相對)性能密集型同步機制不是必需的 - 原子操作足以滿足我的用例,並且可能會提供更好的性能。

不幸的是,Boost.Interprocess似乎沒有原子。


C ++標准庫提供了std::atomic類模板,該模板封裝了操作需要是原子的對象,並且還具有測試原子操作是否無鎖的功能。 但它也不要求無鎖原子也不需要地址: [atomics.lockfree] / 4只是鼓勵無鎖操作無地址,這與cppreference一致

我想不出為什么會以非地址方式實現無鎖原子的任何理由。 在我看來,以無地址的方式實現無鎖原子相當容易。

因為在使用原子而不是互斥體(來自Boost.Interprocess)時我會獲得顯着的性能優勢,所以在這里折扣標准兼容性並將std::atomic對象存儲在共享內存中似乎很誘人。


這個問題分為兩部分:

  1. 在實踐中,CPU是否以無地址方式實現無鎖原子? (我只關心用於運行現代桌面和移動操作系統的CPU(例如Windows,MacOS,Linux,Android,iOS),但不關心嵌入式系統)
  2. 為什么實現使用無鎖地址的無地址原子?

是的,無鎖原子在所有普通CPU上的所有C ++實現上都是無地址的,並且可以安全地在進程之間的共享內存上使用。 非無鎖的原子公司1 不會進程之間的安全,雖然。 每個進程都有自己的鎖的哈希表( 在哪里是std :: atomic的鎖? )。

C ++標准意味着無鎖原子在進程之間的共享內存中工作,但它只能在沒有定義術語等的情況下達到“應該”的程度。

C ++ draft 29.5無鎖屬性

[注意:無鎖操作也應該是無地址的。 也就是說,通過兩個不同地址在同一存儲器位置上的原子操作將以原子方式進行通信。 實現不應該依賴於任何每個進程的狀態。 此限制允許通過多次映射到進程的內存以及在兩個進程之間共享的內存進行通信。 - 結束說明]

這是一個很容易在當前硬件上實現的實施質量建議,實際上你必須努力設計一個在x86 / ARM / PowerPC /其他主流CPU上違反它的deathstation9000 C ++實現,而實際上無鎖。


原子讀 - 修改 - 寫操作的硬件暴露機制基於MESI緩存一致性,它只關心物理地址。 x86 lock cmpxchg / lock add / etc.使一個核心掛起到處於Modified狀態的緩存行,因此在原子操作過程中沒有其他核心可以讀取/寫入它。 對於'int num',num ++可以是原子的嗎? )。

大多數非x86體系結構使用LL / SC ,它允許您編寫一個重試循環,只有存儲才會進行存儲。 LL / SC可以在沒有引入地址的情況下以無等待的方式模擬具有O(1)開銷的CAS。

C ++無鎖原子編譯直接使用LL / SC指令。 有關x86示例的num++問題,請參閱我的答案。 有關使用LL / SC指令的compare_exchange_weak vs fetch_add的AArch64代碼生成的一些示例,請參閱原子清除無符號整數的最低非零位

原子純負載或純存儲更容易,並且可以通過對齊數據免費實現。 在x86上,請參閱為什么在x86 上對自然對齊的變量進行整數賦值? 其他ISA有類似的規則。


相關:我在答案中包含了一些關於無地址的評論。 真正的測試std :: atomic是無鎖的 我不確定它們是否有用或正確。 :/


腳注1

所有主流CPU都具有無鎖原子,用於指向指針寬度的對象。 有些具有更寬的原子,如x86具有lock cmpxchg16b ,但並非所有實現都選擇將其用於雙寬度無鎖原子對象。 檢查C ++ 17 std::atomic::is_always_lock_free ,或ATOMIC_xxx_LOCK_FREE如果已定義),以進行編譯時檢測。

(有些微控制器不能將指針保存在單個寄存器中(或通過單個操作復制它),但通常不存在此類ISA的多核實現。)


為什么實現使用無鎖地址的無地址原子?

我不知道硬件上有任何合理的原因可以像普通的現代CPU一樣工作。 您可以想象一些通過向某些人提交地址來執行原子操作的架構

我認為C ++標准希望盡可能避免限制非主流實現。 例如,在某種解釋器之上的C ++,而不是編譯為“正常”CPU架構的機器代碼。

IDK,如果您可以在松散耦合的共享內存系統上實現C ++,例如具有以太網鏈接而不是共享內存的集群,或者非連貫的共享內存(必須為其他線程顯式刷新以查看您的商店)。

我認為這是主要的C ++委員會不能說太多有關如何原子能公司必須在沒有假設的實現將運行一個操作系統在多個進程可以設置共享內存下的程序來實現。

他們可能想象一些未來無法使用無地址原子的ISA,但我認為他們更可能不想談論多個C ++程序之間的共享內存。 該標准僅要求實現運行一個程序。

顯然std::atomic_flag實際上保證是無地址為什么只保證std :: atomic_flag無鎖? 所以IDK為什么不對實現選擇實現無鎖的任何atomic<T>做出相同的要求。

暫無
暫無

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

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