2012-04-07 88 views
8

有沒有人有相當新的std::async的經驗?我們目前正在實現一個並行文件解析器,它讀取一個文件塊並將這個塊傳遞給一個異步函數。GCC的行爲與std :: async(std :: launch :: async)與Clang的行爲

使用Clang(v3.0)這種方式非常適用於默認的std::async策略(取決於實施)。在兩個核心的機器上,最多可以啓動4個線程,效果非常好。

但是對於GCC(v4.7),文件讀線程不會產生任何新線程,從而使程序最終完全順序。

使用std::launch::async,兩個版本差不多都是一樣的(應該是這種情況)。

有誰知道GCC的C++ 11線程能力的當前狀態?或者這可能是我們實施中的錯誤?

短代碼:

while (readNewChunk()) { 
    Chunk &chunk = fileReader_.getChunk(); //reading the file 
    ChunkLoader *chunkLoader = new ChunkLoader(); 
    auto ftr = std::async(std::launch::async, &ChunkLoader::createDictionaries, chunkLoader); 
    dictCreationFutures_.push_back(std::move(ftr)); 
} 
+0

我真的會推薦使用Boost。它不會是一個適當的C++ 11支持的大跳躍。 C++ 11中的新線程模型需要與GCC或MSVC使用的不同的內存佈局,並且它們的實現並不是很多。 – 2012-04-07 23:49:15

回答

15

行爲在規範內,即使它不是你想要的。如果您未指定啓動策略,則將其視爲async|deferred,這意味着要由實施決定哪一個。如果給出選擇,GCC恰好總是挑選deferred

+0

謝謝你清理那個。我認爲當前所有的實現都有點「更加智能」,而不僅僅是簡單的_deferred_。 – Bouncner 2012-04-09 15:20:25

+4

我不同意。這就是標準所說的(強調我的):「如果這個策略與其他策略一起被指定,例如當使用'launch :: async | launch :: deferred'的策略值時,實現應該推遲調用或選擇政策_當沒有更多的併發能夠被有效利用。「這與啓動任何推遲的新線程大不相同。 – 2013-04-17 09:14:55

5

EDIT2:我要解釋一點。

std :: async promises a'future;'那就是:當你想要的時候,它會在那裏。現在可能會計算出來,可能會在你提出要求時計算出來,我們只是希望它會發生。

像我下面的海報筆記一樣,海灣合作委員會默認爲延期(這意味着,它會履行承諾,當它被要求,可能不會事先)。這種默認的原因是因爲GCC還沒有提供適當的C++ 11線程支持。它沒有一個好的內部線程調度器,還有很多其他的東西。這有點破解。不,更像是一堆黑客。事實上,如果您在GCC上使用C++ 11編寫線程代碼,那麼當它們實現功能時它會更加正確;現在,它主要是正確的。我的意思是,你最終得到的結果,對吧?如果你告訴它啓動一個線程,它會,因爲它太愚蠢了(現在)意識到它可以並且應該獨立運行(不像CLang,它有更好的內部線程調度器)。

編輯:認真嗎?錯誤地下調了!

這是我的參考! http://gcc.gnu.org/projects/cxx0x.html。請注意,「併發」(包括「內存模型」)下的幾乎所有內容都標記爲「否」。 GCC.GNU.org。他們是你知道的GCC的權威。

從我的評論稍微編輯:

我真的會推薦使用Boost。當GCC準備就緒時,它不會大幅跳躍到正確的C++ 11支持。 C++ 11中的新線程模型需要與GCC或MSVC使用的不同的內存佈局,而且它們還沒有實現得太多。

+3

在「內存佈局」方面,C++ 11發生了哪些變化? – 2012-04-08 01:56:37

+0

@NicolBolas http://gcc.gnu.org/projects/cxx0x.html。請注意,幾乎所有包括'內存模型'在內的'併發'下的所有內容都被標記爲否 – 2012-04-08 13:55:00

+5

是的,但這並不能解釋「內存*佈局*」更改的內容。佈局是關於事物相對於其他事物的地方。內存*模型*解釋了有關訪問變量在其他線程中何時可見的規則等。 – 2012-04-08 17:09:31

1

所以我明白這是2年後,但我不禁覺得有必要回應@ std''OrgnlDave對GCC與CLang的評論,要注意至少目前2015年1月鏗鏘風3.5版和GCC 4.9版具有完全相同的行爲。這種行爲是,當沒有啓動策略提供時,默認爲不同,並且在future :: get被調用時執行,並且只有當顯式提供異步啓動策略時,編譯器纔會導致在後臺執行該函數。