Also testen wir parallele Streams und bisher bringen sie überhaupt keine Leistungssteigerung auf einem 8-Kern-Rechner.
Optional ret = Arrays.stream( a ).parallel()
.mapToObj( source -> { some very heavy number crunching } )
.min( Comparator.comparing( s -> s.valueDelta ) );
Das Array a hat die Länge 4 und enthält die Zahl 0...3.
Ich kann „.peek()“ verwenden und den Thread ausdrucken und stellen Sie sicher, dass 4 laufende Threads verwendet werden.
Die Laufzeit ist etwas langsamer als das Ersetzen des Streams durch eine sequentielle for-Schleife, die über a iteriert.
Die Zahlenverarbeitung hat kein IO, keine Interaktion oder Synchronisierung und keinen Zugriff Nur schreibgeschützte Datenstruktur zur Bestimmung von a bester Wert „Swap“.
Nur als Experiment habe ich meine Zahlenverarbeitung durch einen Schlaf (2000) ersetzt und das Ganze wurde nach 2039 ms beendet, sodass es scheinbar parallel läuft. Aber die Zahlenverarbeitung wird überhaupt nicht schneller.
Wenn man den Prozess-Explorer und den Ressourcenmonitor unter Windows betrachtet, scheint es, als würde nur ein Kern verwendet.
Also habe ich versucht, es unter Linux auszuführen und habe keine besseren Ergebnisse erzielt.
Aus irgendeinem Grund nutzt JVM die verfügbaren Kerne mit seinem Threading nicht richtig aus.
Wir können dies auf mehreren Computern, Windows und Linux reproduzieren und niemand hat jemals Geschwindigkeit erreicht up.
Als Alternative habe ich es auch mit einem festen Threadpool mit Größe 4 implementiert und auch hier keinerlei Beschleunigung, während 4 Threads laufen (ich drucke aus dem Tread heraus). Debuggen, um zu sehen, ob ich einen anderen Thread habe, der etwas parallel druckt).
Irgendeine Idee?
BEARBEITEN Aktualisierungen nach einigen weiteren Tests:
Nach gründlichen Tests habe ich weitere Erkenntnisse:
Sie können es reproduzieren, indem Sie Folgendes tun: „Zahlenzerkleinerung“. Ich habe 4 Array-Listen verwendet, die ich gemischt und sortiert habe (dies ist ein Analogon zu meinem Code, da ich einige andere Listentypen verwendet habe).
Optional ret = Arrays.stream( arrayOfLists ).parallel()
.mapToObj( list-> {
Collections.shuffle( list );
list.sort( comparator );
return list.get(0);
} )
.min();
Wenn nun das Mischen und Sortieren einer Liste weniger als, sagen wir, 30 Sekunden dauert, sehe ich keine Verbesserung durch die Parallisierung. Unabhängig davon, ob ich parallelisiere, dauert es im Grunde genommen 2 Minuten, bis sie fertig sind.
Aber wenn ich die Listen lang genug mache, sagen wir 1.000.000 Elemente, dann sehe ich eine gewisse Geschwindigkeitssteigerung. Wenn ich mich recht erinnere, dauern die vier Listen nacheinander etwa 7 Minuten und mit 4 Threads oder parallelen Streams etwa 5 (auch unter Verwendung von 4 Threads, wie ich überprüft habe).
Lassen Sie sich nicht die genauen Zeitzahlen nennen ... war etwas in der Nähe.
Der Grund dafür scheint nun zu sein, dass das Betriebssystem (Windows und Linux) die Arbeitslast nicht für hoch genug hält, um die Threads auf verschiedene Kerne zu verschieben, was verrückt ist .
Wenn ich keine Listen habe, die so groß sind, dass sie fast eine Minute dauern, wird die gesamte Arbeit nur von einem Kern erledigt, während der Rest meiner 8-Kern-CPU schläft.
In meinem ursprünglichen Problem habe ich nun einen Graphen für minimale Kreuzungskanten (mehrere Partitionen) unter Verwendung einer Ableitung von Lin-Kernighan partitioniert.
Die Auswertung aller möglichen Bewegungen kann leicht in disjunkte Operationen pro Startpartition des Swaps aufgeteilt werden .
Also wollte ich das parellisieren. Aber weil diese Arbeit insgesamt (in meinem Fall (4 Partitionen) etwa 1,5 Sekunden dauert), weigert sich das Betriebssystem, meine JVM-Threads zu parellisieren, und am Ende habe ich eine Geschwindigkeitssteigerung von 0.
Und das ist völlig verrückt, weil der gesamte Algorithmus auf etwa 18.000 Knoten läuft und insgesamt etwa 5 bis 10 Minuten dauert.
Vor fast 20 Jahren wurden Betriebssysteme intelligenter geplant. Ich habe meine Masterarbeit über realistische Leistungsvorhersagen paralleler Algorithmen geschrieben und man konnte damals nahezu lineare Beschleunigungen für unabhängige Probleme SEHR kleiner Größen erzielen.
Die Frage ist jetzt:
Sind Machen die OS-Scheduler diesen Unsinn nur mit Java-VMs oder ist das jetzt eine allgemeine Regression bei der Planung?
Kann ich etwas dagegen tun? Führen Sie sie parallel aus.
Die parallele JVM-Verarbeitung mit Streams oder Threadpools funktioniert nicht wirklich ⇐ Java
-
- Similar Topics
- Replies
- Views
- Last post