提问人:alveko 提问时间:10/7/2013 最后编辑:Konrad Rudolphalveko 更新时间:11/15/2021 访问量:30577
等待多个未来?
Waiting for multiple futures?
问:
我想运行相同类型的任务(工作线程),但一次不超过一定数量的任务。当任务完成时,其结果是新任务的输入,然后可以启动该任务。
有什么好的方法可以在 C++11 中使用异步/未来范式实现这一点吗?
乍一看,它看起来很简单,您只需生成多个任务:
std::future<T> result = std::async(...);
然后,运行以获取任务的异步结果。result.get()
然而,这里的问题是,未来的对象必须存储在某种队列中,并一个接一个地等待。但是,可以一遍又一遍地遍历未来的对象,检查它们是否已准备就绪,但由于不必要的 CPU 负载,因此不需要这样做。
是否有可能以某种方式等待给定集合的任何未来准备好并获得其结果?
到目前为止,我能想到的唯一选择是没有任何异步/未来的老式方法。具体来说,生成多个工作线程,并在每个线程的末尾将其结果推送到受互斥锁保护的队列中,通过条件变量通知等待线程队列已更新了更多结果。
有没有其他更好的异步/未来解决方案?
答:
你可以创造“第一代”的所有未来,并将所有这些未来交给你的第二代任务,然后他们自己等待他们的输入。
评论
C++11 中的线程支持只是第一次通过,虽然很不稳定,但它还不支持多次等待。std::future
但是,您可以相对低效地伪造它。你最终会为每个线程创建一个帮助线程(哎呀,非常昂贵),然后将他们的“这已经准备好了”收集到一个同步的多生产者单消费者消息队列中,然后设置一个消费者任务来调度给定的准备就绪的事实。std::future
future
std::future
在这个系统中,没有添加太多功能,并且让任务直接声明它们已准备就绪并将其结果粘贴到上述队列中会更有效率。如果采用此路线,则可以编写与 或 模式匹配的包装器,并返回表示队列消息的类似对象。这基本上涉及重新实现并发库的块。std::future
std::async
std::thread
std::future
如果你想继续使用 ,你可以创建 s,并让每个依赖任务都依赖于 s 的集合:即,在没有中央调度程序的情况下执行。这不允许像中止/关闭消息这样的事情,我认为这对于一个强大的多线程任务系统来说是必不可少的。std::future
shared_future
shared_future
最后,您可以等待 C++2x,或者每当并发 TS 折叠到标准中时,为您解决问题。
评论
when_any
when_all
.then
future
.then
.then
future
鉴于“为多个未来而战”的标题吸引了人们提出诸如“是否需要等待未来清单?您可以通过跟踪待处理的线程来充分做到这一点:
unsigned pending = 0;
for (size_t i = 0; i < N; ++i) {
++pending;
auto callPause =
[&pending, i, &each, &done]()->unsigned {
unsigned ret = each();
results[i] = ret;
if (!--pending)
// called in whatever thread happens to finish last
done(results);
return ret;
};
futures[i] = std::async(std::launch::async, each);
}
可以将 std::experimental::when_all 与 spread 运算符一起使用
评论
facebook 的愚蠢在期货上有 collectAny/collectN/collectAll,我还没有尝试过,但看起来很有希望。
评论
when_any(futures...).then(foo)
when_any
spawning multiple worker threads and at the end of each thread push its result into a mutex-protected queue
对我来说听起来不错。如果工作线程只是偶尔检查队列大小≥ 1,则甚至不需要通知。when_any
.then(...)