Async.Parallel oder Array.Parallel.Map?

8

Ich versuche ein Muster zu implementieren, das ich von Don Symes Blog gelesen habe

( Ссылка )

Dies deutet darauf hin, dass es Möglichkeiten für massive Leistungsverbesserungen durch die Nutzung asynchroner I / O gibt. Ich versuche derzeit, ein Stück Code zu verwenden, der mit Array.Parallel.Map "funktioniert", und zu sehen, ob ich irgendwie dasselbe Ergebnis mit Async.Parallel erzielen kann, aber Async.Parallel, und kann nichts zur Arbeit bringen.

Ich habe ein Stück Code (unten vereinfacht, um den Punkt zu veranschaulichen), der erfolgreich ein Array von Daten für einen Cusip abruft. (Eine Preisserie zum Beispiel)

%Vor%

Dieser Ansatz konstruiert also ein Array von Arrays, indem eine Verbindung über das Internet zu meinem Datenlieferanten für jede Aktie hergestellt wird (was bis zu 3000 sein kann) und gibt mir eine Matrix zurück (1 pro Aktie, mit einem Preis) Serie für jeden). Ich verstehe zwar nicht, was unter Array.Parallel.map passiert, aber ich frage mich, ob dies ein Szenario ist, in dem Ressourcen unter der Haube verschwendet werden und es tatsächlich schneller sein könnte, asynchrone I / O zu verwenden? Um dies zu testen, habe ich versucht, diese Funktion mithilfe von asyncs zu erstellen, und ich denke, dass die folgende Funktion dem Muster in Don Syme's Artikel mit den URLs folgt, aber nicht mit "let!" Kompiliert wird.

%Vor%

Der Fehler, den ich bekomme, ist: Von diesem Ausdruck wurde erwartet, dass er Async & lt; 'a & gt; aber hier ist der Typ obj

Es kompiliert gut mit "lassen" statt "lassen!", aber ich hatte gedacht, der ganze Punkt war, dass Sie das Ausrufezeichen benötigen, damit der Befehl ausgeführt wird, ohne einen Thread zu blockieren.

Also ist die erste Frage wirklich, was ist falsch mit meiner obigen Syntax, in getStockDataAsync, und dann auf einer höheren Ebene, kann jemand einige zusätzliche Erkenntnisse über asynchrone I / O bieten und ob das Szenario, das ich vorgestellt habe, würde davon profitieren, macht es möglicherweise viel, viel schneller als Array.Parallel.map? Vielen Dank.

    
user297400 19.03.2010, 14:15
quelle

2 Antworten

18
Mit

F # asynchronen Workflows können Sie asynchrone Berechnungen implementieren. F # unterscheidet jedoch zwischen der üblichen Berechnung und asynchronen Berechnungen . Dieser Unterschied wird vom Typensystem verfolgt. Zum Beispiel hat eine Methode, die Webseiten herunterlädt und synchron ist, den Typ string -> string (URL wird genommen und HTML zurückgegeben), aber eine Methode, die das Gleiche asynchron tut, hat den Typ string -> Async<string> . Im Block async können Sie mit let! asynchrone Operationen aufrufen, aber alle anderen (synchronen Standardmethoden) müssen mit let aufgerufen werden. Nun, das Problem mit Ihrem Beispiel ist, dass die Operation GetData eine gewöhnliche synchrone Methode ist, so dass Sie sie nicht mit let! aufrufen können.

Wenn Sie im typischen F # -Szenario das GetData -Member asynchron machen möchten, müssen Sie es mithilfe eines asynchronen Workflows implementieren. Daher müssen Sie es auch in den Block async einbinden. Irgendwann werden Sie einen Speicherort erreichen, an dem Sie wirklich eine primitive Operation asynchron ausführen müssen (z. B. Herunterladen von Daten von einer Website). F # stellt mehrere primitive asynchrone Operationen bereit, die Sie mit async wie let! (eine asynchrone Version von AsyncGetResponse method) aus GetResponse block aufrufen können. In Ihrer GetData -Methode schreiben Sie zum Beispiel so etwas:

%Vor%

Die Zusammenfassung besteht darin, dass Sie einige primitive asynchrone Vorgänge identifizieren müssen (z. B. Warten auf den Webserver oder das Dateisystem), primitive asynchrone Operationen an diesem Punkt verwenden und den gesamten Code, der diese Operationen verwendet, in async umbrechen. Blöcke. Wenn es keine primitiven Operationen gibt, die asynchron ausgeführt werden können, ist Ihr Code CPU-gebunden und Sie können einfach Parallel.map verwenden.

Ich hoffe, dies hilft Ihnen zu verstehen, wie asynchrone F # -Arbeitsabläufe funktionieren. Weitere Informationen finden Sie beispielsweise in Don Syme Blog-Post , Serie über asynchrone Programmierung von Robert Pickering oder meine < a href="http://tomasp.net/articles/fsharp-webcast-async.aspx"> F # -Webcast .

    
Tomas Petricek 19.03.2010, 15:09
quelle
5

@Tomas hat bereits eine gute Antwort. Ich werde nur ein paar Bits dazu sagen.

Das Idiom für F # asyncs besteht darin, die Methode mit einem "Async" -Präfix zu benennen ( AsyncFoo , nicht FooAsync ; Letzteres ist ein Idiom, das bereits von einer anderen .NET-Technologie verwendet wird). Ihre Funktionen sollten also getStockData und asyncGetStockData sein.

Wenn Sie in einem asynchronen Workflow let! anstelle von let oder do! anstelle von do verwenden, sollte die rechte Seite den Typ Async<T> anstelle von T enthalten. Grundsätzlich benötigen Sie eine vorhandene Async-Berechnung, um an dieser Stelle im Workflow "async" zu gehen. Jedes Async<T> ist entweder ein anderer async{...} Workflow oder ein asynchrones "primitives". Die Grundelemente werden in der F # -Bibliothek definiert oder im Benutzercode über Async.FromBeginEnd oder Async.FromContinuations erstellt, wodurch die Details der unteren Ebene zum Starten einer Berechnung, Registrieren eines I / O-Callbacks, Freigeben des Threads und erneutes Starten der Berechnung definiert werden können wenn man zurückgerufen wird. Also müssen Sie async den ganzen Weg bis zu einem echten asynchronen I / O-Primitiv "lotsen", um die Vorteile asynchroner I / O voll ausschöpfen zu können.

    
Brian 19.03.2010 15:34
quelle

Tags und Links