Home > Net >  Need explanation on why my pi is equal to 0
Need explanation on why my pi is equal to 0

Time:11-06

I was rewriting the code below using OpenMP task to parallilize the Pi program.

Original Code:

#include <omp.h>
#include <stdio.h>
static long num_steps = 1024*1024*1024;
#define MIN_BLK  1024*1024*256

double pi_comp(int Nstart,int Nfinish,double step)
{  int i,iblk;
double x, sum = 0.0,sum1, sum2;
if (Nfinish-Nstart < MIN_BLK){
  for (i=Nstart;i< Nfinish; i  ){
     x = (i 0.5)*step;
     sum = sum   4.0/(1.0 x*x); 
  }
}
else{
  iblk = Nfinish-Nstart;
  sum1 = pi_comp(Nstart,         Nfinish-iblk/2,step);
  sum2 = pi_comp(Nfinish-iblk/2, Nfinish,       step);
  sum = sum1   sum2;
}return sum;
}
int main ()
{
int i;
double step, pi, sum;
double init_time, final_time;
step = 1.0/(double) num_steps;

init_time = omp_get_wtime();
sum = pi_comp(0,num_steps,step);
pi = step * sum;
final_time = omp_get_wtime() - init_time;
printf(" for %ld steps pi = %f in %f secs\n",num_steps,pi,final_time);

}  

OpenMP Code:

#include <omp.h>
#include <stdio.h>
static long num_steps = 1024*1024*1024;
#define MIN_BLK  1024*1024*256

double pi_comp(int Nstart,int Nfinish,double step)
{  int i,iblk;
double x, sum = 0.0,sum1, sum2;
if (Nfinish-Nstart < MIN_BLK){
  for (i=Nstart;i< Nfinish; i  ){
     x = (i 0.5)*step;
     sum = sum   4.0/(1.0 x*x); 
  }
}
else{
  iblk = Nfinish-Nstart;
  #pragma omp task firstprivate(sum1)
  sum1 = pi_comp(Nstart,Nfinish-iblk/2,step);
  #pragma omp task firstprivate(sum2)
  sum2 = pi_comp(Nfinish-iblk/2, Nfinish,step);
  sum = sum1   sum2;
}return sum;
}
int main ()
{
int i;
double step, pi, sum;
double init_time, final_time;
step = 1.0/(double) num_steps;

init_time = omp_get_wtime();
#pragma omp parallel
{
#pragma omp single
sum = pi_comp(0,num_steps,step);
}

pi = step * sum;
final_time = omp_get_wtime() - init_time;
printf(" for %ld steps pi = %f in %f secs\n",num_steps,pi,final_time);

}  

I dont know why the output for the OpenMP program has pi = 0 instead of pi itself when testing the speed of a certain amount of thread. Is there something I did wrong in the OpenMP code that didn't give me pi?

Output:

g   -fopenmp  -c pi_recur_omp.cpp
g   -fopenmp  -o pi_recur_omp pi_recur_omp.o -lm
./pi_recur 
 for 1073741824 steps pi = 3.141593 in 4.562793 secs
./pi_recur_omp 
 for 1073741824 steps pi = 0.000000 in 2.990318 secs

CodePudding user response:

Your OpenMP code is not working properly because of:

  1. sum1 and sum2 should be shared. Using the firstprivate clause (which is the default) makes them private, so the updated values are not available outside the tasks.
  2. You have to wait for tasks to finish before you can sum them, so a #pragma omp taskwait line is needed.

So, your code should be something like:

#pragma omp task shared(sum1)
sum1 = pi_comp(Nstart,Nfinish-iblk/2,step);
#pragma omp task shared(sum2)
sum2 = pi_comp(Nfinish-iblk/2, Nfinish,step);
#pragma omp taskwait
sum = sum1   sum2;

CodePudding user response:

In this case, I'd say the mistake is using recursion at all. It doesn't really gain you much (if anything at all). I'd probably just do a simple iterative version:

#include <omp.h>
#include <stdio.h>
static long num_steps = 1024*1024*1024;

double pi_comp(int Nstart,int Nfinish,double step)
{  
    int i,iblk;
    double sum = 0.0,sum1, sum2;

#pragma omp parallel for reduction( :sum)
    for (i=Nstart;i< Nfinish; i  ){
        double x = (i 0.5)*step;
        sum = sum   4.0/(1.0 x*x); 
    }
    return sum;
}
int main ()
{
    int i;
    double step, pi, sum;
    double init_time, final_time;
    step = 1.0/(double) num_steps;

    init_time = omp_get_wtime();
    sum = pi_comp(0,num_steps,step);
    pi = step * sum;
    final_time = omp_get_wtime() - init_time;
    printf(" for %ld steps pi = %f in %f secs\n",num_steps,pi,final_time);

}

Result:

for 1073741824 steps pi = 3.141593 in 0.455449 secs
  • Related