web-dev-qa-db-ja.com

OpenMPネストされた並列forループと内部並列for

このようなネストされた並列forループを使用する場合:

#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
}

新しいタスクを作成する以外のことを実行するための外側の並列はありますか?

23
Scott Logan

コンパイラが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_コードは機能しますが、それは最善のアイデアではないかもしれません。

ところで、なぜ動的スケジューリングなのか?すべてのループの繰り返しは非一定の時間で評価されますか?

39
Hristo Iliev

番号。

最初 #pragma omp parallelは並列スレッドのチームを作成し、2番目のスレッドは元のスレッドのそれぞれに対して別のチーム、つまりチームのチームを作成しようとします。ただし、ほとんどすべての既存の実装では、2番目のチームにはスレッドが1つしかありません。2番目の並列領域は基本的に使用されません。したがって、あなたのコードは、

#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
    }
}
10
Walter