Résultat bizarre chez moi (dual core), apparemment OpenMP a besoin d’une synchronisation explicite lorsque plusieurs threads accèdent à un même emplacement mémoire.
pi1.c
[code]#include <stdio.h>
#include <omp.h>
inline double MoinsUnPuissanceN(const int n)
{
return (n&1) ? -1. : 1.;
}
void main()
{
double p = 4.;
unsigned long rang = 1000000000;
#pragma omp parallel for
for(unsigned long i = 1; i <= rang; ++i)
{
p += (MoinsUnPuissanceN(i) * 4.) / (2. * i + 1.);
}
printf(“valeur approchée de pi au rang %ld : %.10f\n”, rang, p);
}[/code]
pi2.c
[code]#include <stdio.h>
#include <omp.h>
inline double MoinsUnPuissanceN(const int n)
{
return (n&1) ? -1. : 1.;
}
void main()
{
const int nb_thread = 2;
double result[nb_thread]; // désolé j’aime pas devoir modifier 2 endroits pour un même paramètre 
double p = 4.;
unsigned long rang = 1000000000;
// du coup faut initialiser le tableau
for (double* I = result; I < result + nb_thread; ++I)
*I = 0.;
#pragma omp parallel for num_threads(nb_thread)
for(unsigned long i = 1; i <= rang; ++i)
{
result[omp_get_thread_num()] += (MoinsUnPuissanceN(i) * 4.) / (2. * i + 1.);
}
for(double* I = result; I < result + nb_thread; ++I)
{
p += *I;
}
printf(“valeur approchée de pi au rang %ld : %.10f\n”, rang, p);
}[/code]
[code]$ export CFLAGS=’-std=c99 -O2 -fopenmp’
$ make pi1 pi2
$ time ./pi1
valeur approchée de pi au rang 1000000000 : 3.9999999990
real 0m3.675s
user 0m6.944s
sys 0m0.000s
$ time ./pi2
valeur approchée de pi au rang 1000000000 : 3.1415926546
real 0m3.596s
user 0m6.928s
sys 0m0.016s[/code]
En premier j’ai pensé à un bug que j’aurais introduit quand j’ai légèrement modifié le code, mais le fait est que non. En plus si je supprime la ligne OpenMP dans pi1 le résultat redevient correct, c’est donc clairement un problème de synchronisation. Le plus bizarre c’est que dans ta version (pas dans la mienne) le résultat n’est correct que si la déclaration double p = 4 utilise un transtypage int -> double (si j’utilise double p = 4. le résultat est mauvais).
Bref y’a un truc vraiment pas clair qui me semble provenir d’OpenMP, mais comme je ne le connais pas je ne saurais pas dire d’où ça vient précisément. À vue de nez il semble avoir besoin d’une synchronisation explicite sur p (peut-être à rajouter dans la ligne #pragma omp ?).
Bon sinon si on ne tient pas compte de la correction du résultat, au niveau performance pure c’est kif-kif chez moi : pas plus de 150ms d’écart pour 10¹⁰ itérations sur 35.3 secondes au total. Mais bien entendu si on rajoute de la synchro à pi1 ses perfs vont chuter.
Dernière remarque : sur un système mono-CPU multi-core le code de pi2 marche bien tel qu’il est car les différents cores partagent le même cache (L1 et/ou L2 je sais jamais).
Par contre sur un système réellement multi-CPU il va y avoir énormément de cache-trashing (et donc une terrible perte de performance) car (sauf hasard) les variables modifiées dans les différents threads sont trop proches les unes des autres dans la mémoire (même ligne de cache). Pour résoudre ce souci il faut ajouter assez de padding pour que les différents éléments du tableau soient certains de se trouver sur des lignes de cache différentes (padding dépendant du CPU).
Edit : je crois qu’on s’est un peu éloignés de la question d’origine là… 
Incorrigibles j’vous dis !