以下说明如何修复 omp_prime.c 中的错误。有关完整的文件列表,请参见 2.1.1 omp_prime.c 的完整列表。
将第 45 行和第 46 行移动到临界段中,以便消除第 45 行上 total 的读取和第 46 行上 total 的写入之间的数据争用。临界段保护这两行并防止数据争用。以下是更正后的代码:
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 }
请注意,添加单个临界段还修复了 omp_prime.c 中的两个其他数据争用。它修复了第 45 行上 prime[]
的数据争用,以及第 46 行上 total 的数据争用。第 18 行上 pflag[]
的读取和第 21 行上 pflag[]
的写入之间的第四个数据争用实际上是良性争用,因为它不会导致不正确的结果。修复良性数据争用不是必需的。
还可以将第 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 }
第 45 行和第 46 行周围的临界段消除了数据争用,因为线程不使用任何互斥锁控制其对 total 的访问。第 46 行周围的临界段确保 total 的计算值是正确的。但是,程序仍是不正确的。两个线程可能使用 total 的同一值更新 primes[]
的同一元素。此外,primes[]
中的某些元素可能根本未赋值。