Ein Muster, auf das ich jetzt schon mehrmals gestoßen bin, ist eines, bei dem eine Liste von Werten überprüft werden muss, indem ein Test darüber abgebildet wird und geprüft wird, ob einige oder alle Elemente bestanden wurden. Die typische Lösung besteht darin, nur die praktischen Einbauten all
und zu verwenden any
.
Das Problem ist, dass diese seriell ausgewertet werden. In vielen Fällen wäre es viel schneller, parallel zum Abschluss des Prozesses zu bewerten, sobald ein Thread ein "False" für all
oder ein "True" für findet any
. Ich bin mir ziemlich sicher, dass das Kurzschlussverhalten mit Control.Parallel nicht implementiert werden kann, da es eine prozessübergreifende Kommunikation erfordert und ich Control.Concurrent noch nicht annähernd genug verstehe, um dies zu implementieren.
Es ist ein ziemlich verbreitetes Muster in der Mathematik (z. B. Miller-Rabin-Primalität), daher habe ich das Gefühl, dass jemand wahrscheinlich bereits eine Lösung dafür gefunden hat, aber aus offensichtlichen Gründen eine Google-Suche nach "parallel oder / und / any / all on list" durchführt haskell "gibt nicht viele relevante Ergebnisse zurück.
quelle
unamb
Bibliothek möglichpthreads
in C oder grüne Threads in Haskell). Sie starten nicht mehrere Webserver, um gleichzeitige Webanforderungen zu verarbeiten, sondern führen mehrere Threads in einem einzigen Prozess aus! Gleiches gilt für die Parallelität. Sie drehen so viele Threads hoch, wie Sie CPUs haben, und teilen Ihre Arbeit gleichmäßig auf, wodurch Sie sich um CPU-gebundene Aufgaben kümmern. Versuchen Sie, diese Bibliothek selbst zu überzeugen github.com/lehins/haskell-schedulerAntworten:
In vielen realistischen Programmen können Sie zu diesem Zweck parallele Strategien verwenden. Dies liegt daran, dass, obwohl es keinen expliziten Mechanismus zum Abbrechen nicht benötigter Berechnungen gibt, dies implizit geschieht, wenn der Garbage Collector ausgeführt wird. Betrachten Sie als konkretes Beispiel das folgende Programm:
Dies verwendet eine parallele Listenstrategie, um
waldo = 0
in der Ausgabe von 100 PRNG-Streams mit jeweils 40 Millionen Nummern zu suchen (was niemals gefunden wird). Kompilieren und ausführen:und es fixiert vier Kerne für ungefähr 16s und druckt schließlich
False
. Beachten Sie in der Statistik, dass alle 100 Funken "konvertiert" werden und somit vollständig ausgeführt werden:Wechseln Sie jetzt
waldo
zu einem Wert, der früh gefunden werden kann:und ändern Sie
main
, um den Thread 10 Sekunden lang am Leben zu halten:Sie werden feststellen, dass es
True
fast sofort gedruckt wird , aber 4 Kerne (zumindest für eine kurze Zeit) an 100% CPU gebunden bleiben. Dies zeigt, dass nicht benötigte Berechnungen weiterhin ausgeführt werden und nicht kurzgeschlossen werden, wie Sie vielleicht befürchtet haben.ABER die Dinge ändern sich, wenn Sie eine Speicherbereinigung erzwingen, nachdem Sie die Antwort erhalten haben:
Jetzt werden Sie sehen, dass die CPU kurz nach dem Drucken in den Leerlauf fällt
True
, und die Statistiken zeigen, dass die meisten Berechnungen vor dem Ausführen durch Müll gesammelt wurden:In realistischen Programmen wird kein explizites Programm
performGC
benötigt, da GCs selbstverständlich regelmäßig durchgeführt werden. Einige unnötige Berechnungen werden weiterhin ausgeführt, nachdem die Antwort gefunden wurde. In vielen realistischen Szenarien ist der Anteil unnötiger Berechnungen jedoch kein besonders wichtiger Faktor.Insbesondere wenn die Liste groß ist und jeder einzelne Test eines Listenelements schnell ist, weisen parallele Strategien eine hervorragende Leistung in der Praxis auf und lassen sich leicht in den Handel umsetzen.
quelle