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.
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.
Dann sollten Sie ungefähr
angeben %Vor%hoffentlich ...
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
:
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.
Tags und Links haskell