Sagen wir, ich habe zwei Funktionen:
%Vor%Ich möchte eine Funktion schreiben, die dem entspricht:
%Vor%Aber wenn ich das tue, wird mir bei großen Listen zwangsläufig der Speicher ausgehen.
Ein einfaches Beispiel ist das folgende:
%Vor% Ich verstehe, dass dies der Fall ist, weil die Liste x
im Speicher gespeichert wird, ohne dass sie als Garbage Collector erfasst wird. Es wäre besser, anstelle von f
und g
arbeitete an x
in, nun, "parallel".
Angenommen, ich kann f
und g
nicht ändern und auch keine separate Kopie von x
erstellen (nehme an, dass x
teuer in der Produktion ist), wie kann ich h
schreiben, ohne in out zu laufen Speicherprobleme?
Eine kurze Antwort ist, dass Sie nicht können. Da Sie keine Kontrolle über f
und g
haben, können Sie nicht garantieren, dass die Funktionen ihre Eingaben sequenziell verarbeiten. Eine solche Funktion kann auch die gesamte Liste im Speicher behalten, bevor das Endergebnis erzeugt wird.
Wenn Ihre Funktionen jedoch als Falten ausgedrückt werden, ist die Situation anders. Das bedeutet, dass wir jeden Schritt schrittweise anwenden können, sodass wir diese Schritte in einem Durchgang parallelisieren können.
Das sind viele Ressourcen zu diesem Bereich. Zum Beispiel:
Das Muster des Konsums einer Sequenz von Werten mit richtig definierten Raumgrenzen wird allgemeiner mit rohrartigen Bibliotheken wie Conduit , iteratees oder Pipes . Zum Beispiel könnten Sie in Conduit die Kombination aus Computersummen und Produkten als
ausdrücken %Vor%Wenn Sie Ihre Funktionen in Falten umwandeln können, können Sie sie einfach mit einem Scan verwenden:
%Vor% Wir verbrauchen die Eingabe in Chunks für eine bessere Leistung. Mit -O2
kompiliert, sollte dies in einem konstanten Leerzeichen ausgeführt werden. Die Zwischenergebnisse werden als Fortschrittsanzeige gedruckt.
Wenn Sie Ihre Funktion nicht in eine Faltung umwandeln können, bedeutet dies, dass die gesamte Liste konsumieren muss, um eine Ausgabe zu erzeugen, und dieser Trick trifft nicht zu.
Sie können mehrere Threads verwenden, um f x
und g x
parallel auszuwerten.
z. B.
%Vor%Es ist eine gute Möglichkeit, die parallele Laufzeit von GHC auszunutzen, um einen Platzverlust zu verhindern, indem Sie zwei Dinge gleichzeitig tun.
Alternativ müssen Sie f
und g
zu einem einzigen Pass fusionieren.
Tags und Links haskell