prime_omp.c 内のスレッドは、関数 is_prime() を実行することによって、整数が素数かどうかをチェックします。
16 int is_prime(int v) 17 { 18 int i; 19 int bound = floor(sqrt(v)) + 1; 20 21 for (i = 2; i < bound; i++) { 22 /* no need to check against known composites */ 23 if (!pflag[i]) 24 continue; 25 if (v % i == 0) { 26 pflag[v] = 0; 27 return 0; 28 } 29 } 30 return (v > 1); 31 }
スレッドアナライザは、行 26 での pflag[ ] への書き込みと行 23 での pflag[ ] の読み取りとの間にデータの競合があることを報告します。ただし、このデータの競合は、最終的な結果の正確さには影響しないので影響のないものです。23 行で、スレッドは、所与の i の値で、pflag[i] が 0 に等しいかどうかをチェックします。pflag[i] が 0 に等しい場合、i が既知の合成数である (つまり、 i は素数でないとわかっている) ことを意味します。この結果、v が i で割り切れるかどうかをチェックする必要がなくなります。v がいずれかの素数で割り切れるかどうかだけをチェックすればよくなります。したがって、pflag[i] が 0 に等しい場合、スレッドは i の次の値に進みます。pflag[i] が 0 に等しくなく、v が i で割り切れる場合、スレッドは 0 を pflag[v] に割り当てて、v が素数でないことを示します。
正確さの観点からは、複数のスレッドが同じ pflag[ ] 要素をチェックし、同時にそれに書き込むかどうかは重要ではありません。pflag[ ] 要素の初期値は 1 です。スレッドはこの要素を更新するときに、0 の値を割り当てます。つまり、スレッドはその要素に対してメモリーの同じバイトの同じビットに 0 を格納します。現在のアーキテクチャーでは、このような格納は不可分であると想定することが安全です。つまり、その要素がスレッドによって読み取られるときに、読み取られる値は 1 か 0 のどちらかになります。スレッドは、0 の値を割り当てる前に所定の pflag[ ]要素をチェックする場合 (行 23)、行 25 から 28 を実行します。その間に別のスレッドがその同じ pflag[ ] 要素 (行 26) に 0 を割り当てた場合も、最終結果は変化しません。これは、基本的に、最初のスレッドが不必要に行 25 ~ 28 を実行したが、最終結果は同じであったことを意味します。