OpenMP* THREADPRIVATE 変数の不適切な使用

並列領域間でのデータの受け渡しに THREADPRIVATE 変数が誤って使用されています。

THREADPRIVATE 宣言子は、変数を複製して、それぞれのスレッドで独自のコピーを持つように指定します。OpenMP* は、予期できない方法でスレッドに処理を割り当てるため、特定のスレッドのプライベート・コピーの値がスケジューリング・ポイントの後に中間値となります。このエラー診断は、値が中間状態にあるときに THREADPRIVATE 変数が読み取られた場合にレポートされます。

THREADPRIVATE 変数の値は、主に 2 つの場合に中間状態となります。1 つ目は、変数が変更された並列領域を終了した時点です。ここでの問題は、どのスレッドがどの代入を実行するのか予測することが一般に不可能であることです。もう 1 つは、並列領域を開始する時点です。ここでの問題は、どのスレッドが領域を実行するチームに参加するのか予測することが一般に不可能であることです。並列領域に COPYIN 節がある場合、チームの各メンバーのプライベート・コピーは、エントリー時にマスタースレッドの変数の値で初期化されます。

このメッセージは、特に、ある並列領域で THREADPRIVATE 配列変数に値が代入され、別の並列領域でその値が読み取られた場合にレポートされます。OpenMP* は、非初期スレッドの THREADPRIVATE 変数にあるデータの値が、ごく限られた状況下において 2 つの並列領域間で保持されることのみ保証します。特に、2 つの並列領域は同じ番号のスレッドによってシーケンシャルに実行され、どちらの領域も明示的な並列領域内に (動的に) 入れ子されていてはなりません。さらに、両方の並列領域で dyn-var 内部制御変数は偽でなければなりません。これらすべての条件が満たされた場合は、それぞれの領域の同じスレッド番号の THREADPRIVATE 変数がその変数の同じコピーにアクセスします。

この診断のメッセージテキストは、2 つの並列領域がこの基準を満たせなかった原因を説明します。多くの原因が考えられます。例えば、異なる数の SECTION 宣言子を持つ 2 つの SECTIONS 領域は、常に同じ数のスレッドによって実行されません。

通常、このエラーは指摘された場所での THREADPRIVATE 変数の使用法が適切でないことを示します。並列領域を再編成して個別の領域で行われる操作を統合するか、または THREADPRIVATE 変数を使用せずに 2 つの並列領域間のデータを平坦化する必要があります。

ID

問題箇所

説明

1

不正なメモリーアクセス

値が参照された場所

2

OpenMP* 宣言

値が以前に定義された場所

3

OpenMP* 宣言

値が以前に定義された領域


#include <stdio.h>
#include <omp.h>

int a[1000];
#pragma omp threadprivate(a)

int main(int argc, char **argv)
{
    int i;
    int sum = 0;

#pragma omp parallel for schedule(static, 5)
    for (i = 0; i < 1000; i++) {
       a[i] = i;
    }

// The above loop will not map loop iterations to threads
// in the same way that the following loop did because
// the chunk size is different in the two loops.
// Therefore the threadprivate array "a" cannot be used to
// pass values from the first loop into the other in parallel mode.

#pragma omp parallel for reduction (+:sum) schedule(static, 20)
    for (i = 0; i < 1000; i++) {
        sum = sum + a[i];
    }
    
    printf("%d\n", sum);

    return 0;
}
        

© 2010 Intel Corporation. 無断での引用、転載を禁じます。