Parallèle pour la boucle dans openmp
Je suis en train de paralléliser un très simple boucle for, mais c'est ma première tentative à l'aide d'openMP dans un temps long. Je suis déconcerté par le 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
qui est, sans aucun "-fopenmp", et j'obtiens ces horaires:
real 0m18.417s
user 0m18.357s
sys 0m0.004s
lorsque j'utilise "-fopenmp",
g++ -O3 -fopenmp testMP.cc -o testMP -I /opt/boost_1_48_0/include
Je obtenir ces chiffres pour l'époque:
real 0m6.853s
user 0m52.007s
sys 0m0.008s
qui n'a pas de sens pour moi. Comment à l'aide de huit cœurs ne peut conduire qu'à tout juste 3 fois
augmentation de la performance? Suis-je le codage de la boucle correctement?
- Votre accès à la mémoire sont très locales. Vous êtes probablement faire des choses horribles à la mémoire cache du processeur. Il y a certains frais généraux de la direction générale de rejoindre trucs trop et vous pourriez être limité par la bande passante mémoire.
- Ne devrait pas x, y et r privés() par OpenMP? Comme cela, vous pourriez obtenir de mauvais résultats.
- Mieux encore, ils doivent être déclarés à l'intérieur de la boucle. Pré-déclarer les variables en début de fonction est odeur de code en C++.
- il n'est pas "odeur de code" si vous voulez savoir si cela n'est pas aléatoire marche se termine.
- Alors ils ne peuvent pas être privé. C'est l'odeur de code. Toujours. Déclarer des variables lorsque vous utilisez eux, pas plus tôt.
Vous devez vous connecter pour publier un commentaire.
Vous devriez faire usage de la OpenMP
reduction
clause dex
ety
:Avec
reduction
chaque thread s'accumule son propre somme partielle dansx
ety
et à la fin, toutes les valeurs partielles sont additionnées afin d'obtenir les valeurs finales.Voir - superlinear speed-up 🙂
x
ety
ont été utilisés pour autre chose. J'ai réalisé plus tard que c'était en réalité une réduction de lui-même.x,y
sontdouble
tableau? Puisreduction
serait de faire une copie pour chaque thread, qui serait à la consommation n fois de mémoire, puis version de série, non?essayons de comprendre comment paralléliser simple boucle for en utilisant OpenMP
supposons que nous avons
3
threads disponibles, c'est ce qui va se passertout d'abord
et enfin
Ce que vous pouvez réaliser au plus(!) est une accélération linéaire.
Maintenant, je ne me souviens pas qui est qui avec le temps à partir de linux, mais je vous suggère d'utiliser le temps.h ou (en c++ 11) "chrono" et de mesurer l'exécution directement à partir du programme. Meilleur pack de l'ensemble du code dans une boucle, l'exécuter 10 fois et la moyenne pour obtenir env exécution par le prog.
En outre, vous avez de l'omi un problème avec x,y - qui n'adhèrent pas à le paradigme de la localité des données de la programmation parallèle.