Was ist der Unterschied zwischen diesen beiden?
[EIN]
#pragma omp parallel
{
#pragma omp for
for(int i = 1; i < 100; ++i)
{
...
}
}
[B]
#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
...
}
Was ist der Unterschied zwischen diesen beiden?
[EIN]
#pragma omp parallel
{
#pragma omp for
for(int i = 1; i < 100; ++i)
{
...
}
}
[B]
#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
...
}
Antworten:
Ich glaube nicht, dass es einen Unterschied gibt, einer ist eine Abkürzung für den anderen. Obwohl Ihre genaue Implementierung möglicherweise anders damit umgeht.
Die kombinierten parallelen Worksharing-Konstrukte sind eine Verknüpfung zum Angeben eines parallelen Konstrukts, das ein Worksharing-Konstrukt und keine anderen Anweisungen enthält. Zulässige Klauseln sind die Vereinigung der Klauseln, die für die Parallel- und Worksharing-Konstruktionen zulässig sind.
Entnommen aus http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf
Die Spezifikationen für OpenMP finden Sie hier:
Diese sind gleichwertig.
#pragma omp parallel
erzeugt eine Gruppe von Threads, während #pragma omp for
Schleifeniterationen zwischen den erzeugten Threads aufgeteilt werden. Mit der fusionierten #pragma omp parallel for
Direktive können Sie beide Dinge gleichzeitig tun .
#pragma omp parallel for
Direktive verwende. Es sollte einen Unterschied geben.
Hier ist ein Beispiel für die Verwendung von getrennt parallel
und for
hier . Kurz gesagt, es kann für die dynamische Zuweisung von OpenMP-Thread-Private-Arrays verwendet werden, bevor der for
Zyklus in mehreren Threads ausgeführt wird. Es ist unmöglich, die gleiche Initialisierung für den parallel for
Fall durchzuführen .
UPD: Im Fragenbeispiel gibt es keinen Unterschied zwischen einem einzelnen Pragma und zwei Pragmas. In der Praxis können Sie jedoch mit getrennten parallelen und für Direktiven ein Thread-bewussteres Verhalten erzielen. Ein Code zum Beispiel:
#pragma omp parallel
{
double *data = (double*)malloc(...); // this data is thread private
#pragma omp for
for(1...100) // first parallelized cycle
{
}
#pragma omp single
{} // make some single thread processing
#pragma omp for // second parallelized cycle
for(1...100)
{
}
#pragma omp single
{} // make some single thread processing again
free(data); // free thread private data
}
Obwohl beide Versionen des spezifischen Beispiels gleichwertig sind, wie bereits in den anderen Antworten erwähnt, gibt es immer noch einen kleinen Unterschied zwischen ihnen. Die erste Version enthält eine unnötige implizite Barriere, die am Ende des "omp for" auftritt. Die andere implizite Barriere befindet sich am Ende des Parallelbereichs. Durch Hinzufügen von "nowait" zu "omp for" würden die beiden Codes zumindest aus OpenMP-Sicht gleichwertig. Ich erwähne dies, weil ein OpenMP-Compiler für beide Fälle leicht unterschiedlichen Code generieren könnte.
Ich sehe ganz andere Laufzeiten, wenn ich in g ++ 4.7.0 eine for-Schleife nehme und benutze
std::vector<double> x;
std::vector<double> y;
std::vector<double> prod;
for (int i = 0; i < 5000000; i++)
{
double r1 = ((double)rand() / double(RAND_MAX)) * 5;
double r2 = ((double)rand() / double(RAND_MAX)) * 5;
x.push_back(r1);
y.push_back(r2);
}
int sz = x.size();
#pragma omp parallel for
for (int i = 0; i< sz; i++)
prod[i] = x[i] * y[i];
Der Seriencode (nein openmp
) läuft in 79 ms. Der Code "Parallel für" läuft in 29 ms. Wenn ich das weglasse for
und benutze #pragma omp parallel
, schießt die Laufzeit bis zu 179 ms, was langsamer als der Seriencode ist. (Die Maschine hat eine Hardware-Parallelität von 8)
Der Code verlinkt auf libgomp
#pragma omp for
keine Multithread-gemeinsame Nutzung der Schleife gibt. Aber das war sowieso nicht der Fall der OPs. Versuchen Sie es erneut mit einem zusätzlichen im #pragma omp for
Inneren #pragm omp parallel
und es sollte ähnlich (wenn nicht gleich) wie die #pragma omp parallel for
Version laufen .
Es gibt offensichtlich viele Antworten, aber diese beantwortet es sehr gut (mit Quelle)
#pragma omp for
delegiert nur Teile der Schleife für verschiedene Threads im aktuellen Team. Ein Team ist die Gruppe von Threads, die das Programm ausführen. Zu Beginn des Programms besteht das Team nur aus einem einzigen Mitglied: dem Master-Thread , der das Programm ausführt.Um ein neues Thread-Team zu erstellen, müssen Sie das parallele Schlüsselwort angeben. Es kann im umgebenden Kontext angegeben werden:
#pragma omp parallel { #pragma omp for for(int n = 0; n < 10; ++n) printf(" %d", n); }
und:
Was sind: parallel, für und ein Team
Der Unterschied zwischen parallel, parallel für und für ist wie folgt:
Ein Team ist die Gruppe von Threads, die derzeit ausgeführt werden. Zu Beginn des Programms besteht das Team aus einem einzigen Thread. Ein paralleles Konstrukt teilt den aktuellen Thread für die Dauer des nächsten Blocks / der nächsten Anweisung in ein neues Thread-Team auf. Danach wird das Team wieder zu einem zusammengeführt. for teilt die Arbeit der for-Schleife auf die Threads des aktuellen Teams auf.
Es werden keine Threads erstellt, sondern nur die Arbeit auf die Threads des aktuell ausgeführten Teams aufgeteilt. parallel für ist eine Abkürzung für zwei Befehle gleichzeitig: parallel und für. Parallel erstellt ein neues Team und teilt dieses Team auf, um verschiedene Teile der Schleife zu verarbeiten. Wenn Ihr Programm niemals ein paralleles Konstrukt enthält, gibt es nie mehr als einen Thread. Der Master-Thread, der das Programm startet und ausführt, wie in Nicht-Threading-Programmen.
schedule(static, chunk)
Klausel in der Direktive verwende, tritt ein Problem auf. Der Code läuft gut, aber wenn ich diesen Code von einem MPI-Programm aus aufrufe, läuft er in eine Endlosschleife. Der Schleifenzähler ist in allen Iterationen dieser Schleife Null. Ich habe den Schleifenzähler in der#pragma omp parallel
Direktive als privat definiert . Keine Ahnung, warum es nur fehlschlägt, wenn MPI den Code aufruft. Ich bin mir ziemlich sicher, dass jeder MPI-Prozess auf einem anderen Prozessor des Clusters ausgeführt wird, wenn dies wichtig ist. Keine Ahnung, ob der Zeitplan das Problem verursacht.