Sun Studio 12: スレッドアナライザユーザーズガイド

2.4.3.1 omp_prime.c 内のバグの修正

次に omp_prime.c のバグを修正する方法を示します。このファイルの全コードリストは、「2.1.1 omp_prime.c の全コード」にあります。

行 45 の total の read と行 46 の total への write とのデータ競合を解決するには、行 45 と 46 をクリティカルセクションに移動します。クリティカルセクションはこの 2 つの行を保護し、データ競合の発生を防ぎます。次に修正したコードを示します。

42      #pragma omp parallel for         .
43      for (i = 2; i < N; i++) {
44          if ( is_prime(i) ) {
                 #pragma omp critical

                 {          
 45                 primes[total] = i;
 46                 total++;
                 }
 47          }
 48      }

1 つのクリティカルセクションを追加することで、omp_prime.c 内のほかの 2 つのデータ競合も解決されます。行 45 の prime[] でのデータ競合だけでなく、行 46 の total でのデータ競合も解決します。4 つ目の、 行 18 の pflag[] の read と行 21 の pflag[] への write とのデータ競合は、不正な結果につながることはないため、実際には良性のデータ競合です。良性のデータ競合の解決は重要ではありません。

次に示すように行 45 と 46 をクリティカルセクションに移動することもできますが、この変更はプログラムの問題の解決になりません。

42      #pragma omp parallel for         .
43      for (i = 2; i < N; i++) {
44          if ( is_prime(i) ) {
                 #pragma omp critical
                 {          
45                 primes[total] = i;
                 }
                 #pragma omp critical
                 {

46                 total++;
                 }
47          }
48      }

スレッドが排他的ロックを使用して total へのアクセスを制御していないため、行 45 と 46 を含むこのクリティカルセクションによってデータ競合は解消されます。行 46 を含むクリティカルセクションは、total の演算値が必ず正しくなるようにします。しかし、依然としてプログラムは正しくありません。2 つのスレッドが、同じ total 値を使用して primes[] の同じ要素を更新する可能性があります。さらに、primes[] 内の一部要素にまったく値が代入されない可能性があります。