2015-04-26 57 views
1

我在CppCon 2014年都是看Mike Acton's talk on Data-oriented design in C++,他給出了這樣的例子:可以``__restrict__這個``不知何故?

int Foo::Bar(int count) 
{ 
    int value = 0; 
    for (int i = 0; i < count; i++) { 
     if (m_someDataMemberOfFoo) value++ 
    } 
    return value; 
} 

,並解釋一些編譯器如何繼續重新閱讀m_someDataMemberOfFoo在每次迭代中,也許是因爲它的價值可能會因併發訪問。不管編譯器是否適合這樣做 - 是否可以告訴編譯器在執行某種方法時特別忽略任何併發訪問的可能性,以便它可以優化得更好?

換句話說,我可以告訴編譯器:this__restrict__ ed嗎?

+4

任何值得使用該名稱的編譯器都會考慮將循環檢出,或至少將'm_someDataMemberOfFoo'保存在寄存器中。任何嘗試使用此代碼同時修改'm_someDataMemberOfFoo'的程序都表現出未定義的行爲。 –

+0

@IgorTandetnik:不一定。這是一個不合理的語義假設。也許'm_someDataMemberOfFoo'應該通過併發修改來改變? – einpoklum

+0

我覺得這個假設在上下文中是合理的。如果'm_someDataMemberOfFoo'是線程安全的(比如說''atomic''),並且期望它會被同時修改,那麼整個問題都是沒有意義的。在某些情況下,「*某些*編譯器會在每次迭代中重新讀取」​​m_someDataMemberOfFoo「 - 所有編譯器都會這樣做,而且這對他們來說是完全有效且合理的 - 實際上是必需的。 –

回答

4
  1. __restrict__沒有在C++標準化的,所以這個問題只能在特定平臺來回答。對於GCC,你可以申請__restrict__thisin the same wayconst

    void T::fn() __restrict__ 
    
  2. 。在你的例子沒有潛在的混淆。 C++爲數據競爭指定未定義的行爲。

  3. A new system用於C++限制指針正在開發中。它可能會在C++ 17中被標準化。支持this是所述設計目標之一。

+0

別名不是我擔心的,它是併發訪問。假設我的循環是'(!m_YouRangSir){mySleep(Miliseconds(1000)); } ...... – einpoklum

+0

另外,這個建議看起來非常冗長而且很尷尬,我希望他們能做一些簡單的事情,比如'__restrict__',爲了避免模棱兩可的問題。 – einpoklum

+0

@einpoklum在此上下文中,別名包括併發訪問。如果循環中存在關鍵部分,則必須重新讀取該成員。如果你想使用'restrict'關鍵字,你可以'#define restrict [[alias_set()]]''。屬性可以放置在聲明的開頭,或者放在聲明符id的前面。我不確定提案如何適用於'this',現在我看它;這些例子只顯示*允許使用'this'進行鋸齒。 – Potatoswatter

2

通過您發佈的代碼,任何優化編譯的代碼都不應該重新讀取該類成員。但是,採取這種類似的代碼:

void Foo::Bar(int count, int* result) 
{ 
    *result = 0; 
    for (int i = 0; i < count; i++) { 
     if (m_someDataMemberOfFoo) (*result)++; 
    } 
} 

在這種情況下,編譯器必須假設結果== & m_someDataMemberOfFoo這樣的可能性,如果該構件具有int類型。很顯然,任何開發者都認爲這種方式應該被取消,但這是合法的,編譯器必須正確處理。

如果您將該方法標記爲「const」,甚至會出現這種情況。 const方法不允許通過使用這個指針來修改* this的任何部分(有一些例外)。但是,如果實際對象不是const,那麼*這個成員可以通過其他方式進行合法修改。

C語言中的「restrict」旨在解決這個問題,並希望C++中的相同特性能夠解決此問題。

+0

不能編譯器 - 至少在理論上 - 仍然優化您提供的示例代碼,因爲即使它假設結果==&m_someDataMemberOfFoo,該值設置爲0並且永遠不會達到增量。如果達到增量,結果不能別名m_someDataMemberOfFoo。 (這不會以任何方式使你正在創建的點無效,只是要求) –

+0

在我鏈接的聊天中,MSVC會在循環條件中用m_someDataMemberOfFoo編譯代碼以重複讀取該成員... – einpoklum

相關問題