J'essaie de paralléliser une boucle for très simple, mais c'est ma première tentative d'utiliser openMP depuis longtemps. Je suis déconcerté par les temps d'exécution. Voici mon code:
#include <vector>
#include <algorithm>
using namespace std;
int main ()
{
int n=400000, m=1000;
double x=0,y=0;
double s=0;
vector< double > shifts(n,0);
#pragma omp parallel for
for (int j=0; j<n; j++) {
double r=0.0;
for (int i=0; i < m; i++){
double Rand_g1 = cos(i/double(m));
double Rand_g2 = sin(i/double(m));
x += Rand_g1;
y += Rand_g2;
r += sqrt(Rand_g1*Rand_g1 + Rand_g2*Rand_g2);
}
shifts[j] = r / m;
}
cout << *std::max_element( shifts.begin(), shifts.end() ) << endl;
}
Je le compile avec
g++ -O3 testMP.cc -o testMP -I /opt/boost_1_48_0/include
c'est-à-dire, pas de "-fopenmp", et j'obtiens ces timings:
real 0m18.417s
user 0m18.357s
sys 0m0.004s
quand j'utilise "-fopenmp",
g++ -O3 -fopenmp testMP.cc -o testMP -I /opt/boost_1_48_0/include
Je reçois ces chiffres pour l'époque:
real 0m6.853s
user 0m52.007s
sys 0m0.008s
ce qui n'a pas de sens pour moi. Comment l'utilisation de huit cœurs ne peut entraîner qu'une augmentation de 3 fois des performances? Suis-je en train de coder la boucle correctement?
Vous devez utiliser la clause OpenMP reduction
pour x
et y
:
#pragma omp parallel for reduction(+:x,y)
for (int j=0; j<n; j++) {
double r=0.0;
for (int i=0; i < m; i++){
double Rand_g1 = cos(i/double(m));
double Rand_g2 = sin(i/double(m));
x += Rand_g1;
y += Rand_g2;
r += sqrt(Rand_g1*Rand_g1 + Rand_g2*Rand_g2);
}
shifts[j] = r / m;
}
Avec reduction
chaque thread accumule sa propre somme partielle dans x
et y
et à la fin toutes les valeurs partielles sont additionnées afin d'obtenir les valeurs finales.
Serial version:
25.05s user 0.01s system 99% cpu 25.059 total
OpenMP version w/ OMP_NUM_THREADS=16:
24.76s user 0.02s system 1590% cpu 1.559 total
Voir - accélération superlinéaire :)
essayons de comprendre comment paralléliser une boucle simple en utilisant OpenMP
#pragma omp parallel
#pragma omp for
for(i = 1; i < 13; i++)
{
c[i] = a[i] + b[i];
}
supposons que nous avons 3
threads disponibles, c'est ce qui va se passer
d'abord
et enfin