C++ 为什么要使用 std::async?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17963172/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why should I use std::async?
提问by user2485710
I'm trying to explore all the options of the new C++11 standard in depth, while using std::async and reading its definition, I noticed 2 things, at least under linux with gcc 4.8.1 :
我试图深入探索新 C++11 标准的所有选项,同时使用 std::async 并阅读其定义,我注意到两件事,至少在带有 gcc 4.8.1 的 linux 下:
- it's called async, but it got a really "sequential behaviour", basically in the row where you call the futureassociated with your async function foo, the program blocks until the execution of fooit's completed.
- it depends on the exact same external library as others, and better, non-blocking solutions, which means
pthread
, if you want to usestd::async
you need pthread.
- 它被称为async,但它有一个真正的“顺序行为”,基本上在你调用与你的异步函数foo关联的未来的那一行,程序阻塞直到foo的执行完成。
- 它依赖于与其他库完全相同的外部库,以及更好的非阻塞解决方案,这意味着
pthread
,如果您想使用std::async
,则需要 pthread。
at this point it's natural for me asking why choosing std::async over even a simple set of functors ? It's a solution that doesn't even scale at all, the more future you call, the less responsive your program will be.
在这一点上,我很自然地问为什么选择 std::async 而不是一组简单的函子?这是一个根本无法扩展的解决方案,您调用的未来越多,您的程序响应就越慢。
Am I missing something ? Can you show an example that is granted to be executed in an async, non blocking, way ?
我错过了什么吗?您能否展示一个允许以异步、非阻塞方式执行的示例?
采纳答案by juanchopanza
If you need the result of an asynchronous operation, then you haveto block, no matter what library you use. The idea is that you get to choose when to block, and, hopefully when you do that, you block for a negligible time because all the work has already been done.
如果需要异步操作的结果,那么无论使用什么库,都必须阻塞。这个想法是你可以选择何时阻止,并且希望当你这样做时,你阻止的时间可以忽略不计,因为所有的工作都已经完成。
Note also that std::async
can be launched with policies std::launch::async
or std::launch::deferred
. If you don't specify it, the implementation is allowed to choose, and it could well choose to use deferred evaluation, which would result in all the work being done when you attempt to get the result from the future, resulting in a longer block. So if you want to make sure that the work is done asynchronously, use std::launch::async
.
另请注意,std::async
可以使用策略std::launch::async
或std::launch::deferred
. 如果不指定,则允许实现选择,并且很可能会选择使用延迟求值,这会导致当您尝试从未来获取结果时,所有工作都已完成,从而导致更长的块. 因此,如果您想确保异步完成工作,请使用std::launch::async
.
回答by Jonathan Wakely
- it's called async, but it got a really "sequential behaviour",
- 它被称为异步,但它有一个真正的“顺序行为”,
No, if you use the std::launch::async
policy then it runs asynchronously in a new thread. If you don't specify a policy it mightrun in a new thread.
不,如果您使用该std::launch::async
策略,则它会在新线程中异步运行。如果您不指定策略,它可能会在新线程中运行。
basically in the row where you call the future associated with your async function foo, the program blocks until the execution of foo it's completed.
基本上在你调用与你的异步函数 foo 相关的未来的那一行,程序会阻塞,直到 foo 的执行完成。
It only blocks if foo hasn't completed, but if it was run asynchronously (e.g. because you use the std::launch::async
policy) it might have completed before you need it.
它仅在 foo 尚未完成时阻塞,但如果它是异步运行的(例如因为您使用std::launch::async
策略),它可能在您需要它之前已经完成。
- it depends on the exact same external library as others, and better, non-blocking solutions, which means pthread, if you want to use std::async you need pthread.
- 它取决于与其他库完全相同的外部库,以及更好的非阻塞解决方案,这意味着 pthread,如果您想使用 std::async,则需要 pthread。
Wrong, it doesn't have to be implemented using Pthreads (and on Windows it isn't, it uses the ConcRT features.)
错误,它不必使用 Pthreads 实现(在 Windows 上不是,它使用 ConcRT 功能。)
at this point it's natural for me asking why choosing std::async over even a simple set of functors ?
在这一点上,我很自然地问为什么选择 std::async 而不是一组简单的函子?
Because it guarantees thread-safety and propagates exceptions across threads. Can you do that with a simple set of functors?
因为它保证线程安全并跨线程传播异常。你能用一组简单的函子来做到这一点吗?
It's a solution that doesn't even scale at all, the more future you call, the less responsive your program will be.
这是一个根本无法扩展的解决方案,您调用的未来越多,您的程序响应就越慢。
Not necessarily. If you don't specify the launch policy then a smart implementation can decide whether to start a new thread, or return a deferred function, or return something that decides later, when more resources may be available.
不必要。如果您没有指定启动策略,那么智能实现可以决定是启动一个新线程,还是返回延迟函数,或者返回一些稍后决定的内容,当更多资源可用时。
Now, it's true that with GCC's implementation, if you don't provide a launch policy then with current releases it will never run in a new thread (there's a bugzilla reportfor that) but that's a property of that implementation, not of std::async
in general. You should not confuse the specification in the standard with a particular implementation. Reading the implementation of one standard library is a poor way to learn about C++11.
现在,确实,对于 GCC 的实现,如果您不提供启动策略,那么对于当前版本,它永远不会在新线程中运行(有一个bugzilla 报告),但这是该实现的属性,而不是std::async
一般. 您不应将标准中的规范与特定实现混淆。阅读一个标准库的实现是学习 C++11 的一种糟糕方式。
Can you show an example that is granted to be executed in an async, non blocking, way ?
您能否展示一个允许以异步、非阻塞方式执行的示例?
This shouldn't block:
这不应该阻止:
auto fut = std::async(std::launch::async, doSomethingThatTakesTenSeconds);
auto result1 = doSomethingThatTakesTwentySeconds();
auto result2 = fut.get();
By specifying the launch policy you force asynchronous execution, and if you do other work while it's executing then the result will be ready when you need it.
通过指定启动策略,您可以强制异步执行,如果您在执行时执行其他工作,那么结果将在您需要时准备就绪。
回答by Yakk - Adam Nevraumont
I think your problem is with std::future
saying that it blocks on get
. It only blocks if the result isn't already ready.
我认为您的问题std::future
在于说它阻止了get
. 它仅在结果尚未就绪时阻塞。
If you can arrange for the result to be already ready, this isn't a problem.
如果你可以安排结果已经准备好了,这不是问题。
There are many ways to know that the result is already ready. You can poll the future
and ask it (relatively simple), you could use locks or atomic data to relay the fact that it is ready, you could build up a framework to deliver "finished" future
items into a queue that consumers can interact with, you could use signals of some kind (which is just blocking on multiple things at once, or polling).
有很多方法可以知道结果已经准备好了。您可以轮询future
并询问它(相对简单),您可以使用锁或原子数据来传达它已准备好的事实,您可以构建一个框架将“完成”的future
项目交付到消费者可以与之交互的队列中,您可以使用某种信号(这只是一次阻塞多个事物,或轮询)。
Or, you could finish all the work you can do locally, and then block on the remote work.
或者,您可以在本地完成您可以完成的所有工作,然后阻止远程工作。
As an example, imagine a parallel recursive merge sort. It splits the array into two chunks, then does an async
sort on one chunk while sorting the other chunk. Once it is done sorting its half, the originating thread cannot progress until the second task is finished. So it does a .get()
and blocks. Once both halves have been sorted, it can then do a merge (in theory, the merge can be done at least partially in parallel as well).
例如,想象一个并行递归归并排序。它将数组分成两个块,然后async
对一个块进行排序,同时对另一个块进行排序。一旦完成对它的一半进行排序,原始线程在第二个任务完成之前无法继续进行。所以它做了 a.get()
和块。一旦对两半进行了排序,就可以进行合并(理论上,合并也可以至少部分并行进行)。
This task behaves like a linear task to those interacting with it on the outside -- when it is done, the array is sorted.
对于那些在外部与之交互的人来说,这个任务的行为就像一个线性任务——当它完成时,数组被排序。
We can then wrap this in a std::async
task, and have a future
sorted array. If we want, we could add in a signally procedure to let us know that the future
is finished, but that only makes sense if we have a thread waiting on the signals.
然后我们可以将它包装在一个std::async
任务中,并有一个future
排序的数组。如果我们愿意,我们可以添加一个信号过程来让我们知道future
已经完成,但这只有在我们有一个线程等待信号时才有意义。
回答by fatihk
In the reference: http://en.cppreference.com/w/cpp/thread/async
在参考:http: //en.cppreference.com/w/cpp/thread/async
If the async flag is set (i.e. policy & std::launch::async != 0), then async executes the function f on a separate thread of execution as if spawned by std::thread(f, args...), except that if the function f returns a value or throws an exception, it is stored in the shared state accessible through the std::future that async returns to the caller.
如果设置了 async 标志(即 policy & std::launch::async != 0),则 async 在单独的执行线程上执行函数 f,就像由 std::thread(f, args...) 产生一样,除了如果函数 f 返回一个值或抛出异常,它会存储在可通过 async 返回给调用者的 std::future 访问的共享状态中。
It is a nice property to keep a record of exceptions thrown.
记录抛出的异常是一个很好的特性。
回答by msoodb
http://www.cplusplus.com/reference/future/async/
http://www.cplusplus.com/reference/future/async/
there are three type of policy,
有三种类型的政策,
launch::async
launch::deferred
launch::async|launch::deferred
launch::async
launch::deferred
launch::async|launch::deferred
by default launch::async|launch::deferred
is passed to std::async
.
默认情况下launch::async|launch::deferred
传递给std::async
.