MVar, TVar, IORef, ... Ich kann ein Thunk-Problem nicht beschleunigen (denke ich).
(Mein ursprüngliches Problem ist ein threaded Code, ich mache "ForkIO" n-mal aufrufen "addMany"; aber ich denke, mein Problem ist auf "shW" -Funktion)
Lassen Sie den nächsten Code:
%Vor%dann, Profilergebnis zeigen:
%Vor%Ich kann Thunk bei "shW" -Aufrufen nicht entfernen (und die Speichernutzung ist sehr groß). Was falsch?
Ein ähnlicher C # -Code läuft viel (viel) schneller:
%Vor%Vielen Dank!
AKTUALISIEREN
Das ursprüngliche Problem wurde behoben: Ссылка
Vielen Dank Don Stewart !
Es ist sofort offensichtlich, dass es ein Leck gibt, wenn Sie auf den Heap und die GC-Zeit schauen:
%Vor%280M Residenz und 89% GC. Viele Thunks werden zugeteilt und weggeworfen.
Ein Heap-Profil macht dies offensichtlich.
Der Schlüssel ist, dass dies "stg_app *" -Dinge sind (d. h. STG-Maschinen wenden Thunks an).
Ein subtiles, aber bemerkenswertes Problem mit der modify -Familie von Funktionen ist das Problem hier - wenn Sie ein träges atomicModify haben, gibt es einfach keine Möglichkeit, das Feld strikt zu aktualisieren, ohne den Wert zu verlangen.
Bei all Ihrer sorgfältigen Verwendung von atomicModifyIORef r (\ !x' -> (x' + k, ()))
wird also eine Kette von Anwendungen der (+)
-Funktion erstellt, so dass das Ergebnis der Kette (dh der Wert in der Zelle) beobachtet wird, wobei jede Addition streng ist sein Argument. Nicht was du willst! Keine Ihrer Striktheitsannotationen für das Argument , umIREef zu ändern, hat Auswirkungen auf die Zelle selbst. Nun ist normalerweise eine Lazy Modify das, was Sie wollen - es ist nur ein Pointer-Swap, also können Sie sehr kurze atomare Abschnitte haben.
Aber manchmal ist das nicht, was Sie wollen.
(Für den Hintergrund dieses Problems siehe GHC-Ticket # 5926 , jedoch das Das Problem war zumindest 2007 bekannt, als ich das Paket strict-concurrency schrieb, um dieses Problem mit MVars zu vermeiden Es wurde im Jahr 2009 diskutiert , und wir haben jetzt strenge Versionen in 2012) .
Wenn Sie zuerst den Wert anfordern, können Sie das Problem beheben. Z.B.
%Vor% Beachten Sie, dass dieses Problem jetzt in den Bibliotheken dokumentiert , und Sie können atomicModifyIORef'
verwenden, um dies zu vermeiden.
Und wir bekommen:
%Vor%Das bedeutet eine 22-fache Beschleunigung, und die Speicherbelegung wird konstant. Zum Lachen, hier ist das neue Heap-Profil:
Tags und Links haskell memory concurrency lazy-evaluation