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,sumDies 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?

Antworten auf die Frage(4)

Ihre Antwort auf die Frage