スコープチェックを有効にするには、-xvpara および -xopenmp オプションを使用するとともに最適化レベルを -xO3 かそれ以上に設定してから OpenMP プログラムをコンパイルする必要があります。スコープチェックは、プログラムが -xopenmp=noopt でコンパイルされただけでは動作しません。最適化レベルが -xO3 未満の場合、コンパイラは警告メッセージを発行し、スコープチェックを行いません。
スコープチェック時には、コンパイラはすべての OpenMP 構文を確認します。いくつかの変数のスコープ宣言に問題がある場合は、コンパイラは警告メッセージを発行します。場合によっては、正しいデータ共有属性節が提案されます。
次に例を示します。
例 7-1 スコープチェック
% 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 source2
% 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 への参照では、何らかのガベージ値が取得されることがあります。コンパイラはこの問題を指摘し、FIRSTPRIVATE としてスコープ宣言することをプログラマに提案します。
変数 i はループインデックス変数です。ループインデックスがループ後に使用される場合、プログラマはこれを LASTPRIVATE として指定することもあります。 しかし、これは上記の例には当てはまりません。i はループ後にはまったく参照されていません。コンパイラは警告を発行し、i を PRIVATE としてスコープ宣言するようプログラマに提案します。PRIVATE を LASTPRIVATE の代わりに使用すると、パフォーマンスが向上します。
プログラマは、変数 b に対してはデータ共有属性を明示的に指定しません。OpenMP 仕様 3.0 の 79 ページ、27 - 28 行によると、b は SHARED として暗黙的にスコープ宣言されます。ただし、b を SHARED としてスコープ宣言すると、データ競合が発生します。b の正しいデータ共有属性は REDUCTION です。