实现并行算法来计算pi

时间:2010-03-02 09:51:46

标签: c algorithm openmp

我想在OpenMP中使用线程实现下面代码的并行版本,有没有更好的方法呢?

/* Program to compute Pi using Monte Carlo methods */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#define SEED 35791246

int main(int argc, char* argv)
{
   int niter=0;
   double x,y;
   int i,count=0; /* # of points in the 1st quadrant of unit circle */
   double z;
   double pi;
   clock_t end_time, start_time; 


   printf("Enter the number of iterations used to estimate pi: ");
   scanf("%d",&niter);

   start_time = clock(); 
   /* initialize random numbers */
   srand(SEED);
   count=0;

 #pragma omp parallel for
      for ( i=0; i<niter; i++) {
      x = (double)rand()/RAND_MAX;
      y = (double)rand()/RAND_MAX;
      z = x*x+y*y;
      if (z<=1) count++;
    }  
#pragma omp task
   pi=(double)count/niter*4;
#pragma omp barrier

   end_time = clock();

   printf("# of trials= %d , estimate of pi is %g, time= %f \n",niter,pi, difftime(end_time, start_time));

   return 0;
}

2 个答案:

答案 0 :(得分:2)

rand功能在这里使用不是一个好主意。要么它不是线程安全的,你将有线程获得重复值(不是非常随机),或者它将有一个锁,MP版本将比单线程版本慢。

我建议找另一个可以从多个线程同时使用的随机数生成器。

答案 1 :(得分:2)

可以通过更正一些OpenMP错误来改进。首先,由于您在所有并行线程中总结({副本] count,因此您需要在并行段末尾应用减少运算符,以将所有这些运算符组合回单个值。此外,变量ixyz需要为每个并行线程设置单独的实例 - 您不希望线程使用相同的线程!要指定所有这些,循环顶部的#pragma指令应为:

#pragma omp parallel for private(i, x, y, z) reduction(+:count)

此外,其范围是for循环,因此您无需执行任何其他操作;循环退出后,线程会自动同步。 (并且您需要同步以使count包含来自所有线程的所有增量!)特别是,您的taskbarrier pragma是没有意义的,因为此时您又回到了只有一个线程 - 而且,将单个计算放在并行任务中是没有意义的。

在这些情况下,gabe提出了系统随机数生成器可能缓慢和/或随机性差的问题。您可能希望调查系统中的详细信息,并在每个线程中为其提供一个新的随机种子,或根据您找到的内容使用不同的随机数生成器。

除此之外,它看起来相当合理。你可以对该算法做很多其他事情,因为它简短且可以平行化。