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:
sum1
andsum2
should be shared. Using thefirstprivate
clause (which is the default) makes them private, so the updated values are not available outside the tasks.- 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