venerdì 5 ottobre 2012

Pi Greco con OpenMP e GMP

Per testare il calcolo parallelo e l'Hyperthreading avevo la necessita' di un algoritmo parallelizzabile e con una convergenza piuttosto lenta per poter apprezzare le differenze di tempo di calcolo nella versione parallela e non parallela.

Scartato il calcolo di Pi Greco mediante la formula di Gauss (gia' utilizzata in un precedente post) perche' ricorsiva e quindi non parallelizzabile e scartato l'insieme di Mandelbrot perche' comunque un minimo complesso , ho provato a determinare il valore di Pi Greco mediante lo sviluppo in serie di Taylor mediante la formula


La sommatoria converge con estrema lentezza al valore di Pi Greco

Standard (tempo di esecuzione 0.049s)
-----------------------------------------------------

#include <cmath>
#include <iostream>

using namespace std;

int main()
{

float pi_s = 0.0;

for (int n=0; n<100000;++n)
{
pi_s = pi_s + (pow(-1,n)/(2*n+1));
}
cout << "Normale " << pi_s*4 << endl <<endl;

return 0;
}
-----------------------------------------------------


OMP (tempo di esecuzione 0.05s)
-----------------------------------------------------

#include <cmath>
#include <iostream>
#include <omp.h>

using namespace std;

int main()
{

float pi_s = 0.0;
#rpragma omp parallel
{
#pragma omp for reduction(+:pi_s) nowait
for (int n=0; n<100000;++n)
{
pi_s = pi_s + (pow(-1,n)/(2*n+1));
}
}
cout << "Normale " << pi_s*4 << endl <<endl;

return 0;
}

-----------------------------------------------------


GMP (tempo di esecuzione 0.1s)
-----------------------------------------------------

#include <cmath>
#include <iostream>
#include <gmp.h>

using namespace std;

int main()
{
mpf_t pi;
mpf_t transi;
mpf_t print;


int sopra;
int sotto;
//float pi_s = 0.0;

mpf_init_set_ui(pi,0);
mpf_init_set_ui(transi,1);
mpf_init_set_ui(print,0);

for (int n=0; n<100000000;++n)
{
sopra = pow(-1,n);
sotto = (2*n)+1;
mpf_set_si(transi,sopra);
mpf_div_ui(transi,transi,sotto);
mpf_add(pi,pi,transi);
mpf_mul_ui(print,pi,4);

//Calcolo eseguito senza GMP
//pi_s = pi_s + (pow(-1,n)/(2*n+1)); 
//cout << "Normale " << pi_s*4 << endl <<endl;
}
gmp_printf("Pi %.Ff\n",print);

return 0;
}



-----------------------------------------------------

L'integrazione di OMP e GMP non e' banale perche' se si uniscono i due esempi sopra riportati il compilatore riporta che la variabile pi has invalid type for ' reduction'