为什么以下 OpenMP 程序无法减少我的变量?
Why fails the following OpenMP program to reduce my variable?
考虑以下最小 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
在进入缩减循环时没有正确初始化。
OpenMP 4.0.0 manual 甚至在第 55 页指出 除非指定 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;
}
好的,我得到了答案,但我很努力地得到它...
这是一个竞争条件,因为 rho
是共享的并且您在并行区域内初始化它 rho = 0.0;
要么在并行区域之外初始化它,要么在之前使用 #pragma omp single
将修复代码...
考虑以下最小 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
在进入缩减循环时没有正确初始化。
OpenMP 4.0.0 manual 甚至在第 55 页指出 除非指定 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;
}
好的,我得到了答案,但我很努力地得到它...
这是一个竞争条件,因为 rho
是共享的并且您在并行区域内初始化它 rho = 0.0;
要么在并行区域之外初始化它,要么在之前使用 #pragma omp single
将修复代码...