C 为什么这个OpenMP程序每次都给我不同的答案?
我正在尝试使用多个线程运行此程序C 为什么这个OpenMP程序每次都给我不同的答案?,c,multithreading,parallel-processing,openmp,C,Multithreading,Parallel Processing,Openmp,我正在尝试使用多个线程运行此程序 #include <stdio.h> #include <time.h> #include <omp.h> #define NUM_THREADS 4 static long num_steps = 1000000000; int main() { int i; double x, pi, sum = 0.0; double step = 1.0/(double)num_steps; clock_t st
#include <stdio.h>
#include <time.h>
#include <omp.h>
#define NUM_THREADS 4
static long num_steps = 1000000000;
int main()
{
int i;
double x, pi, sum = 0.0;
double step = 1.0/(double)num_steps;
clock_t start = clock(), diff;
#pragma omp parallel for num_threads(NUM_THREADS) reduction (+:sum)
for (i = 0; i < num_steps; i++)
{
x = (i+0.5)*step;
sum += 4.0/(1.0 + x*x);
}
#pragma omp ordered
pi = step*sum;
printf("pi = %.15f\n %d iterations\n", pi, num_steps);
diff = clock() - start;
int msec = diff * 1000 / CLOCKS_PER_SEC;
printf("Time taken %d seconds %d milliseconds", msec/1000, msec%1000);
return 0;
}
#包括
#包括
#包括
#定义NUM_线程4
静态长步数=100000000;
int main()
{
int i;
双x,π,和=0.0;
双步长=1.0/(双)个步长;
时钟开始=时钟(),差异;
#pragma omp parallel for num_线程(num_线程)缩减(+:sum)
对于(i=0;i
通过添加num_线程的#pragma omp parallel(num_线程)缩减(+:sum)
。我也在for循环之后订购了#pragma omp
,我认为我实际上不需要它,因为在所有线程都完成for循环之前,任何线程都不应该继续。这是正确的吗?这也是为什么与作为单线程程序运行相比,我的性能只提高了大约一秒的原因吗?这是6秒,而我只有7秒
我无法回答的是,为什么每次运行该程序时,它都会给我一个不同的pi答案?您的问题来自于您忘记声明
x
private
。
如果将OpenMP指令更改为:
#pragma omp parallel for num_threads(NUM_THREADS) reduction(+:sum) private(x)
您的代码将生效
然而,这里仍然存在两个问题:
#pragma omp ordered
没有任何意义,因为您没有进入并行
区域。你应该移除它clock()
测量时间是危险的,这不是因为该函数不是线程安全的,而是因为它返回当前线程及其子线程的CPU时间,而不是经过的时间。因此,无论是否激活OpenMP,您通常都会得到几乎相同的结果,人们会纳闷为什么他们的代码没有公开任何加速。。。因此,除非您有很好的理由使用clock()
,否则请使用omp\u get\u wtime()
除了Gilles指出的bug之外,这里还有一个更基本的问题 并行线程之间的缩减不一定是确定的。每线程贡献的组合顺序可以随着代码的每次执行而改变。如果您不知道为什么这很重要,请阅读“ 如果你没有得到这一点,那么,考虑三个线程在十进制算术机上做一个和减少,它支持三位数的精度。 假设我们对集合(100,-100,0.1)进行累加,如果我们按这个顺序加,我们将得到100-100=0+0.1=0.1,但是如果我们按这个顺序加(100,0.1,-100),我们将得到100+0.1=100(三个有效数字,记住!)-100==0
如果您使用的是英特尔编译器,则可以设置一个环境变量来请求确定性缩减(
KMP\u deterministic\u reduce
),但是,该环境变量仅在使用相同数量的线程时才强制执行确定性。它不会在具有不同线程数的运行之间强制执行它。(这样做需要对每个线程贡献的累积执行一个命令,这将需要不同的代码生成和一些线程间同步)。我在vs2015中测试了您的程序,它每次都给我相同的pi值,这很奇怪。只是复制粘贴了一次,然后运行了两次。第一次是3.141737761473218,第二次是3.141576654805244。如果这有什么意义的话,我就在Windows上。也许我应该在Linux上试试。我得到了所有时间3.141592653589971,这似乎很好。注意,OP使用的是Windows。MSVC和MinGW(而不是MinGW-w64)使用的Microsoft C运行时库clock()
返回墙时间。但我同意通常最好使用omp\u get\u wtime()
。