2016-07-24 24 views
3

Wenn Wert x in einer Liste ist, wo x ist eine Funktion und parList auf dieser Liste aufgerufen wird (z [l,x,l,x]) tut x einmal bekommen berechnet oder zweimal?Haskell lazy evaluation in Parallelität

Von meinem Verständnis von Haskells Lazy Evaluation, einmal x ausgewertet wurde, muss es nicht erneut ausgewertet werden, da es den gleichen Wert zurückgeben würde. Aber würde dies in einer Multithread-Umgebung gelten?

Antwort

6

Wenn erstellen Sie einen Funken für eine Berechnung (das ist, was parList der Fall ist) gibt es immer eine Möglichkeit ist , dass die Arbeit für diese Berechnung wird zweimal durchgeführt werden. In der Praxis passiert das selten. Grundsätzlich gibt es eine Wettlaufsituation zwischen den Threads, die die Funken und den Hauptfaden verarbeiten.

Haskell implementiert Trägheit, indem man zunächst den Wert eines variablen Einstellung mit einer Thunk - im Wesentlichen einen Zeiger auf Code den Wert zu berechnen. Wenn der Wert der Variablen angefordert wird, führt Haskell den Code durch den Thunk und ersetzt den Thunk mit dem zurückgegebenen Wert. Wenn die Variable später verwendet wird, verwendet Haskell nur den gespeicherten Wert.

Wenn Sie eine Variable parallel auswerten, wird ein Funke erstellt, der auf die Variable zeigt. Wenn der Funke von einem Hintergrund-Thread verarbeitet wird, fordert er nur den Wert an, auf den der Funke zeigt. Wenn der Funke auf einen Thunk zeigt, wird der Thunk ausgeführt und mit dem zurückgegebenen Wert aktualisiert. Wenn der Funke auf einen bereits ausgewerteten Wert zeigt, passiert nichts und wir sagen, dass der Funke verpufft.

Wenn Sie also eine Liste wie [x,x,x,x,x,x] parallel auswerten, einen Funken wird für jedes Element der Liste erstellt werden, und es ist möglich, dass zwei oder mehrere dieser Funken zur gleichen Zeit ausgeführt werden. Es ist auch möglich, dass der Haupt-Thread x gleichzeitig auswertet. In diesem Fall wird die Arbeit zur Berechnung x dupliziert. Sobald jedoch der Thunk für x aktualisiert wurde, wird kein Auswertungen von x, beginnend danach, x neu berechnet.

+0

Prost, ich habe noch eine weitere Frage. Bedenke, dass wir 2 lange Funken haben. Stellen Sie sich vor, der erste Funke greift auf und berechnet "x", kehrt aber nicht zurück. Währenddessen folgt parallel, aber nach dieser Berechnung der zweite Funkenzugriff "x". Erhält dieser Funke den Wert von x aus der Berechnung des ersten Funkens oder berechnet er selbst? –

+0

Wenn eine Berechnung den Wert von 'x' benötigt und' x' momentan ein Thunk ist, wird die Arbeit ausgeführt, um 'x' zu berechnen, update' x' mit dem berechneten Wert (so ist 'x' kein Thunk mehr) und weitermachen. – ErikR

+0

Ja, danke dafür, aber meine Frage betrifft die Interaktion von faulen Bewertungen und Funken. Ich versuche zu verstehen, ob ein ausgewerteter Thunk von einem Funken für einen anderen Funken verfügbar ist, der gestartet wurde, bevor der Thunk ausgewertet wurde. Nehmen wir an, ich habe zwei Funken S1 und S2, die gegenwärtig parallel laufen, und beide wurden zum Zeitpunkt t0 einen Thunk an x ​​übergeben. Zum Zeitpunkt t1, einige Zeit nachdem S1 und S2 begonnen haben, greift S1 auf x zu und bewertet somit den Thunk.Nehmen wir an, dass die Thunk-Auswertung zum Zeitpunkt t2 abgeschlossen ist. Zum Zeitpunkt t3 (wo t3> t2 ist) greift der Funke S2 ​​auf x zu. –