openMP вложенная параллель для циклов против внутренней параллели для

Если я использую вложенную параллель для таких циклов:

#pragma omp parallel for schedule(dynamic,1)
for (int x = 0; x < x_max; ++x) {
    #pragma omp parallel for schedule(dynamic,1)
    for (int y = 0; y < y_max; ++y) { 
    //parallelize this code here
   }
//IMPORTANT: no code in here
}

это эквивалентно:

for (int x = 0; x < x_max; ++x) {
    #pragma omp parallel for schedule(dynamic,1)
    for (int y = 0; y < y_max; ++y) { 
    //parallelize this code here
   }
//IMPORTANT: no code in here
}

Является ли внешняя параллель для выполнения чего-либо другого, кроме создания новой задачи?

Ответ 1

Если ваш компилятор поддерживает OpenMP 3.0, вы можете использовать предложение collapse:

#pragma omp parallel for schedule(dynamic,1) collapse(2)
for (int x = 0; x < x_max; ++x) {
    for (int y = 0; y < y_max; ++y) { 
    //parallelize this code here
    }
//IMPORTANT: no code in here
}

Если это не так (например, поддерживается только OpenMP 2.5), существует простой способ:

#pragma omp parallel for schedule(dynamic,1)
for (int xy = 0; xy < x_max*y_max; ++xy) {
    int x = xy / y_max;
    int y = xy % y_max;
    //parallelize this code here
}

Вы можете включить вложенный параллелизм с omp_set_nested(1); и ваш вложенный omp parallel for кода будет работать, но это может быть не лучшая идея.

Кстати, почему динамическое планирование? Является ли каждая итерация цикла оценена в непостоянное время?

Ответ 2

NO.

Первая #pragma omp parallel создаст команду параллельных потоков, а вторая попытается создать для каждого из исходных потоков другую команду, то есть команду команд. Однако практически во всех существующих реализациях вторая команда имеет только один поток: вторая параллельная область по существу не используется. Таким образом, ваш код больше похож на

#pragma omp parallel for schedule(dynamic,1)
for (int x = 0; x < x_max; ++x) {
    // only one x per thread
    for (int y = 0; y < y_max; ++y) { 
        // code here: each thread loops all y
    }
}

Если вы этого не хотите, но только параллельный внутренний цикл, вы можете сделать это:

#pragma omp parallel
for (int x = 0; x < x_max; ++x) {
    // each thread loops over all x
#pragma omp for schedule(dynamic,1)
    for (int y = 0; y < y_max; ++y) { 
        // code here, only one y per thread
    }
}