Zu Beginn des #pragma omp parallel
werden eine Reihe von Threads erstellt, und wenn wir dann zu #pragma omp for
die Arbeitslast verteilt wird. Was passiert, wenn diese for-Schleife eine for-Schleife enthält, und ich platziere eine #pragma omp for
auch davor? Erzeugt jeder Thread neue Threads? Wenn nicht, welche Threads werden mit dieser Aufgabe betraut? Was genau geschieht in dieser Situation?
Antworten
Zu viele Anzeigen?Standardmäßig werden keine Threads für die innere Schleife erzeugt. Sie wird sequentiell mit dem Thread ausgeführt, der sie erreicht.
Dies liegt daran, dass die Verschachtelung standardmäßig deaktiviert ist. Wenn Sie jedoch die Verschachtelung über omp_set_nested()
wird eine neue Gruppe von Threads gestartet.
Wenn Sie jedoch nicht vorsichtig sind, kann dies dazu führen, dass p^2
Anzahl von Threads (da jeder der ursprünglichen p
Threads wird eine weitere p
Fäden). Daher ist die Verschachtelung standardmäßig deaktiviert.
In einer Situation wie der folgenden:
#pragma omp parallel
{
#pragma omp for
for(int ii = 0; ii < n; ii++) {
/* ... */
#pragma omp for
for(int jj = 0; jj < m; jj++) {
/* ... */
}
}
}
Sie lösen damit ein undefiniertes Verhalten aus, da Sie gegen den OpenMP-Standard verstoßen. Genauer gesagt verletzen Sie die in Abschnitt 2.5 (Worksharing-Konstrukte) aufgeführten Einschränkungen:
Die folgenden Einschränkungen gelten für Konstrukte zur Arbeitsteilung:
- Jede arbeitsteilige Region muss von allen Threads in einem Team oder von keinem angetroffen werden.
- Die Reihenfolge der Arbeitsteilungsregionen und der Barriereregionen, auf die man trifft, muss für jeden Thread eines Teams gleich sein.
Dies wird in den folgenden Beispielen deutlich A.39.1c und A.40.1c :
Beispiel A.39.1c : Das folgende Beispiel für die Verschachtelung von Schleifenkonstrukten ist konform weil die inneren und äußeren Schleifenbereiche an unterschiedliche parallele Regionen binden:
void work(int i, int j) {}
void good_nesting(int n)
{
int i, j;
#pragma omp parallel default(shared)
{
#pragma omp for
for (i=0; i<n; i++) {
#pragma omp parallel shared(i, n)
{
#pragma omp for
for (j=0; j < n; j++)
work(i, j);
}
}
}
}
Beispiel A.40.1c : Das folgende Beispiel ist nicht konform weil die innere und äußere Schleifenregion eng verschachtelt sind
void work(int i, int j) {}
void wrong1(int n)
{
#pragma omp parallel default(shared)
{
int i, j;
#pragma omp for
for (i=0; i<n; i++) {
/* incorrect nesting of loop regions */
#pragma omp for
for (j=0; j<n; j++)
work(i, j);
}
}
}
Beachten Sie, dass dies ein Unterschied ist zu:
#pragma omp parallel for
for(int ii = 0; ii < n; ii++) {
/* ... */
#pragma omp parallel for
for(int jj = 0; jj < m; jj++) {
/* ... */
}
}
in dem Sie versuchen, eine verschachtelte parallele Region zu erzeugen. Nur in diesem Fall gilt die Diskussion von Mysticial Antwort.