考虑以下最小C代码示例。使用export OMP_NUM_THREADS=4 && gcc -fopenmp minimal.c && ./a.out
(Debian 8上的GCC 4.9.2)编译和执行时,这会在我的机器上生成五行rho=100
(有时也是200或400)。所有五条印刷线的预期输出当然是rho=400
。
如果我在// MARKER
插入更多代码或在那里放置障碍,程序更有可能产生正确的结果。但即使有另一个障碍,它有时会失败,我的计划也会失败。所以问题似乎是a
在进入缩减循环时未正确初始化。
第55页的OpenMP 4.0.0 manual偶数状态在循环结构的末尾有一个隐式屏障,除非指定了nowait子句。因此应设置a
在这一点上。这里出了什么问题?我错过了什么吗?
#include <stdio.h>
#ifdef _OPENMP
#include <omp.h>
#define ID omp_get_thread_num()
#else
#define ID 0
#endif
double a[100];
int main(int argc, char *argv[]) {
int i;
double rho;
#pragma omp parallel
{
#pragma omp for
for (i = 0; i < 100; i++) {
a[i] = 2;
}
// MARKER
rho = 0.0;
#pragma omp for reduction(+: rho)
for (i = 0; i < 100; i++) {
rho += ((a[i])*(a[i]));
}
fprintf(stderr, "[%d] rho=%f\n", ID, rho);
}
fprintf(stderr, "[%d] rho=%f\n", ID, rho);
return 0;
}
答案 0 :(得分:3)
好的,我已经得到了答案,但我很生气......
这是一种竞争条件,因为rho
已共享且您在并行区域内初始化它,如rho = 0.0;
将其初始化到并行区域之外,或者之前使用#pragma omp single
将修复代码......