Task based concurrency
-
Hallo,
ich befolge grade die Tutorial Serie von Bartosz Milewski zum Thema Concurrency und habe eine Frage zum Task based Ansatz mit Async. Der vollständigkeit halber hier einmal der Link: https://www.youtube.com/watch?v=_Ll0PIobErE, 15te minute.
Mein Quellcode sieht genauso aus, wie bei ihm, wenn ich mein Programm aber ausführe, werden alle Tasks in dem main Thread ausgeführt. Bei ihm werden die ersten 6 Tasks in unterschiedlichen threads ausgeführt und nur die übrigen 4 anschließend im main thread.
Ich habe das Programm auf einer Maschine mit 4 Cores ausgeführt und alle tasks wurden sequenziell auf dem main thread abgearbeitet. Daher wollte ich mal nachfragen, woran das liegt und ob ich doch etwas falsch gemacht habe.
Hier ist der Code von mir und dem Tutorial:
int main() { std::cout << "main thread: " << std::this_thread::get_id() << std::endl; std::vector<std::future<void>> futures; for (int i = 0; i != 10; ++i) { auto fut = std::async([] { std::this_thread::sleep_for(std::chrono::seconds(2)); std::cout << "thread id: " << std::this_thread::get_id() << std::endl; }); futures.push_back(std::move(fut)); } std::for_each(futures.begin(), futures.end(), [](std::future<void> &f){ f.wait(); }); std::cout << std::endl; std::this_thread::sleep_for(std::chrono::seconds(10)); return 0; }
-
std::async
hat auch einen Overload der die Launch Policy angibt. Du hast den ohne explizite Policy Angabe gewählt:Behaves the same as
async(std::launch::async | std::launch::deferred, f, args...)
. In other words,f
may be executed in another thread or it may be run synchronously when the resultingstd::future
is queried for a value.Du möchtest wohl nur
std::launch::async
angeben, damit tatsächlich ein neuer Thread zur Ausführung verwendet wird.auto fut = std::async(std::launch::async, [] { std::this_thread::sleep_for(std::chrono::seconds(2)); std::cout << "thread id: " << std::this_thread::get_id() << std::endl; });
-
Hallo Arcoth,
vielen Dank für deine Antwort. Ich hab noch eine weitere Frage dazu: Wovon hängt es denn ab, ob ein Task in einem separatem Thread ausgeführt wird oder im main thread, wenn ich keine run policy übergebe?
-
Async schrieb:
Hallo Arcoth,
vielen Dank für deine Antwort. Ich hab noch eine weitere Frage dazu: Wovon hängt es denn ab, ob ein Task in einem separatem Thread ausgeführt wird oder im main thread, wenn ich keine run policy übergebe?
Hängt laut CPP-Reference von der Implementationm der STL ab.
If both the std::launch::async and std::launch::deferred flags are set in policy, it is up to the implementation whether to perform asynchronous execution or lazy evaluation.
-
Der Sinn davon ist, dass die Implementierung selber entscheiden können soll, was in einer Situation effizienter ist. Kann der Compiler beispielsweise erkennen, dass die Funktion kaum Zeit benötigen wird, kann er sie bei
deferred
direkt zumget
verschieben.Das kann er auch machen, wenn ein Thread auf N Futures wartet: Er erzeugt (N-1) zusätzliche Threads und erledigt die übrig gebliebene Aufgabe im Thread, der ansonsten nur warten würde.
In generischem Code ist das sinnvoll, wenn die Art der Arbeit noch nicht abzusehen ist. Ob das ein Compiler bzw eine Standardbibliothek so kompliziert umsetzt, ist eine andere Frage.
async
ist wie eine Annotation, die dem Compiler eine Zusatzinformation liefert. Wennif
eine räumliche Verzweigung ist, istasync
eine zeitliche: "Dieser Funktionsaufruf ist zeitlich unabhängig von den Statements danach". Was sich verzweigt, muss irgendwann wieder zusammengeführt werden.future
modelliert die nicht abgeschlossene Verzweigung, die man mitget
abschließen kann.