我是openMP和C的新手,我尝试过“OpenMP简介 - 蒂姆·马特森(英特尔)”Pi的例子但结果却不是3.14。我将代码与老师进行比较。他们是一样的。但结果是不同的
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
//OpenMP example program: hello;
static long num_steps = 100000;
#define NUM_THREADS 2
double step;
int main()
{
int nnum,i,j=0;
step= 1.0/(double)num_steps;
double sum[NUM_THREADS];
double x,pi,result=0.0;
omp_set_num_threads(NUM_THREADS);
#pragma omp parallel
{
int id=omp_get_thread_num();
int num=omp_get_num_threads();
if(id==0) nnum = num;
for(i=id,sum[id]=0.0;i<num_steps;i=i+num)
{
x=(i+0.5)*step;
sum[id]=sum[id]+(4.0/(1.0+x*x));
}
}
while(j<nnum)
{
printf(" is %2.4f \n",sum[j]);
result=result+sum[j];
j++;
}
pi = step*result;
printf("the result is %f \n",pi);
return 0;
}
答案 0 :(得分:4)
代码错了。 &#34;我&#34;变量由线程共享,并且两者都递增,因此有效地只执行预期迭代的1 / NUM_THREADS。
有三种不同的方法来解决它。第一个是写
#pragma omp parallel private(i)
这使得每个线程都使用变量的单独副本。第二种是在i
内声明#pragma omp parallel
,这具有相同的效果(请参阅代码中id
已经是私有的)。
第三个也是更有趣的是将for
语句更改为
#pragma omp for
for(i=0;i<num_steps;i++)
这使得OpenMP编译器查看循环并说“好”,这是一个带有num_steps
次迭代的循环&#34;。然后它将生成代码以将0..num_steps-1范围拆分为一个或多个块,并将它们中的每一个传递给NUM_THREADS
个线程之一。例如,一个线程将处理0到49999,另一个线程将处理50000到99999.重要的是要注意:
没有#pragma omp for
,for
循环指定每个单独线程的索引,因此迭代变量i
必须是私有的
#pragma omp for
,for
循环指定整个循环的索引,迭代变量i
不必是私有的,因为OpenMP将创建一个单独的线程-private迭代变量本身。