12

我一直在思考std::async以及应该如何在未来的编译器实现中使用它。然而,现在我有点被一些感觉像是设计缺陷的东西困住了。

std::async几乎取决于实现,可能有两种变体launch::async,一种将任务启动到新线程中,另一种使用线程池/任务调度程序。

但是,根据用于实现的这些变体中的哪一个,std::async用法会有很大差异。

对于基于“线程池”的变体,您将能够启动许多小任务而不必担心开销,但是,如果其中一个任务在某个时候阻塞怎么办?

另一方面,“启动新线程”变体不会遇到阻塞任务的问题,另一方面,启动和执行任务的开销会非常高。

线程池: +低开销,-从不阻塞

启动新线程: +fine with blocks,-high开销

所以基本上取决于实现,我们使用的方式std::async会非常谨慎。如果我们有一个程序可以很好地与一个编译器一起工作,那么它可能会在另一个编译器上运行得非常糟糕。

这是设计使然吗?还是我错过了什么?你会像我一样认为这是一个大问题吗?

在当前规范中,我缺少类似的东西std::oversubscribe(bool),以便实现独立于std::async.

编辑:据我所知,C++11 标准文档没有给出关于发送到的任务是否std::async阻塞的任何提示。

4

2 回答 2

11

std::async使用“就像在新线程中一样”运行的策略启动的任务std::launch::async,因此不真正支持线程池 --- 运行时必须在每个任务执行之间拆除并重新创建所有线程局部变量,这不是直截了当。

这也意味着您可以期望std::launch::async以并发运行的策略启动的任务。可能会有启动延迟,并且如果您的运行线程多于处理器,则会出现任务切换,但它们应该正在运行,而不是仅仅因为一个碰巧等待另一个而死锁。

一个实现可以选择提供一个扩展,允许您的任务在线程池中运行,在这种情况下,由该实现来记录语义。

于 2012-02-20T15:42:44.510 回答
1

我希望实现能够启动新线程,并将线程池留给标准化它的未来版本的 C++。有没有使用线程池的实现?


MSVC 最初使用基于其并发运行时的线程池。根据STL Fixes In VS 2015, Part 2这已被删除。C++ 规范为实现者留下了一些空间来做聪明的事情,但是我认为它并没有为这个线程池实现留下足够的空间。特别是我认为规范仍然要求thread_local对象将被销毁和重建,但使用 ConcRT 的线程池将不支持这一点。

于 2012-02-20T15:42:10.073 回答