C++ 为什么std::async比简单的分离线程慢?
我已经被告知好几次了,我应该使用C++ 为什么std::async比简单的分离线程慢?,c++,multithreading,c++11,asynchronous,stdasync,C++,Multithreading,C++11,Asynchronous,Stdasync,我已经被告知好几次了,我应该使用std::async来处理带有std::launch::async参数的fire&forget类型的任务(因此它最好在新的执行线程上发挥神奇的作用) 受这些声明的鼓舞,我想看看std::async与以下内容的比较: 顺序执行 一个简单的分离std::thread 我的简单异步“实现” 我的朴素异步实现如下所示: template <typename F, typename... Args> auto myAsync(F&& f, A
std::async
来处理带有std::launch::async
参数的fire&forget类型的任务(因此它最好在新的执行线程上发挥神奇的作用)
受这些声明的鼓舞,我想看看std::async
与以下内容的比较:
- 顺序执行
- 一个简单的分离
std::thread
- 我的简单异步“实现”
template <typename F, typename... Args>
auto myAsync(F&& f, Args&&... args) -> std::future<decltype(f(args...))>
{
std::packaged_task<decltype(f(args...))()> task(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
auto future = task.get_future();
std::thread thread(std::move(task));
thread.detach();
return future;
}
其中someTask()
是一种简单的方法,我在这里稍等片刻,模拟完成的一些工作:
void someTask()
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
最后,我的结果:
- 电话:1263615
- 电话:47111
- 标准:同步:821441
- 我的异步:30784
std::aysnc
比我天真的实现要慢得多,或者只是简单的分离的std::thread
s为什么?在这些结果之后,是否有任何理由使用std::async
(注意,我也用clang++和g++进行了这个基准测试,结果非常相似)
更新:
在阅读了Dave的答案后,我更新了我的小基准,如下所示:
std::future<void> f[TIMES];
auto astart = std::chrono::high_resolution_clock::now();
for (int i = 0; i < TIMES; ++i)
{
f[i] = std::async(std::launch::async, someTask);
}
auto adur = std::chrono::high_resolution_clock::now() - astart;
std::未来f[次];
auto astart=std::chrono::高分辨率时钟::now();
对于(int i=0;i
因此,
std::future
s现在不会在每次运行时被销毁,因此也不会加入。在代码中进行此更改之后,std::async
会产生与我的实现类似的结果&分离的std::thread
s.一个关键区别是,异步返回的未来会在未来被破坏时加入线程,或者在您的情况下,被一个新值替换
这意味着它必须执行
someTask()
并加入线程,这两者都需要时间。您的其他测试都没有这样做,它们只是独立地生成它们。sts::async
返回一个特殊的std::future
。这个未来有一个~future
,它执行.wait()
所以你们的例子根本不同。速度慢的人实际上会在你的时间安排中完成任务。速度快的人只是把任务排成一列,忘记了如何知道任务已经完成。由于让线程持续超过main结尾的程序的行为是不可预测的,因此应该避免它
比较任务的正确方法是在生成时,在计时器结束之前,存储生成的未来
。wait()/。join()
所有任务,或者避免在计时器过期之前销毁对象。然而,这最后一个案例使缝合版本看起来比实际情况更糟
您确实需要在开始下一个测试之前加入/等待,否则您将从它们的计时中窃取资源
请注意,移动的期货将从源代码中删除等待。我确信这不是问题所在,但我只需要询问信息的完整性。您正在测量调试(未优化)或发布(优化)版本吗?我假设一个优化的构建,否则任何测量都是毫无意义的,但我必须问。@JesperJuhl完全正确的问题,但我是用-O2测量的。“异步返回的未来在未来被破坏时加入线程”AKA:永远不要使用
std::async
@KerrekSB:如果你想要的话,您应该显式地调用future::wait
,就像您对其他future
所做的那样。问题是async
返回的future
与其他future
对象的行为不同。问题在于不一致性,而不是行为。这种不一致、不可复制的行为很容易让人意外地做出错误的事情,就像这里所做的那样。谢谢你,这解开了谜团。但是,这种行为背后的原因是什么?你能给我指一些关于这件事的文章,或者类似的东西吗?@kristepkristpet部分得到了回答(免责声明:这是我写的)。。不管怎样,这一部分的未来在2012/2013年曾被大量讨论过,但我不确定最终的结论是什么。
std::future<void> f[TIMES];
auto astart = std::chrono::high_resolution_clock::now();
for (int i = 0; i < TIMES; ++i)
{
f[i] = std::async(std::launch::async, someTask);
}
auto adur = std::chrono::high_resolution_clock::now() - astart;