2011-12-22 4 views
2

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

ответ

3

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

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

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

+0

Я думаю, что ваш ответ может быть неправильным в том смысле, что он обращается к другой ситуации от той, которую спрашивает ОП. – Massimiliano

+0

@Massimiliano Hmm ... хорошо пункт. Но я не могу ни подтвердить, ни отрицать UB, что вы утверждаете в своем ответе, поскольку, похоже, у меня есть другая интерпретация этих двух пуль. – Mysticial

+0

Какова ваша интерпретация? По крайней мере, согласны ли вы, что если 'n% nthreads!= 0', а расписание не является «статическим», тогда точка 2 всегда нарушается? – Massimiliano

1

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

#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 and 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++) { 
     /* ... */ 
    } 
    } 

, в котором вы пытаетесь породить вложенный параллельная область. Только в этом случае обсуждается ответ «Мистический».

Смежные вопросы