Verständnis von Eval Monads 'rpar'

8

Betrachten wir das folgende Beispiel aus Parallele und gleichzeitige Programmierung in Haskell :

%Vor%

Das Buch zeigt seine Zusammenstellung:

%Vor%

Und dann den obigen Test ausführen:

%Vor%

Wenn ich richtig verstehe, führt die Eval-Monade (mit rpar ) dazu, dass sowohl fib 36 als auch fib 35 parallel berechnet werden.

Erfolgt die tatsächliche Arbeit, d. h. die Berechnung der Funktion fib ... beim Aufruf von (runEval test) ? Oder vielleicht ist evaluate ... erforderlich? Oder, schließlich, wird es berechnet, wenn print r aufgerufen wird, um es vollständig auszuwerten?

Es ist mir nicht klar wenn die eigentliche Arbeit für rpar ausgeführt wird.

    
Kevin Meredith 18.06.2015, 12:58
quelle

1 Antwort

4

Hier ist meine Vermutung, aber ich kann das nicht auf meinem Laptop reproduzieren, zu viele Importe würde ich von Kabalen bekommen müssen.

%Vor%

Dabei feuern Sie die Auswertung von (fib 36) und (fib 35) parallel ab, aber Sie warten nicht auf sie - Sie geben sofort (x,y) zurück, während x und y noch ausgewertet werden. Wenn Sie dann zu print r gelangen, müssen Sie warten, bis x und y die Auswertung abgeschlossen haben.

Theoretisch sollte der folgende Code test1 warten, bis x und y die Auswertung abgeschlossen haben, bevor sie zurückgegeben werden.

%Vor%

Dann sollten Sie ungefähr

angeben %Vor%

hoffentlich ...

BEARBEITEN

Endlich komme ich wieder zu meinem Rechner, repliziere den Zustand und mein vorgeschlagener Code gibt das erwartete Ergebnis. Das OP wirft jedoch eine weitere gute Frage auf: Wenn evaluate nur den WHNF auswertet, warum wird dann sogar gearbeitet, bevor der Druck aufgerufen wird?

Die Antwort ist in der Monadedefinition von Control.Parallel.Strategies - mit anderen Worten, es ist nicht evaluate , das die Auswertung von x und y , sondern runEval schiebt. Die Eval -Monade ist streng im ersten Argument: in x >>= f wird x ausgewertet (siehe diese Frage bevor Sie fortfahren). Dann ergibt die Entzuckerung von test1 :

%Vor%

Dann, da rpar nur die Auswertung "funkt", verwendet es par (beginnt mit der Auswertung des ersten Arguments, gibt aber sofort die zweite zurück) und gibt sofort Done zurück, jedoch rseq (wie seq , aber streng nur im ersten Argument) gibt Done nicht zurück, bis das Argument tatsächlich ausgewertet wurde (nach WHNF). Ohne die Aufrufe rseq wissen Sie also, dass x und y begonnen haben, ausgewertet zu werden, aber keine Gewissheit, dass sie beendet wurden, aber mit diesen Aufrufen wissen Sie, dass auch x und y ebenfalls sind ausgewertet, bevor return für sie aufgerufen wird.

    
Alec 18.06.2015 16:03
quelle

Tags und Links