スコープチェックを有効にするには、-xvpara および -xopenmp オプションを指定して OpenMP プログラムをコンパイルします。最適化レベルは -xO3 以上にしてください。スコープチェックは、プログラムが -xopenmp=noopt でコンパイルされただけでは動作しません。最適化レベルが -xO3 未満の場合、コンパイラは警告メッセージを発行し、スコープチェックを行いません。
スコープチェック時には、コンパイラはすべての OpenMP 構文を確認します。いくつかの変数のスコープ宣言に問題がある場合、コンパイラは警告メッセージを発行し、場合によっては、正しいデータ共有属性節を提案します。たとえば、コンパイラが次の状態を検出すると、警告メッセージが表示されます。
異なるループ繰り返し間でデータに依存関係がある場合に、OpenMP ディレクティブを使用して並列化されたループ。
OpenMP のデータ共有属性節に問題がある可能性がある。たとえば、並列領域内の変数へのアクセスがデータ競合を招く可能性があるときに、並列領域に shared になる変数を指定した場合、または並列領域内の変数に割り当てられた値が並列領域のあとで使用されるときに、並列領域に private になる変数を指定した場合です。
% cat t.c #include <omp.h> #include <string.h> int main() { int g[100], b, i; memset(g, 0, sizeof(int)*100); #pragma omp parallel for shared(b) for (i = 0; i < 100; i++) { b += g[i]; } return 0; } % cc -xopenmp -xO3 -xvpara source1.c "source1.c", line 10: Warning: inappropriate scoping variable 'b' may be scoped inappropriately as 'shared' . write at line 13 and write at line 13 may cause data race "source1.c", line 10: Warning: inappropriate scoping variable 'b' may be scoped inappropriately as 'shared' . write at line 13 and read at line 13 may cause data race
コンパイラは、最適化レベルが -xO3 未満の場合はスコープチェックを行いません。
% cc -xopenmp=noopt -xvpara source1.c "source1.c", line 10: Warning: Scope checking under vpara compiler option is supported with optimization level -xO3 or higher. Compile with a higher optimization level to enable this feature
次の例は、潜在的なスコープエラーがどのように報告されるかを示しています。
使用例 7-2 スコープ宣言エラーの例% cat source2.c #include <omp.h> int main() { int g[100]; int r=0, a=1, b, i; #pragma omp parallel for private(a) lastprivate(i) reduction(+:r) for (i = 0; i < 100; i++) { g[i] = a; b = b + g[i]; r = r * g[i]; } a = b; return 0; } % cc -xopenmp -xO3 -xvpara source2.c "source2.c", line 8: Warning: inappropriate scoping variable 'r' may be scoped inappropriately as 'reduction' . reference at line 13 may not be a reduction of the specified type "source2.c", line 8: Warning: inappropriate scoping variable 'a' may be scoped inappropriately as 'private' . read at line 11 may be undefined . consider 'firstprivate' "source2.c", line 8: Warning: inappropriate scoping variable 'i' may be scoped inappropriately as 'lastprivate' . value defined inside the parallel construct is not used outside . consider 'private' "source2.c", line 8: Warning: inappropriate scoping variable 'b' may be scoped inappropriately as 'shared' . write at line 12 and write at line 12 may cause data race "source2.c", line 8: Warning: inappropriate scoping variable 'b' may be scoped inappropriately as 'shared' . write at line 12 and read at line 12 may cause data race
この例は、スコープチェックによって検出される典型的なエラーを示しています。
縮約変数として r が指定され、この変数の演算は + となっているが、実際に行われるべき演算は * です。
private として a が明示的にスコープ宣言されています。private 変数には初期値がないので、行 11 の a への参照では、未定義の値が取得されることがあります。コンパイラはこの問題を指摘し、a を firstprivate としてスコープ宣言するように提案します。
変数 i はループインデックス変数です。ループインデックスの値が parallel for ループのあとに使用される場合、プログラマはこれを LASTPRIVATE として指定することもあります。ただし、上記の例では、i はループ後にまったく参照されません。コンパイラは警告を発行し、i を private としてスコープ宣言するように提案します。private を lastprivate の代わりに使用すると、パフォーマンスが向上します。
変数 b にはデータ共有属性が明示的に指定されていません。OpenMP 仕様によると、b は shared として暗黙的にスコープ宣言されます。ただし、b を shared としてスコープ宣言すると、データ競合が発生します。b の正しいデータ共有属性は reduction です。