Enttäuschende Leistung mit Parallel.For
Ich versuche meine Rechenzeiten mit zu beschleunigenParallel.For
. Ich habe eine Intel Core i7 Q840-CPU mit 8 Kernen, aber ich schaffe es nur, ein Leistungsverhältnis von 4 im Vergleich zu einer sequentiellen zu bekommenfor
Schleife. Ist das so gut wie es nur geht?Parallel.For
, oder kann der Methodenaufruf optimiert werden, um die Leistung zu steigern?
Hier ist mein Testcode, sequentiell:
var loops = 200;
var perloop = 10000000;
var sum = 0.0;
for (var k = 0; k < loops; ++k)
{
var sumk = 0.0;
for (var i = 0; i < perloop; ++i) sumk += (1.0 / i) * i;
sum += sumk;
}
und parallel:
sum = 0.0;
Parallel.For(0, loops,
k =>
{
var sumk = 0.0;
for (var i = 0; i < perloop; ++i) sumk += (1.0 / i) * i;
sum += sumk;
});
Die Schleife, die ich parallelisiere, beinhaltet die Berechnung mit einer "global" definierten Variablen,sum
Dies sollte jedoch nur einen winzigen Bruchteil der Gesamtzeit innerhalb der parallelisierten Schleife ausmachen.
In Release Build ("Code optimieren" -Flag setzen) die sequentiellefor
Schleife dauert 33,7 s auf meinem Computer, während dieParallel.For
Schleife dauert 8,4 s, ein Leistungsverhältnis von nur 4,0.
Im Task-Manager kann ich sehen, dass die CPU-Auslastung bei der sequentiellen Berechnung 10 bis 11% beträgt, während sie bei der parallelen Berechnung nur 70% beträgt. Ich habe versucht, explizit festzulegen
ParallelOptions.MaxDegreesOfParallelism = Environment.ProcessorCount
aber ohne Erfolg. Mir ist nicht klar, warum nicht die gesamte CPU-Leistung dem zugewiesen wirdparallel Berechnung?
Mir ist aufgefallen, dass zu SO eine ähnliche Frage aufgeworfen wurdeVormit einem noch enttäuschenderen Ergebnis. Diese Frage beinhaltete jedoch auch eine minderwertige Parallelisierung in einer Drittanbieter-Bibliothek. Mein Hauptanliegen ist die Parallelisierung grundlegender Operationen in den Kernbibliotheken.
AKTUALISIEREN
In einigen Kommentaren wurde ich darauf hingewiesen, dass die von mir verwendete CPU nur 4 physische Kerne hat, was für das System als 8 Kerne sichtbar ist, wenn Hyper-Threading aktiviert ist. Aus diesem Grund habe ich Hyper-Threading deaktiviert und ein neues Benchmarking durchgeführt.
Mit Hyper-ThreadingdeaktiviertMeine Berechnungen sind jetztschneller, sowohl die parallele als auch die (was ich dachte) sequentiellefor
Schleife. CPU-Auslastung während derfor
Schleife ist bis zu ca. 45% (!!!) und 100% während derParallel.For
Schleife.
Rechenzeit für diefor
Schleife 15,6 s (mehr als doppelt so schnell wie mit Hyper-Threadingaktiviert) und 6,2 s fürParallel.For
(25% besser als bei Hyperthreadingaktiviert). Leistungsverhältnis mitParallel.For
ist jetzt nur2.5Läuft auf 4 echten Kernen.
Das Leistungsverhältnis ist also immer noch erheblich niedriger als erwartet, obwohl das Hyper-Threading deaktiviert ist. Auf der anderen Seite ist es faszinierend, dass die CPU-Auslastung während der Laufzeit so hoch istfor
Schleife? Könnte es auch in dieser Schleife eine Art interne Parallelisierung geben?