2012-04-07 97 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被调用时执行,并且只有当显式提供异步启动策略时,编译器才会导致在后台执行该函数。