If I launch std::async with std::launch::async policy shouldn't it start every async task in a new thread? At the moment it looks that new async tasks move to a thread which just completed it's work. I'm using VC11 as my compiler. As you can see from the output when a new worker (e.g. a worker gets a thread with ID 34500 multiple times) is launched with std::async, it starts in a previously finished thread. Is my understanding of std::async wrong or is there an underlying work stealing queue or something of that sort?
Worker (ID=24072) starting.
Worker (ID=34500) starting.
Worker (ID=32292) starting.
Worker (ID=31392) starting.
Worker (ID=17976) starting.
Worker (ID=31580) starting.
Worker (ID=33512) starting.
Worker (ID=33804) starting.
Worker 32292 finished.
Worker (ID=32292) starting.
Worker 17976 finished.
Worker (ID=17976) starting.
Worker 31580 finished.
Worker (ID=31580) starting.
Worker 34500 finished.
Worker (ID=34500) starting.
Worker 34500 finished.
Worker (ID=34500) starting.
Worker 32292 finished.
Worker (ID=32292) starting.
Worker 17976 finished.
Worker (ID=17976) starting.
Worker 34500 finished.
Worker 17976 finished.
Worker 31580 finished.
Worker 32292 finished.
Worker 33804 finished.
Worker 31392 finished.
Worker 33512 finished.
Worker 24072 finished.
If I launch
std::async
withstd::launch::async
policy shouldn't it start every async task in a new thread?
The specification requires that the asynchronous operation be executed "as if in a new thread of execution" (C++11 §30.6.8/11). The important words here are: as if.
An already-running worker thread can be reused if and only if the behavior is the same as if a new thread was created. This means, for example, that variables with the thread_local
storage class must be reset between asynchronous operations executed on a single thread.
It is not necessary that the thread identifier be reset because a thread identifier only uniquely identifies a thread while it is running. If a thread terminates, another thread may be started with the first thread's identifier.
Is there an underlying work stealing queue or something of that sort?
This is implementation-specific. The Visual C++ 2012 implementation of the C++11 thread support library is built atop the Concurrency Runtime (ConcRT), which includes a work-stealing task scheduler.
James is right, with one correction: Microsoft implementation of launch::async is incorrect. This was discussed at length by the C++ concurrency working group in Redmond. Visual C++ 2012 is still in beta, so they will probably change the implementation to be Standard compliant.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With