等待多个未来

Waiting for multiple futures?

本文关键字:未来 等待      更新时间:2023-10-16

我想运行相同类型的任务(工作线程(,但一次不超过一定数量的任务。当任务完成时,其结果是新任务的输入,然后可以启动该任务。

有什么好方法可以在 C++11 中使用异步/未来范式来实现这一点?

乍一看,它看起来很简单,您只需生成多个任务:

std::future<T> result = std::async(...);

然后,运行 result.get() 以获取任务的异步结果。

但是,这里的问题是将来的对象必须存储在某种队列中,并逐个等待。但是,可以一遍又一遍地迭代未来的对象,检查它们中的任何一个是否已准备就绪,但由于不必要的 CPU 负载,这是不希望的。

是否有可能以某种方式等待给定集合中的任何未来准备就绪并获得其结果?

到目前为止,我能想到的唯一选择是没有任何异步/未来的老式方法。具体来说,生成多个工作线程,并在每个线程结束时将其结果推送到受互斥锁保护的队列中,通过条件变量通知等待线程队列已更新为更多结果。

有没有其他更好的异步/未来解决方案?

C++11 中的线程支持只是第一次传递,虽然std::future摇滚,但它还不支持多次等待。

但是,您可以相对低效地伪造它。 您最终会为每个std::future创建一个帮助线程(哎哟,非常昂贵(,然后将他们的"此future已准备就绪"收集到同步的多生产者单使用者消息队列中,然后设置一个使用者任务来调度给定std::future已准备就绪的事实。

此系统中的std::future没有添加太多功能,并且让任务直接声明它们已准备就绪并将其结果粘贴到上述队列中会更有效。 如果你走这条路,你可以编写与std::asyncstd::thread模式匹配的包装器,并返回一个表示队列消息的类似std::future的对象。 这基本上涉及重新实现并发库的一个块。

如果你想继续使用 std::future ,你可以创建 shared_future s,并让每个依赖任务依赖于shared_future s集:即,在没有中央调度程序的情况下执行此操作。 这不允许诸如中止/关闭消息之类的事情,我认为这对于强大的多线程任务系统至关重要。

最后,您可以等待 C++2x,或者每当并发 TS 折叠到标准中时,为您解决问题。

您可以创建">第 1 代"的所有未来,并将所有这些未来交给您的第 2 代任务,然后他们将自己等待他们的输入。

Facebook的愚蠢行为已经收集了期货上的Any/collectN/collectAll,我还没有尝试过,但看起来很有希望。

鉴于"Wating for Multiple Futures"的标题吸引了人们提出诸如"是否等待所有期货列表?您可以通过跟踪挂起的线程来充分做到这一点:

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 与传播运算符一起使用