Ich versuche Clojure-Futures zu verstehen, und ich habe Beispiele aus den gängigen Clojure-Büchern gesehen, und es gibt Beispiele, in denen Futures für parallele Berechnungen verwendet werden (was sinnvoll erscheint).Clojure-Futures verstehen
Ich hoffe jedoch, dass jemand das Verhalten eines einfachen Beispiels erklären kann, das aus O'Reillys Programmier-Clojure-Buch stammt.
(def long-calculation (future (apply + (range 1e8))))
Wenn ich versuche, dies zu dereferenzieren, von
tun(time @long-calculation)
Es gibt das richtige Ergebnis (4999999950000000), aber fast sofort (in 0.045 msec) auf meinem Rechner.
Aber wenn ich die eigentliche Funktion aufrufen, wie so
(time (apply + (range 1e8)))
bekomme ich das auch richtige Ergebnis, aber die benötigte Zeit ist viel größer (~ 5000 msec).
Wenn ich die Zukunft dereferenziere, ist mein Verständnis, dass ein neuer Thread erstellt wird, auf dem der Ausdruck ausgewertet wird - in diesem Fall würde ich erwarten, dass es auch etwa 5000 ms dauert.
Wie kommt die dereferenzierte Zukunft so schnell zum richtigen Ergebnis?
Gibt es ein Nachteil, eine große Anzahl von Futures zu verwenden? Ich habe einen Code geschrieben, der an mehreren Stellen numerisch intensive Berechnungen durchführt. Anstatt native Java-Arrays zu verwenden oder Hinting zu schreiben, kann ich stattdessen idiomatischen funktionalen Code und 'future' die Ergebnisse dieser Berechnungen schreiben? – endbegin
Futures sind ziemlich leicht, haben aber etwas Overhead, so dass ich sie für extrem kleine Berechnungen vermeiden würde. Wenn Sie Berechnungen parallel durchführen möchten, sollten Sie 'pmap' verwenden - eine gleichzeitige Version von' map', die Futures unter der Haube verwendet. Wenn Ihr Code wirklich numerisch intensiv ist, verwenden Sie wahrscheinlich am besten beide Java-Arrays * und * pmap/futures, wenn Sie das Beste aus Ihrer CPU-Zeit herausholen wollen. – mikera
Ich habe versucht, mit pmap zu spielen, aber habe es nur nützlich gefunden, wenn die Datengröße "groß" ist (wie groß ist natürlich etwas subjektiv). Ich habe Clojure gelernt, indem ich einige einfache digitale Signalverarbeitungsfunktionen implementiert habe, und es gibt einen spürbaren Geschwindigkeitsvorteil bei der Verwendung von nativen Java-Arrays gegenüber einem funktionalen Stil mit der seq-Abstraktion im Einzelprozessor/Thread-Modus. Wenn ich Futures verwende, ist die Beschleunigung so immens, dass es wirklich keine Rolle spielt, ob ich nativen oder funktionalen Code verwende. Fühlt sich an, als würde ich etwas Offensichtliches vermissen. – endbegin