Что происходит в OpenMP, когда есть прагма для внутренней прагмы для? - PullRequest
2 голосов
/ 23 декабря 2011

В начале #pragma omp parallel создается куча потоков, затем, когда мы достигаем #pragma omp for, рабочая нагрузка распределяется.Что произойдет, если в этом цикле for есть цикл for, и я помещаю #pragma omp for перед ним?Каждый поток создает новые темы?Если нет, то каким потокам назначена эта задача?Что именно происходит в этой ситуации?

Ответы [ 2 ]

3 голосов
/ 25 декабря 2011

По умолчанию никакие потоки не создаются для внутреннего цикла. Это делается последовательно, используя поток, который достигает его.

Это потому, что вложение отключено по умолчанию. Однако если вы включите вложение с помощью omp_set_nested(), то будет создан новый набор потоков.

Однако, если вы не будете осторожны, это приведет к p^2 количеству потоков (поскольку каждый из исходных p потоков будет порождать другие p потоков.) Поэтому вложение по умолчанию отключено. *

1 голос
/ 08 июня 2013

В ситуации, подобной следующей:

#pragma omp parallel
{
#pragma omp for
  for(int ii = 0; ii < n; ii++) {
    /* ... */
#pragma omp for 
    for(int jj = 0; jj < m; jj++) {
      /* ... */
    }
  }
}

, что происходит, когда вы запускаете неопределенное поведение при нарушении стандарта OpenMP.Точнее, вы нарушаете ограничения, представленные в разделе 2.5 (конструкции разделения):

Следующие ограничения применяются к конструкциям разделения:

  • Каждая область разделения должна встречаться всеми потоками.в команде или вообще ни при каких обстоятельствах.
  • Последовательность встречающихся областей разделения и барьерных областей должна быть одинаковой для всех потоков в команде.

Это явнопоказано в примерах A.39.1c и A.40.1c :

Пример A.39.1c : следующий пример вложенности конструкции цикла соответствует, поскольку области внутреннего и внешнего цикла связываются с различными параллельными областями:

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);
    }
    }
  }
}

Пример A.40.1c : Следующий пример не соответствует поскольку внутренние и внешние области цикла тесно вложены

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);
    }
  }    
}

Обратите внимание, что это отличается от:

#pragma omp parallel for
  for(int ii = 0; ii < n; ii++) {
    /* ... */
#pragma omp parallel for 
    for(int jj = 0; jj < m; jj++) {
      /* ... */
    }
  }

, в котором вы пытаетесь создать вложенную параллельную область.Только в этом случае обсуждение Мистического ответа имеет место.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...