Die Stream-API wurde entwickelt, um es einfach zu machen, Berechnungen in einer Weise zu schreiben, die von der Ausführung abstrahiert war, wodurch das Wechseln zwischen sequentiell und parallel einfach wurde.
Aber nur weil es einfach ist, bedeutet das nicht immer, dass es eine gute Idee ist. Tatsächlich ist es eine schlechte Idee, einfach überall .parallel()
einzufügen, nur weil man es kann.
Zunächst einmal bietet Parallelismus keine Vorteile außer der Möglichkeit einer schnelleren Ausführung, wenn mehr Kerne verfügbar sind. Eine parallele Ausführung wird immer mehr Arbeit erfordern als eine sequentielle, denn zusätzlich zur Lösung des Problems muss sie auch die Aufteilung und Koordination von Teilaufgaben durchführen. Die Hoffnung besteht darin, dass Sie schneller zur Antwort gelangen, indem Sie die Arbeit auf mehrere Prozessoren aufteilen; ob dies tatsächlich geschieht, hängt von vielen Dingen ab, einschließlich der Größe Ihres Datensatzes, wie viel Berechnung Sie für jedes Element durchführen, der Art der Berechnung (genauer gesagt, interagiert die Verarbeitung eines Elements mit der Verarbeitung anderer?), der Anzahl der verfügbaren Prozessoren und der Anzahl anderer Aufgaben, die um diese Prozessoren konkurrieren.
Es sei auch darauf hingewiesen, dass Parallelismus oft auch Nichtdeterminismus in der Berechnung sichtbar macht, der von sequentiellen Implementierungen oft verborgen wird; manchmal spielt dies keine Rolle, oder es kann durch Beschränkung der beteiligten Operationen abgemildert werden (d. h., Reduktionsoperatoren müssen zustandslos und assoziativ sein).
In Wirklichkeit wird Parallelismus manchmal Ihre Berechnung beschleunigen, manchmal nicht und manchmal sie sogar verlangsamen. Am besten ist es, zuerst mit sequentieller Ausführung zu entwickeln und dann den Parallelismus anzuwenden, wenn
(A) Sie wissen, dass tatsächlich ein Nutzen für eine gesteigerte Leistung besteht und
(B) dass dies tatsächlich zu einer gesteigerten Leistung führen wird.
(A) ist ein Geschäftsproblem, kein technisches. Wenn Sie ein Performance-Experte sind, sollten Sie in der Regel in der Lage sein, den Code zu betrachten und (B) zu bestimmen, aber der kluge Weg ist es zu messen. (Und verschwenden Sie nicht einmal Ihre Zeit, bis Sie von (A) überzeugt sind; wenn der Code schnell genug ist, ist es besser, Ihre Gehirnzellen anderswo einzusetzen.)
Das einfachste Performance-Modell für Parallelismus ist das "NQ"-Modell, bei dem N
die Anzahl der Elemente und Q
die Berechnung pro Element ist. Im Allgemeinen müssen Sie das Produkt NQ überschreiten, bevor Sie einen Leistungsbeitrag erhalten. Bei einem Problem mit niedrigem Q wie "Summieren von Zahlen von 1
bis N
" sehen Sie in der Regel einen Breakeven zwischen N=1000
und N=10000
. Bei Problemen mit höherem Q sehen Sie Breakevens bei niedrigeren Schwellenwerten.
Aber die Realität ist ziemlich kompliziert. Also, bis Sie Expertise erlangen, identifizieren Sie zuerst, wann die sequentielle Verarbeitung tatsächlich etwas kostet, und messen dann, ob Parallelismus hilfreich sein wird.