11

有没有人有相当新的经验std::async?我们目前正在实现一个并行文件解析器,它读取一个文件块并将这个块传递给一个异步函数。

以这种方式使用 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));
}
4

4 回答 4

17

行为符合规范,即使它不是您想要的。如果您未指定启动策略,则将其视为async|deferred,这意味着由实现决定哪个。deferred如果有选择,GCC 碰巧总是选择。

于 2012-04-08T02:20:09.240 回答
5

EDIT2:我会解释更多。

std::async 承诺“未来”;那就是:当你想要它时,它就会出现。它现在可以计算,它可以在您要求时计算,我们只是承诺它会发生。

就像我下面的海报一样,GCC 默认为 deferred(这意味着,当它被要求时,它会履行该承诺,并且可能不会事先)。这个默认的原因是因为 GCC 还没有提供适当的 C++11 线程支持。它没有一个好的内部线程调度程序,除此之外还有很多其他东西。这有点像黑客。不,更像是一堆黑客。事实上,如果你在 GCC 上用 C++11 编写线程代码,那么当他们实现特性时,它就会正常工作;现在,它大部分工作正常。我的意思是,你最终得到结果,对吧?

如果你告诉它启动一个线程,它会启动一个线程,因为它(目前)太愚蠢了,无法意识到它可以而且应该独立运行(不像 CLang,它目前具有更好的内部线程调度程序)。

编辑:认真的?误入歧途!

这是我的参考! http://gcc.gnu.org/projects/cxx0x.html。请注意,“并发”下的几乎所有内容,包括“内存模型”都标记为 NO 。GCC.GNU.org。你知道他们是 GCC 的权威。

根据我的评论稍作编辑:

我真的建议使用 Boost。当 GCC 准备好时,对正确的 C++11 支持不会有很大的飞跃。C++11 中的新线程模型需要与 GCC 或 MSVC 使用的不同的内存布局,而且它们还没有真正实现。

于 2012-04-07T23:50:36.677 回答
1

所以我知道这是 2 年后,但我不禁觉得有必要回应 @std''OrgnlDave 关于 GCC 与 CLang 的评论,请注意至少目前,2015 年 1 月,clang 版本 3.5 和GCC 4.9 版具有完全相同的行为。这种行为是,当没有提供启动策略时,默认为不同,并在调用 future::get 时执行,并且只有当显式提供异步启动策略时,编译器才会导致在后台执行函数。

于 2015-01-07T21:17:14.533 回答
1

更新的答案:GCC 7.3.0 和 Clang 6.0 都将std::async()在默认启动策略的单独线程上执行工作。两者都将创建与调用一样多的线程std::async()(经过 100 次调用测试)。

我不知道 GCC 的这种行为何时改变。

于 2018-07-21T19:41:01.617 回答