[英]What does the [[carries_dependency]] attribute mean?
有人能用凡人懂的語言來解釋嗎?
[[carries_dependency]]
用於允許跨函數調用攜帶依賴項。 這可能允許編譯器在與std::memory_order_consume
一起使用時生成更好的代碼,以便在具有弱排序架構(例如 IBM 的 POWER 架構)的平台上的線程之間傳輸值。
特別是,如果使用memory_order_consume
讀取的值傳遞給函數,然后沒有[[carries_dependency]]
,則編譯器可能必須發出內存柵欄指令以保證支持適當的內存排序語義。 如果參數用[[carries_dependency]]
注釋,那么編譯器可以假設函數體將正確攜帶依賴項,並且可能不再需要此圍欄。
類似地,如果一個函數返回一個加載了memory_order_consume
的值,或者從這樣的值派生出來,那么如果沒有[[carries_dependency]]
編譯器可能需要插入一個柵欄指令來保證適當的內存排序語義得到支持。 有了[[carries_dependency]]
注釋,這個圍欄可能不再是必要的,因為調用者現在負責維護依賴樹。
例如
void print(int * val)
{
std::cout<<*val<<std::endl;
}
void print2(int * [[carries_dependency]] val)
{
std::cout<<*val<<std::endl;
}
std::atomic<int*> p;
int* local=p.load(std::memory_order_consume);
if(local)
std::cout<<*local<<std::endl; // 1
if(local)
print(local); // 2
if(local)
print2(local); // 3
在第 (1) 行中,依賴項是顯式的,因此編譯器知道local
被取消引用,並且它必須確保保留依賴項鏈以避免對 POWER 的圍欄。
在第 (2) 行中, print
的定義是不透明的(假設它不是內聯的),因此編譯器必須發出一個柵欄以確保在print
中讀取*p
返回正確的值。
在第 (3) 行,編譯器可以假設雖然print2
也是不透明的,但是從參數到解除引用的值的依賴性會保留在指令流中,並且在 POWER 上不需要圍欄。 顯然, print2
的定義實際上必須保留這種依賴關系,因此該屬性也會影響為print2
生成的代碼。
簡而言之,我認為,如果有carry_dependency 屬性,那么函數的生成代碼應該針對某個情況進行優化,當實際參數確實來自另一個線程並帶有依賴項時。 類似的返回值。 如果該假設不成立(例如在單線程程序中),則可能會缺乏性能。 但在相反的情況下,沒有 [[carries_dependency]] 可能會導致性能不佳......除了性能改變之外沒有其他影響。
例如,指針解引用操作取決於指針先前是如何獲得的,如果指針 p 的值來自另一個線程(通過“消費”操作),則考慮先前由另一個線程分配給 *p 的值並且可見。 可能還有另一個指針 q 等於 p (q==p),但由於它的值不是來自其他線程,因此 *q 的值可能與 *p 不同。 實際上 *q 可能會引發一種“未定義的行為”(因為訪問內存位置與進行分配的另一個線程不協調)。
真的,在某些工程案例中,內存(和思維)的功能似乎存在一些大錯誤......>:-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.