Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么std::async比简单的分离线程慢?_C++_Multithreading_C++11_Asynchronous_Stdasync - Fatal编程技术网

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;