Wie und Wann @async und @sync-Julia
Habe ich gelesen, das Dokumentation für die @async
und @sync
Makros aber immer noch nicht herausfinden, wie und Wann Sie zu verwenden, noch kann ich finden, viele Ressourcen oder Beispiele für die Sie an anderer Stelle auf den internet.
Mein unmittelbares Ziel ist es, einen Weg zu finden, um mehrere Mitarbeiter parallel arbeiten und dann warten, bis Sie alle fertig zu gehen in meinem code. Dieser post: Warten auf den Abschluss einer Aufgabe auf dem remote-Prozessor Julia enthält ein erfolgreicher Weg dies zu erreichen. Ich hatte gedacht, es sollte möglich sein die @async
und @sync
Makros, aber meine anfänglichen Fehler zu erreichen, das machte mich Fragen, ob ich verstehe richtig, wie und Wann diese Makros verwenden.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Laut der Dokumentation unter
?@async
, "@async
umschließt einen Ausdruck in eine Aufgabe." Was dies bedeutet ist, dass für was auch immer fällt in seinen Anwendungsbereich, Julia startet dieser task läuft, aber dann gehen Sie zu, was kommt als Nächstes im Skript ohne zu warten, für die Aufgabe abzuschließen. So, zum Beispiel, ohne das makro, das Sie erhalten:Aber mit dem makro erhalten Sie:
Julia so erlaubt es, das Skript zu gehen (und die
@time
makro vollständig ausgeführt) ohne zu warten, für die Aufgabe (in diesem Fall, Schlafsack für zwei Sekunden), um abzuschließen.Den
@sync
makro, durch Kontrast, wird "Warten, bis alle dynamisch-geschlossene Verwendungen von@async
,@spawn
,@spawnat
und@parallel
abgeschlossen sind." (laut der Dokumentation unter?@sync
). So sehen wir:In diesem einfachen Beispiel dann, es gibt keinen Punkt, zu der auch eine gemeinsame Instanz von
@async
und@sync
zusammen. Aber, wo@sync
können nützlich sein wird, wo Sie@async
angewendet, um mehrere Operationen, die Sie wünschen, um zu ermöglichen, beginnen alle auf einmal ohne zu warten, für jeden abgeschlossen.Zum Beispiel, nehmen wir an, wir haben mehrere Mitarbeiter und wir möchten, um zu beginnen, jeder von Ihnen, die Sie an einer Aufgabe arbeiten gleichzeitig und Hole dann die Ergebnisse aus diesen Aufgaben. Eine erste (aber falsche) Versuch könnte sein:
Das problem hier ist, dass die Schleife auf jede
remotecall_fetch()
Vorgang abgeschlossen, d.h. für jeden Prozess, um seine Arbeit abzuschließen (in diesem Fall Schlafgelegenheit für 2 Sekunden) bevor Sie fortfahren, um den nächsten beginnenremotecall_fetch()
Betrieb. Im Hinblick auf eine praktische situation, wir sind nicht immer die Vorteile der Parallelität, da unsere Prozesse nicht tun Ihre Arbeit (d.h. schlafen) gleichzeitig.Wir können dies korrigieren, jedoch durch die Verwendung einer Kombination der
@async
und@sync
Makros:Nun, wenn wir zählen jeden Schritt der Schleife, als einem separaten Vorgang, sehen wir, dass es zwei getrennte Vorgänge vorangestellt
@async
makro. Das makro erlaubt es jedem, diese zu starten, und der code weiterhin (in diesem Fall zum nächsten Schritt in der Schleife) vor der jeweiligen Oberflächen. Aber, die Verwendung der@sync
makro, dessen Geltungsbereich umfasst die gesamte Schleife, bedeutet, dass wir nicht gestatten, das Skript zu gehen Vergangenheit, die Schleife, bis alle Operationen vorangestellt@async
abgeschlossen haben.Ist es möglich, um eine noch mehr klares Verständnis von der Funktionsweise dieser Makros durch weitere Optimierungen obigen Beispiel zu sehen, wie die änderungen unter bestimmten Modifikationen. Zum Beispiel, nehmen wir an, wir müssen nur die
@async
ohne die@sync
:Hier, die
@async
makro erlaubt uns, weiter in unsere Schleife auch vor jederremotecall_fetch()
operation abgeschlossen ist. Aber für besser oder schlechter, wir haben keine@sync
makro zu verhindern, dass den code aus weiter Vergangenheit diese Schleife, bis alleremotecall_fetch()
Operationen fertig stellen.Doch jeder
remotecall_fetch()
Betrieb immer noch parallel laufen lassen, selbst wenn wir gehen. Wir können daran erkennen, dass wenn wir warten, bis zwei Sekunden, dann wird das array a mit den Ergebnissen, enthält:(Die "nichts" - element ist das Ergebnis einer erfolgreichen Abruf der Ergebnisse der sleep-Funktion, die keine return Werte)
Können wir auch sehen, dass die beiden
remotecall_fetch()
Operationen beginnen bei im wesentlichen der gleichen Zeit, da die print-Befehle, die Ihnen vorangehen führen Sie auch in der raschen Folge (die Ausgabe dieser Befehle wird hier nicht gezeigt). Vergleichen Sie dies mit dem nächsten Beispiel, wo die print-Befehle ausgeführt, 2 Sekunden Verzögerung aus jeder anderen:Wenn wir die
@async
makro auf die ganze Schleife (anstatt nur der innere Schritt), dann wieder unser Skript wird weiterhin sofort ohne zu warten, für dieremotecall_fetch()
Operationen zu beenden. Jetzt, jedoch, wir lassen nur das Skript weiterhin hinter der Schleife als ganzes. Wir uns nicht erlauben, jeden einzelnen Schritt der Schleife zu starten, bevor der Vorherige fertig ist. Als solche, anders als im Beispiel oben, zwei Sekunden, nachdem das Skript Erlös nach der Schleife, es ist das Ergebnis-array hat immer noch ein element als #undef zurück, der angibt, dass die zweiteremotecall_fetch()
Vorgang noch nicht abgeschlossen hat.Und, nicht überraschend, wenn wir die
@sync
und@async
direkt neben einander, erhalten wir, dass jederemotecall_fetch()
läuft nacheinander (statt gleichzeitig), aber wir wissen nicht weiter in den code, bis jeder fertig ist. In anderen Worten, das wäre, glaube ich, im wesentlichen äquivalent, wenn Sie hatten wir weder makro an Ort und Stelle, genau wiesleep(2)
verhält sich im wesentlichen identisch zu@sync @async sleep(2)
Beachten Sie auch, dass es möglich ist, komplizierter Vorgänge im Bereich der
@async
makro. Die Dokumentation gibt ein Beispiel mit einer ganzen Schleife im Rahmen der@async
.Update: daran Erinnern, dass die Hilfe für die sync-Makros, die besagt, dass es "Warten, bis alle dynamisch-geschlossene Verwendungen von
@async
,@spawn
,@spawnat
und@parallel
abgeschlossen sind." Für die Zwecke der was gilt als "abgeschlossen" es kommt, wie definieren Sie die Aufgaben, die im Rahmen der@sync
und@async
Makros. Betrachten Sie das folgende Beispiel ist eine leichte variation auf eines der Beispiele, die oben gegeben:Dem früheren Beispiel dauerte etwa 2 Sekunden ausgeführt werden, was darauf hinweist, dass die zwei Aufgaben parallel ausführen und das Skript wartet auf jeden, um die komplette Ausführung Ihrer Funktionen, bevor Sie fortfahren. Dieses Beispiel hat allerdings einen viel geringeren Zeit-Bewertung. Der Grund dafür ist, dass für die Zwecke der
@sync
dieremotecall()
Betrieb hat, "fertig", sobald es gesendet hat der Arbeitnehmer den job zu tun. (Beachten Sie, dass das resultierende array, eine, hier, nur enthält RemoteRef Objekt-Typen, die nur zeigen, dass es ist etwas Los mit einem bestimmten Prozess, die könnte in der Theorie heruntergeladen werden irgendwann in der Zukunft). Durch Kontrast, dieremotecall_fetch()
Betrieb hat nur "fertig", wenn Sie die Nachricht erhält, von dem Arbeiter, dass seine Aufgabe abgeschlossen ist.So, wenn Sie sind auf der Suche nach Möglichkeiten, um sicherzustellen, dass bestimmte Operationen mit Ihren Arbeitnehmern abgeschlossen haben, bevor Sie in Ihrem Skript (wie zum Beispiel wird in diesem Beitrag diskutiert: Warten auf den Abschluss einer Aufgabe auf dem remote-Prozessor Julia) ist es notwendig, sorgfältig darüber nachdenken, was gilt als "abgeschlossen" und wie Sie Messen und dann zu operationalisieren, dass Sie in Ihrem Skript.