kri*_*pet 18 c++ multithreading asynchronous c++11 stdasync
我已经多次被告知,我应该使用参数std::async来解决火灾和遗忘类型的任务std::launch::async(所以它最好在新的执行线程上使用它).
在这些陈述的鼓励下,我想看看如何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;
}
Run Code Online (Sandbox Code Playgroud)
没有看中这里,包函子f成std::packaged task与它的参数一起,启动它的一个新的std::thread被分离,并用返回std::future的任务.
现在代码测量执行时间std::chrono::high_resolution_clock:
int main(void)
{
constexpr unsigned short TIMES = 1000;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < TIMES; ++i)
{
someTask();
}
auto dur = std::chrono::high_resolution_clock::now() - start;
auto tstart = std::chrono::high_resolution_clock::now();
for (int i = 0; i < TIMES; ++i)
{
std::thread t(someTask);
t.detach();
}
auto tdur = std::chrono::high_resolution_clock::now() - tstart;
std::future<void> f;
auto astart = std::chrono::high_resolution_clock::now();
for (int i = 0; i < TIMES; ++i)
{
f = std::async(std::launch::async, someTask);
}
auto adur = std::chrono::high_resolution_clock::now() - astart;
auto mastart = std::chrono::high_resolution_clock::now();
for (int i = 0; i < TIMES; ++i)
{
f = myAsync(someTask);
}
auto madur = std::chrono::high_resolution_clock::now() - mastart;
std::cout << "Simple: " << std::chrono::duration_cast<std::chrono::microseconds>(dur).count() <<
std::endl << "Threaded: " << std::chrono::duration_cast<std::chrono::microseconds>(tdur).count() <<
std::endl << "std::sync: " << std::chrono::duration_cast<std::chrono::microseconds>(adur).count() <<
std::endl << "My async: " << std::chrono::duration_cast<std::chrono::microseconds>(madur).count() << std::endl;
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
哪里someTask()是一个简单的方法,我稍等一下,模拟一些完成的工作:
void someTask()
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
Run Code Online (Sandbox Code Playgroud)
最后,我的结果:
谁能解释这些结果?这似乎是std::aysnc很多比我幼稚的做法更慢,或者只是简单明了超脱 std::thread秒.那是为什么?在这些结果之后是否有任何理由使用std::async?
(注意我也用clang ++和g ++做了这个基准测试,结果非常相似)
更新:
在阅读Dave S的回答后,我更新了我的小基准如下:
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;
Run Code Online (Sandbox Code Playgroud)
所以std::futures现在没有被摧毁 - 因此加入 - 每次运行.在代码中进行此更改后,std::async会为我的实现和分离的std::threads 生成类似的结果.
Dav*_*e S 18
一个关键的区别是async返回的未来在未来被破坏时加入线程,或者在你的情况下,用新值替换.
这意味着它必须执行someTask()并加入线程,这两者都需要时间.您的其他测试都没有这样做,他们只是独立地生成它们.
sts::async返回一个特殊的std::future.这个未来有~future一个.wait().
所以你的例子根本不同.慢的实际上在你的时间执行任务.快速的只是排队任务,忘记如何知道任务完成.由于让线程持续超过main结尾的程序行为是不可预测的,因此应该避免使用它.
比较任务的正确方法是存储所产生的futuregenersting时,定时器结束之前.wait()/ .join()他们所有,或避免破坏的对象,直到定时器超时后.然而,最后一种情况使得sewuential版本看起来比它更糟糕.
在开始下一次测试之前,您需要加入/等待,否则您将从他们的时间中窃取资源.
请注意,移动的期货会从源中删除等待.
| 归档时间: |
|
| 查看次数: |
2531 次 |
| 最近记录: |