Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么这个OpenMP程序每次都给我不同的答案?_C_Multithreading_Parallel Processing_Openmp - Fatal编程技术网

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()