簡體   English   中英

什么時候不應該使用 [[carries_dependency]]?

[英]When should you not use [[carries_dependency]]?

我發現了一些問題(比如這個)詢問[[carries_dependency]]做什么,這不是我在這里問的。

我想知道你什么時候不應該使用它,因為我讀過的所有答案都讓人覺得你可以把這段代碼貼在任何地方,而且你會神奇地得到相等或更快的代碼。 一個評論說代碼可以相等或更慢,但海報沒有詳細說明。

我想在任何函數返回或參數上使用 this 的合適位置是指針或引用,並且將在調用線程中傳遞或返回,並且不應在回調或線程入口點上使用它。

有人可以評論我的理解並詳細說明一般的主題,何時以及何時不使用它?

編輯:我知道 這個主題有 這本書,如果其他讀者感興趣的話; 它可能包含我的答案,但我還沒有機會通讀它。

在現代 C++ 中,您通常根本不應該使用std::memory_order_consume[[carries_dependency]] 它們基本上已被棄用,而委員會提出了一種編譯器可以實際實施的更好的機制。

並且希望不需要在整個地方撒上[[carries_dependency]]kill_dependency

2016-06 P0371R1:暫時不鼓勵 memory_order_consume

人們普遍認為,標准中當前對 memory_order_consume 的定義沒有用。 當前所有的編譯器基本上都將它映射到 memory_order_acquire。 困難似乎源於高實現復雜性,源於當前定義使用了相當普遍的“依賴”定義,因此需要頻繁且不方便地使用 kill_dependency 調用,以及頻繁需要 [[carries_dependency] ] 注釋。 詳細信息可以在例如P0098R0 中找到。

值得注意的是,在 C++ 中x - x仍然帶有依賴項,但大多數編譯器會自然地打破依賴項並將該表達式替換為常量0 但是,如果編譯器可以證明分支后的值范圍,有時也會將數據依賴關系轉換為控制依賴關系。


在現代的編譯器,只是促進mo_consumemo_acquire ,完全積極的優化,可以隨時發生; 即使在使用mo_consume代碼中, [[carries_dependency]]kill_dependency也沒有任何mo_consume ,更不用說在其他代碼中了。


對於諸如 POWER 和 ARM 等弱排序 ISA 上的 RCU 等實際用例,對mo_acquire這種增強具有潛在的顯着性能成本(一個額外的障礙)。 觀看 Paul E. McKenney 的 CppCon 2015 演講視頻C++ 原子:memory_order_consume 的悲傷故事 (鏈接包括摘要)。

如果你想要真正的依賴排序只讀性能,你必須“推出你自己的”,例如通過使用mo_relaxed並檢查 asm 以驗證它是否編譯為具有依賴項的 asm。 (避免對這樣的值做任何“奇怪”的事情,比如在函數之間傳遞它。)DEC Alpha 基本上已經死了,所有其他 ISA 都在 asm 中提供了無障礙的依賴排序,只要 asm 本身具有數據依賴。

如果您不想自己動手並過着危險的生活,那么在應該能夠工作的“簡單”用例中繼續使用mo_consume可能不會有什么壞處; 也許未來的一些mo_consume實現將具有相同的名稱並以與 C++11 兼容的方式工作。


正在進行新的consume ,例如 2018 年的http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0750r1.html

因為我讀過的所有答案都讓人覺得你可以把這段代碼貼在任何地方,而且你會神奇地得到相同或更快的代碼

獲得更快代碼的唯一方法是該注釋允許省略圍欄。

因此,它可能有用的唯一情況是:

  • 您的程序在一個重要的頻繁執行的代碼中對原子加載操作使用消費排序;
  • “消費值”不僅會立即在本地使用,還會傳遞給其他函數;
  • 目標 CPU 為消費操作提供特定保證(與該操作之前的給定柵欄一樣強大,僅針對該操作);
  • 編譯器編寫者認真對待他們的工作:他們設法將消耗一個值的高級語言轉換為 CPU 級別消耗,以從 CPU 保證中獲益。

這是可能獲得明顯更快的代碼的一堆必要條件。

(C++ 社區的最新趨勢是放棄發明一種在所有情況下都是安全的正確編譯方案,並為用戶提供一種完全不同的方式來指示編譯器生成“消耗”值的代碼,其中包含很多更明確、可簡單翻譯的 C++ 代碼。)

一個評論說代碼可以相等或更慢,但海報沒有詳細說明。

當然,您可以隨意放置在程序上的那種注釋一般不能使代碼更高效 那太容易了,而且自相矛盾。

要么某個注解在您的代碼上指定了一個約束,這是對編譯器的承諾,並且您不能將它放在與代碼中的保證不對應的任何地方(如 C++ 中的noexcept ,C 中的restrict ),或者它會以各種方式破壞代碼( noexcept函數中的異常會停止程序,受限指針的別名會導致有趣的錯誤編譯和不良行為(以前在這種情況下未定義行為);然后編譯器可以使用它來優化代碼以特定的方式。

或者該注釋不會以任何方式約束代碼,並且編譯器不能指望任何東西並且該注釋不會創造任何更多的優化機會

如果您在某些情況下獲得更高效的代碼而無需使用注釋破壞程序,那么在其他情況下您可能會獲得效率較低的代碼。 這在一般情況下是正確的,對於消費語義尤其如此,它對 C++ 構造的翻譯施加了先前描述的約束。

我想合適的地方使用 this 是在任何函數返回或參數上,這些函數返回或參數是指針或引用,並且將在調用線程內傳遞或返回

不,它可能有用的唯一一種情況是預期的調用函數可能會使用消耗內存順序

暫無
暫無

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

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