27

次のようなネストされた並列 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
}

新しいタスクを作成する以外のことを行うための外側の類似点はありますか?

4

2 に答える 2

40

コンパイラが 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コードが機能しますが、それは最良のアイデアではない可能性があります。

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

于 2012-05-10T20:47:57.943 に答える
12

番号。

1 つ目#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
    }
}
于 2012-05-10T19:49:27.557 に答える