2 Stimmen

Was passiert in OpenMP, wenn es ein pragma for innerhalb eines pragma for gibt?

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?

3voto

Mysticial Punkte 451718

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.

1voto

Massimiliano Punkte 7432

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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X