Compte Rendu de Calcul Parallèle Erik Pernod & Rebecca Bonnet Le but de ce TP est d étudier une résolution d équation aux dérivées partielles (EDP) afin de montrer d une part l efficacité et l utilité du calcul parallèle et, d autre part, de comparer l utilisation d OpenMP et de MPI. I Etude du problème Où L EDP que nous devons résoudre est la suivante : et k=k(x,y) et f=f(x,y). Ω Ω Le domaine de calcul est le carré unité. On décide d utiliser la méthode des différences finies afin d étudier ce problème. On exprime par différences finies ce qui nous donne l équation :, 2,,, 2,, ²,,, On décide d utiliser la méthode de Jacobi car la méthode de Gauss est peu parallélisable. En effet, les algorithmes de montée et de descente nécessitent l utilisation des termes en i et i+1 (ou i-1) ce qui rend difficile la séparation des calculs. On sépare donc A en 3 matrices : A = D + L + U Où D est une matrice diagonale, L, une matrice triangulaire inférieure et U, une matrice triangulaire supérieure. On obtient le système linéaire à une inconnue :
II Résultats Nous allons donc lancer cet algorithme avec et sans méthode de parallélisation. Dans le cas où on parallélise le problème, nous allons tout d abord utiliser Open MP puis MPI. II.1 Open MP vs Séquentiel Le principe d OpenMP est de répartir le calcul des opérations sur plusieurs processeurs. Le programme est codé «normalement», on ne fait appel à la parallélisation que pour des opérations ponctuelles (addition, multiplication etc.). Généralement, on parallélise des boucles. Le schéma suivant illustre bien la méthode : On remarquera deux choses : Premièrement, à la fin de chaque région parallèle, il est nécessaire d attendre la fin des calculs répartis sur les différents processeurs pour continuer le programme (fin de la boucle). Deuxièmement, la librairie OMP ainsi que ses commandes sont des commentaires donc le programme est entièrement exécutable, tel qu il est, en séquentiel. N=M 1 1 25 4 Sans parallèle,46,3,15 1,5 1,483,15 26,32 25,874,3 Parallèle 1 Proc,1,1 21,2 21,2 6,92 6,92 Parallèle 2 Procs,7,9,6 1,9 21,9 61,84 Compteur Speed Up : 1=>2 procs 1,42 83 1,83 3727 1,94 1183 15211
En observant le speed-up, on peut conclure que la parallélisation est efficace. En effet, l accélération est «normale» : le speed up tend vers le nombre de processeurs (2) tout en restant inférieur. Les données récupérées pour N=4 sont sûrement erronées ce qui est probablement dû à une surcharge de calcul de Bigmath (pour les calculs en parallèle) ou à un problème de codage (ce qui expliquerait le fait que le programme de compile pas en séquentiel). On calcul le speedup à l aide de : t(1)= temps pour un processeur t(p)= temps pour 2 processeurs On constate bien que le speedup converge vers 2. On peut donc en conclure que le programme est bien parallélisable. II.2 MPI vs Séquentiel Contrairement à OpenMP, la parallélisation en MPI nécessite une syntaxe totalement différente du programme codé en séquentiel. Cette méthode de travail nécessite une réflexion préalable avant de commencer à programmer. Par exemple, dans notre cas, nous avons décidé de programmer le problème pour l effectuer sur deux processeurs. De ce fait, notre vecteur de taille n devra être décomposé en deux vecteurs. Du coup, au niveau de la programmation, on initialisera un vecteur de taille n/2. Il faut bien comprendre que l on écrit qu un seul code qui sera compilé simultanément sur deux processeurs, chaque processeur traitant la moitié des données. Remarque : Dans certains cas, les données envoyées sur chacun des processeurs ne doivent pas être traitées exactement de la même manière. On a donc recours à des boucles if afin de préciser à chacun des processeurs ce qu il doit faire. Dans notre problème, le calcul de la température dans chaque maille nécessite la connaissance des valeurs des mailles voisines. Il faut donc, au moment où on sépare le vecteur en deux, récupérer les données situées de part et d autre de la césure et de les intégrer dans des lignes de buffer de chacun des deux vecteurs créés. Décomposition du maillage : L L 1 M 1 L L 1 M M on décompose la matrice en 2 vecteurs. M O N M 1 1 1 x 1 1 M N O M 1 M 1 L L 1 M M la composante x sert de buffer. L L 1 x Il y a en réalité n composantes x, pour stocker une ligne entière de la matrice en mémoire.
Résultats : N=M 15 1 25 4 Sans parallèle Parallèle 2 Procs PC,46,3,15 1,5 1,483,15 26,32 25,874,3 1,58,4,7 4,417,7,86 26,9 19,29,45 57,19,35,3 Parallèle 2 Procs Bigmath,3,2,2,9 1,2,2 15,767 19,29,5 4,12 79,2,14 Compteur 83 372 11825 15311 Speed Up,15 1,6 1,75 Quand on n est pas connecté à Bigmath, on ne fait que simuler des doubles processeurs, qui n existent pas physiquement, ce qui a pour conséquence un nombre de bugs assez important. Lorsque l on utilise Bigmath, ce problème est résolu. Les bugs rencontrés sont : - Une impossibilité d exécuter le programme pour une valeur N=M supérieur à 35 alors que le programme OpenMP et mpi tourne sur Bigmath. On constate à nouveau que le speedup converge vers 2 mais moins vite que pour l OpenMP.
II.3 OpenMP vs MPI N=M OMP 2Procs Speed Up OMP MPI 2Procs Speed Up MPI 15 1 25 4,7,9,6 1,9 21,9 1,42,3,2,2 1,83,9 1,2,2 1,94 15,767 19,29,5 61,84 4,12 79,2,14,15 1,6 1,75 On peut donc constater que la parallélisation est tout d abord meilleur par le langage OpenMP puis par la suite, lorsqu on dépasse une taille de N=M=3 le langage MPI devient meilleur. Mais ceci uniquement sur Bigmath. On peut supposer que la simulation de doubles processeurs n est pas aussi efficace que de vrais processeurs en parallèle. Ce qui paraît logique. On constate néanmoins que les valeurs de speedup de OpenMP sont meilleurs que celles du MPI. Comme nous l avons expliqué le langage OpenMP peut être compilé comme du séquentiel, alors que le MPI ne peut pas. Cela peut expliquer les différences de speedup lorsqu on passe d un à deux processeurs. Il n a pas été possible de pousser le programme au delà de 4 itérations, ou alors uniquement en mpi sur Bigmath. Ce qui rendait impossible les comparaisons.
Voici quelques petites remarques sur l optimisation du codage du programme pour une application en parallèle : Il est préférable de travailler sur des vecteurs plutôt que sur des matrices. En effet, même si le remplissage des vecteurs représente plus d opération que le remplissage d une matrice, le programme sera plus rapide. L explication est la suivante : Lors d un remplissage d un vecteur, à partir de la première composante, le processeur alloue automatiquement de la mémoire cache pour les n composantes suivantes. Alors que lors d un remplissage d une matrice, seules les composantes de la première ligne se voient alloue une place dans la mémoire cache. Le passage à la ligne suivante réinitialise l opération. L utilisation de double boucle (sur i puis sur j par exemple), ou de rang supérieur peut être optimisée. Exemple : Dans le premier cas, pour une valeur de i, on calcul «i* n» m fois (à chaque itération de j) alors que dans le deuxième cas, le calcul «i*n» est effectué qu une seule fois. Il s agit donc d un gain de m*n opérations. Ce qui peut devenir non négligeable pour de gros programmes. Boucle non optimisée For(i= ; i<n ; i++) For(j= ; j<m ; j++) U[ j+ i*n] = 1 ; Boucle optimisée Int in= ; For(i= ; i<n ; i++) in=i*n; For(j= ; j<m ; j++) U[ j+ in] = 1 ; III Conclusion A travers ce petit exemple, nous avons pu voir les possibilités et l importance des langages de programmation en parallèle. En effet, même pour des calculs simples, s ils deviennent vraiment nombreux, la différence de temps de calcul peut vite devenir un paramètre à ne pas négliger. Nous avons donc constaté que le langage OpenMP est préférable pour des petits programmes comportant que des boucles à paralléliser. Alors que le MPI qui demande une certaine réflexion préalable, est préférable pour des grosses applications.