Vous pouvez faire le TP sur les machines de l'école ou sur les vôtres.
Vous aurez dans ce cas besoin des dépendances suivantes, à installer au préalable sur votre machine les paquests suivants:
Si vous êtes sur vos machines, installez les paquets ci-dessus.
Une fois fait, récupérez sur votre machine les scripts .sh dans le répertoire /pub/FISE_PDSP35/tp/tp3
.
Si vous êtes sur les machines de l'école, ouvrez un terminal et déplacez vous dans /pub/FISE_PDSP35/tp/tp3
.
Ces scripts servent à installer EZTrace et le format de trace OTF2 en local dans votre $HOME
.
Lisez les scripts *.sh
, notamment install_all.sh. Il permet de lancer les scripts d'installation d'EZTrace, opari2 et OTF2
dans un répertoire commun donné par la variable WORKING_DIR
. Vous pouvez modifier le contenu de cette variable
pour installer les sources où vous le souhaitez dans votre $HOME
.
A la fin des installations, les fichiers eztrace_otf2.env
, opari2.env
et otf2.env
sont créés. Regardez leur contenu dans $WORKING_DIR
.
A la fin du script installAll.sh
, on source ces fichiers .env
afin de mettre à jour les chemins vers les exécutables et
bibliothèques installées.
Commençons par installer ces dépendences.
Lancez le script ìnstall_all.sh
avec une valeur de WORKING_DIR
de votre choix (vous pouvez laisser la valeur par défaut)
EZTrace et la bibliothèque du format OTF2 ont normalement été installés.
Vérifiez que tout s'est bien passé en essayant la commande eztrace_avail
qui liste les modules de traçage possibles pour EZTrace.
Vous devriez avoir ici, entre autres, omp et mpi.
A chaque fois que c'est nécessaire, sourcez ces fichiers .env
afin de pouvoir utiliser EZTrace et le format OTF2 à partir de n'importe quel répertoire.
Une première étape en analyse de performance est d'évaluer la performance de base de l'application. On va s'intéresser dans cette partie à générer un speedup plot à partir d'une application OpenMP simple.
Copiez le contenu du répertoire /pub/FISE_PDSP35/tp/tp3/code/mandelbrot/
dans votre répertoire de travail.
Inspectez le contenu du répertoire mandelbrot/
.
En mathématiques, l’ensemble de Mandelbrot est une fractale calculée à partir d’un ensemble des points
du plan complexe pour lesquels la suite de nombres complexes est définie par récurrence. On vous fournit
dans le fichier mandelbrot/mandelbrot_seq.c
le code de calcul séquentiel.
Un makefile vous permet de générer
deux exécutables :
mandelbrot
) et mandelbrot_gui
). Ces deux programmes prennent en paramètre un argument qui est le nombre d’itérations dans le calcul de
la fractale. Voici un exemple pour lancer l’exécutable graphique avec 10000 itérarions :
$ ./mandelbrot_gui 10000
Examinez le code séquentiel.
Modifiez le fichier mandelbrot/mandelbrot_par.c
en insérant une directive OpenMP parallel for et une seule clause private (concernant plusieurs variables),
pour obtenir une version parallèle. Testez votre programme avec la GUI pour vérifier que vos calculs sont corrects.
Exécutez la version parallèle de l'application (sans GUI) en faisant varier le nombre de threads OpenMP
Créez un fichier .data
qui contient :
Voici un exemple de fichier :
#nbprocs tempseq tempspar
1 4.5 4.5
2 4.5 2.7
4 4.5 1.2
Ecrivez un script qui génère un plot de speedup (dans le langage de votre choix). Voici un exemple de plot.
Profiling Si vous êtes sur votre machine personnelle, utilisez le programme perf
pour vérifier quelle fonction consomme le plus de temps.
Le résultat était-il prévisible?
Dans cet exercice, on veut calculer pi par intégration numérique sur la base que \int_0^n\frac{4}{1+x^2}dx=pi
Le code dans /pub/FISE_PDSP35/tp/tp3/code/pi.c
contient un programme permettant de calculer la valeur de pi par la
méthode dite des rectangles, ou point milieu.\
On utilise donc f(x)=4/(1+x^2) comme fonction à intégrer, N comme nombre de points, et h=1/N comme pas de discrétisation de l’intervalle d’intégration $[0, 1]$.
Copier le fichier dans votre répertoire, et lisez son code attentivement.
Ce code peut être parallélisé de trois façons différentes, c'est à dire avec différentes directives dans chaque version :
pi1.c
)pi2.c
)pi3.c
)Ecrivez les trois versions parallèles du programme dans trois programmes séparés.
Pour les versions les moins performantes, améliorer leur code (sans changer le type des directives OpenMP utilisées). Vous devez obtenir des performances équivalentes pour les trois versions parallèles.
Le but de cet exercice est de générer une trace d'exécution avec EZTrace, et de la visualiser avec Vite. Reprenon le Mandelbrot parallèle précédent et traçons une de ses exécutions :
$ make clean
$ eztrace_cc gcc -fopenmp -o mandelbrot mandelbrot_par.c
$ eztrace -t openmp ./mandelbrot6_par 10000
[...]
Stopping EZTrace... saving trace
$ vite mandelbrot_trace/eztrace_log.otf2
Si vous êtes sur votre machine, vous pouvez compiler l'application avec clang
. Cela utilisera une autre instrumentation d'OpenMP à travers un autre runtime.
Danc ce cas, vous pourrez utiliser le pluging ompt
d'EZTrace :
$ make clean
$ clang -fopenmp -o mandelbrot mandelbrot_par.c
$ eztrace -t ompt ./mandelbrot_par 10000
[...]
Stopping EZTrace... saving trace
$ vite mandelbrot_trace/eztrace_log.otf2
Exécuter le prograœmme parallèle précédent et constatez qu'il y a un problème d'équilibrage de charge entre les threads dans la visualisation avec Vite. Résolvez ce problème et générez une nouvelle trace qui montre que la charge de travail est équilibrée entre les threads. Indice : la clause OpenMP schedule devrait vous permettre de résoudre ce problème
Réitérez la mesure de performance précédente en faisant varier le nombre de threads, and intégrez une mesure du temps d'exécution pour réaliser un speedup plot. Ce plot incluera deux lignes : la version parallélisée de la section précédente et la version parallèle optimisée du 1.
Pour vous entraîner encore, tracez avec EZTrace et le plugin openmp (ou ompt si vous avez clang) l'application dont le code est dans /pub/FISE_PDSP35/tp/tp3/code/fft_openmp.c
.
Récupérez le fichier /pub/FISE_PDSP35/tp/tp3/code/mat_mul_mpi.c
.
Compilez le programme avec mpicc
et lancez le sur 4 rangs MPI : mpirun -np 4 ./mat_mul_mpi
. Faites quelques tests de weak scaling (augmentez raisonnablement N),
et strong scaling pour N=1500 par exemple.
Utilisez EZTrace pour générer une trace d'exécution du programme contenant seulement la partie MPI. Pour cela, utilisez le module openmpi
d'EZTrace :
mpirun -np 4 eztrace -t openmpi ./mat_mul_mpi
. Visualisez la trace obtenue avec Vite : vite mat_mul_mpi_trace/eztrace_log.otf2
.
A priori, ce programe n'est pas ultra intéressant. Le thread maître initialise les matrices, puis envoie les données à chaque rang qui effectue le calcul sur des sous-blocs et renvoie les résultats au maître.
Néanmoins, Vite nous permet de facilement visualiser ce process.
Le programme /pub/FISE_PDSP35/tp/tp3/code/stencil/cstencil_mpi
mixe MPI et OpenMP. Utilisez EZTrace pour générer une trace d'exécution qui montre à la fois les communications MPI et les régions parallèles MPI
en traçant comme avant mais cette fois avec les deux modules EZtrace openmp et mpi.
$ eztrace_cc mpicc -o stencil_mpi stencil_mpi.c -fopenmp
$ export OMP_NUM_THREADS=4 ; mpirun -np 4 eztrace -t "openmpi openmp" ./stencil_mpi 1024
$ vite stencil_mpi_trace/eztrace_log.otf2
Essayez de comprendre la trace ainsi visualisée.
Dans ces exercices, on va prendre des programmes séquentiels, les paralléliser avec OpenMP puis analyser leur performance.
Copiez le fichier /pub/FISE_PDSP35/tp/tp3/code/dependance.c
Son code est constitué de deux boucles imbriquées.
* Après analyse du code, déterminer si les boucles sont des boucles parallèles (i.e. pas de dépendance
entre les itérations). Si on force la parallélisation des boucles, que se passe-t-il ?
* Paralléliser le code en insérant le.s directive.s OpenMP appropriée.s. Deux approches sont pos-
sibles, soit avec la directive flush, soit en utilisant les tâches OpenMP.
Attention à la synchronisation des différents threads de façon à respecter les dépendances entre les itérations.
Votre version parallèle n’est valide que si la valeur affichée de la variable norme est égale à 0.
* Réaliser l’analyse de performance de votre programme (speedup plot et traçage avec EZTrace)
Copiez le fichier `/pub/FISE_PDSP35/tp/tp3/code/dependance.c Son code est constitué de deux boucles imbriquées. * Après analyse du code, déterminer si les boucles sont des boucles parallèles (i.e. pas de dépendance entre les itérations). Si on force la parallélisation des boucles, que se passe-t-il ? * Paralléliser le code en insérant le.s directive.s OpenMP appropriée.s. Deux approches sont pos- sibles, soit avec la directive flush, soit en utilisant les tâches OpenMP. Attention à la synchronisation des différents threads de façon à respecter les dépendances entre les itérations. Votre version parallèle n’est valide que si la valeur affichée de la variable norme est égale à 0. * Réaliser l’analyse de performance de votre programme (speedup plot et traçage avec EZTrace)
Cet exercice concerne le code contenu dans le fichier /pub/FISE_PDSP35/tp/tp3/code/prod_mat.c
.
Ce programme calcule le produit de matrices C = A × B
Dans cet exercice, vous allez modifier le code en insérant les directives OpenMP adaptées, et analyser les performances du code.