2016-02-13 7 views
5

Ich habe folgendes Programm C++ Programm, das keine Kommunikation verwendet, und die gleiche identische Arbeit auf allen Kernen getan, ich weiß, dass dies nicht ein parallele Verarbeitung überhaupt nicht verwenden:Kosten OpenMPI in C++

unsigned n = 130000000; 
std::vector<double>vec1(n,1.0); 
std::vector<double>vec2(n,1.0); 
double precision :: t1,t2,dt; 
t1 = MPI_Wtime(); 
for (unsigned i = 0; i < n; i++) 
{ 
    // Do something so it's not a trivial loop 
    vec1[i] = vec2[i]+i; 
} 
t2 = MPI_Wtime(); 
dt = t2-t1; 

Ich führe dieses Programm in einem einzigen Knoten mit zwei Intel® Xeon® Prozessor E5-2690 v3, so habe ich 24 Kerne alle zusammen. Dies ist ein dedizierter Knoten, niemand benutzt ihn. Da es keine Kommunikation gibt und jeder Prozessor die gleiche Menge an (identischer) Arbeit leistet, sollte die Ausführung auf mehreren Prozessoren die gleiche Zeit ergeben. Allerdings bekomme ich die folgenden Zeiten (gemittelt Zeit über alle Kerne):

1 Kern: 0,237

2 Kerne: 0,240

4 Kerne: 0.241

8 Cores: 0,261

16 Adern: 0,454

Was coul d verursacht die Zunahme der Zeit? Besonders für 16 Kerne. Ich habe Callgrind ran und ich bekomme die ungefähr gleiche Menge an Daten/Befehl fehlt auf allen Kernen (der Prozentsatz der Fehlschläge sind die gleichen).

Ich habe den gleichen Test auf einem Knoten mit zwei Intel® Xeon® Prozessor E5-2628L v2 wiederholt (16 Kerne alle zusammen), beobachte ich die gleiche Zunahme der Ausführungszeiten. Hat das etwas mit der MPI-Implementierung zu tun?

+0

Ich verstehe nicht ganz, was Sie tun - führen Sie eine einzelne Instanz des gleichen Programms auf jedem Kern separat? Außerdem sprichst du über Cores (24) und dann über Prozessoren - was ist das? – MikeMB

+0

Ja, ich renne, ich führe eine einzelne Instanz des gleichen Programms auf jedem Kern. Sorry über die Mischung von Wörtern, ich habe es bearbeitet. – user302157

Antwort

2

ich vermutet, dass es gemeinsame Ressourcen, die von Ihrem Programm verwendet werden sollen, so dass, wenn die Anzahl von ihnen erhöht, gibt es Verzögerungen, so dass eine Ressource free'ed wird, so dass es durch verwendet werden kann, der andere Prozess.

Sie sehen, Sie können 24 Kerne haben, aber das bedeutet nicht, dass Ihr gesamtes System es jedem Kern erlaubt, alles gleichzeitig zu machen. Wie in den Kommentaren erwähnt, ist die Speicherzugriff eine Sache, die Verzögerungen verursachen kann (aufgrund des Datenverkehrs), die gleiche Sache für die Festplatte.

Beachten Sie auch die Verbindungsnetzwerk, die auch von vielen Zugriffen leiden kann. Zusammenfassend stellen Sie fest, dass diese Hardwareverzögerungen ausreichen, um die Verarbeitungszeit zu überfordern.


Allgemeiner Hinweis: Denken Sie daran, wie Efficiency eines Programms definiert:

E = S/p, wobei S die Beschleunigung und p die Anzahl der Knoten/Prozesse/Threads ist

Jetzt Skalierbarkeit berücksichtigen. Normalerweise sind Programme schwach skalierbar, d. H. Dass Sie die Größe des Problems mit derselben Rate erhöhen müssen und p.Indem Sie nur die Anzahl von p erhöhen, während Sie die Größe Ihres Problems (n in Ihrem Fall) konstant halten, während die Effizienz konstant gehalten wird, ergibt sich ein stark skalierbares Programm.

+2

Das könnte es sein. Ich weiß nicht viel über RAM-Zugriff, aber ich weiß, dass alle Kerne den gleichen RAM teilen. Ich weiß nicht, ob der Zugriff auf diesen Speicher gleichzeitig erfolgen kann. – user302157

+0

Genau @ user302157, Sie sehen, es hat auch mit dem Verbindungsnetzwerk zu tun. ;) Scanne die Antworten und wähle eine aus, um sie zu akzeptieren (überprüfe auch mein Update). – gsamaras

+0

Danke! Ja, ich versuche tatsächlich, die Ursache für schlechte Skalierung in schwachen Skalierungstests zu ermitteln. Es gibt tatsächlich parallelen Code vor der Schleife, die verschiedene Daten in die Vektoren einfügt, abhängig vom Rang, aber ich analysiere jeden Teil einzeln und ich war verwirrt über diesen Teil, der sehr gut unter schwacher Skalierung skalieren sollte. Die Ursache für die schlechte Skalierung bei 16 Kernen liegt jedoch in Bandbreitenproblemen. Daran habe ich nicht gedacht. Danke noch einmal. – user302157

1

Ihr Programm verwendet überhaupt keine Parallelverarbeitung. Nur weil Sie es mit OpenMP kompiliert haben, machen Sie es nicht parallel.

Um beispielsweise die for-Schleife zu parallelisieren, müssen Sie das OpenMP-Angebot von # pragma verwenden.

unsigned n = 130000000; 
std::vector<double>vec1(n,1.0); 
std::vector<double>vec2(n,1.0); 
double precision :: t1,t2,dt; 
t1 = MPI_Wtime(); 

#pragma omp parallel for 
for (unsigned i = 0; i < n; i++) 
{ 
    // Do something so it's not a trivial loop 
    vec1[i] = vec2[i]+i; 
} 
t2 = MPI_Wtime(); 
dt = t2-t1; 

jedoch berücksichtigen, dass für große Werte von n, die Auswirkungen des Cache-Misses der perfomance gewonnen mit mehreren Kernen können verstecken.

+2

Ja, ich weiß, dass es keine Parallelverarbeitung gibt. Ich habe erklärt, dass es keine Kommunikation gibt und dass die gleiche identische Arbeit geleistet wird. Ich weiß also nicht, warum es einen Anstieg der Ausführungszeit gibt, selbst wenn jeder Kern genau dasselbe tut. Ich habe das Programm über Callgrind ausgeführt und es gibt die gleiche Menge an Instruktionen/Datenfehlern auf allen Kernen. – user302157

4

In Anbetracht der Tatsache, dass Sie ~ 2 GiB Speicher pro Rang verwenden, ist Ihr Code speichergebunden. Mit Ausnahme der Prefetcher arbeiten Sie nicht im Cache, sondern im Hauptspeicher. Sie treffen einfach die Speicherbandbreite bei einer bestimmten Anzahl aktiver Kerne.

Ein anderer Aspekt kann Turbo-Modus sein, wenn aktiviert. Der Turbo-Modus kann die Kernfrequenz auf höhere Werte erhöhen, wenn weniger Kerne verwendet werden. Solange die Speicherbandbreite nicht gesättigt ist, erhöht die höhere Frequenz des Turbokerns die Bandbreite, die jeder Kern erhält. This paper diskutiert die verfügbare aggregierte Speicherbandbreite auf Haswell Prozessoren in Abhängigkeit von der Anzahl der aktiven Kerne und Frequenz (Bild 7./8.)

Bitte beachten Sie, dass dies nichts mit MPI/OpenMPI zu tun hat. Sie können das gleiche Programm auch X-mal über einen anderen Mittelwert starten.

+0

Danke! Das ist es genau. Ich werde das Papier durchsehen. – user302157

+0

Ich habe die Zeitung überflogen. Schnelle Frage, weißt du, ob es mir möglich ist, die Frequenz der CPU in C++ zu ändern? Ich frage mich nur, wie sie die Häufigkeit in Abb. 7 und 8 variieren, oder brauche ich einen Administratorzugang oder eine andere Art. – user302157

+0

@ user302157, dies erfordert standardmäßig root. Es ist möglich, dies für Benutzer zu aktivieren, indem Sie Berechtigungen für '/ sys/devices/system/cpu/cpu */cpufreq/scaling_ {gouverneur, setspeed}' setzen. Sie können entweder die Dateien direkt schreiben oder 'libcpufreq' (ein bisschen langsam, weil es immer den Gouverneur verdoppelt). – Zulan