Sources du parallelisme
Transcription
Sources du parallelisme
Master Info Parallélisme et Répartition Françoise Baude Université de Nice Sophia-Antipolis UFR Sciences – Département Informatique [email protected] web du cours : deptinfo.unice.fr/~baude Septembre 2009 Chapitre 1 : Introduction générale Chapitre 2 : Paradigmes de programmation parallèle 1 Plan 1. 2. 3. 4. 5. Les différentes Sources de parallélisme Le parallélisme de données Le parallélisme de contrôle Modèles de langages parallèles Petite introduction à OpenMP 2 1 1. Les différentes sources de parallélisme Savoir identifier les formes de //sme Exploitation du parallélisme dans une application peut provenir de plusieurs sources Plein de Données a traiter de la même manière Ex: Exploité par les ordinateurs // « SIMD » Appelé Parallélisme de Données Plein/plusieurs de taches indépendantes sur données différentes Ex: Exploité par les ordinateurs // « MIMD » Appelé Parallélisme de Contrôle Flot de données selon une séquence de traitement Ex: Exploité par les processeurs (pipeline) Appelé Parallélisme de Flux 3 Exemple [Gengler/Ubeda/Desprez] (1) Pour i=0 à (n-1) faire vv[i]=a + b.v[i]2 + c.v[i]3 + d.v[i]4 + e.v[i]5 + f.v[i]6 + g.v[i]7 finPour formule avec v[i] n’interfère pas avec celle avec v[j], i ≠ j Extraction de parallélisme issu des n données : Pour i=0 à (n-1) faire_en_parallele (hyp. sur n proc ! ) vv[i]=a + b.v[i]2 + c.v[i]3 + d.v[i]4 + e.v[i]5 + f.v[i]6 + g.v[i]7 finPour Accélération (théorique) du calcul séquentiel d’un facteur n 4 2 Graphe sous-jacent, taches et liens (1) local ev=v[0] ev=a+b.ev2+ c.ev3+d.ev4+ e.ev5+f.ev6+ g.ev7 vv[0]=ev local ev=v[1] ev=a+b.ev2+ c.ev3+d.ev4+ e.ev5+f.ev6+ g.ev7 vv[1]=ev local ev=v[2] ev=a+b.ev2+ c.ev3+d.ev4+ e.ev5+f.ev6+ g.ev7 vv[2]=ev ……. local ev=v[n-1] ev=a+b.ev2+ c.ev3+d.ev4+ e.ev5+f.ev6+ g.ev7 vv[n-1]=ev ……. Largeur du graphe « n »: degré d’accélération (théorique) du calcul séquentiel Point de Synchronisation (implicite) « fin pour » Profondeur du graphe O(1): complexité en temps parallèle Vecteur vv est dispo 5 Remarques générales Granularité tache ? Doit être suffisante pour masquer le surcout de création des taches (et aussi des threads) Graphe permet de voir le //sme maxi Mais en réalité, souvent moins de proc. ! Ordonnanceur efficace de taches sur les threads sinon qui peut délimiter les taches en fonction des proc. dispo? Compilateur (parallélisation auto.) Ou bien c’est le programmeur Hyp. sur p processeurs, chaque proc. d’identifiant idproc Є [0..p-1] exécute : ind =idproc * (n / p) Pour i=ind à ind + n/p – 1 faire vv[i]=… finPour 6 3 Exemple [Gengler/Ubeda/Desprez] (2) Extraction de parallélisme en délimitant des taches de même granularité si possible a + b.v[i]2 + c.v[i]3 + d.v[i]4 + e.v[i]5 + f.v[i]6 + g.v[i]7 =(a+ b.v[i]2+c.v[i]3)+ v[i]4 *(d+ e.v[i] + f.v[i]2 + g.v[i]3) + y x pour chaque itération i : * z 3 taches Parallèles: input=v[i], output=(calcul de la tache) Mais qui doivent s’attendre pour exécuter le + et le * Pour i=0 à (n-1) faire taches_paralleles : Accélération (théorique) du calcul séquentiel d’un facteur 3 x = a + b.v[i]2 + c.v[i]3 y = d+ e.v[i] + f.v[i]2 + g.v[i]3 z = v[i]4 fin taches_paralleles vv[i]= x + z * y finPour 7 Graphe sous-jacent, taches et liens (2) i -1 local ev ev=v[i] x=a+b.ev2+ c.ev3 local ev=v[i] z=ev4 local ev=v[i] y=d+e.ev+ f.ev2+g.ev3 z y x vv[i]=x+z*y Element vv[i] dispo « Fausse » dépendance: Uniquement là parce que FinPour local ev ev=v[i+1] x=a+b.ev2+ c.ev3 Largeur du graphe « 3 »: degré de //sme, facteur d’accélération du calcul séquentiel Profondeur du graphe O(1) * n = O(n) complexité en temps parallèle local ev=v[i+1] z=ev4 z local ev=v[i+1] y=d+e.ev+ f.ev2+g.ev3 y x vv[i+1]=x+z*y ……. Element vv[i+1] dispo i+2 Vecteur vv est dispo 8 4 Exemple [Gengler/Ubeda/Desprez] (3) Extraction de parallélisme en exprimant un flux Nécessité de reformuler ! a + b.v[i]2 + c.v[i]3 + d.v[i]4 + e.v[i]5 + f.v[i]6 + g.v[i]7 = a + v[i]*(0+v[i]*(b+v[i]*(c+v[i]*…(f+v[i]*(g+v[i]*0))…))) pas de facteur en v[i] v[i] v[i] a X v[i] v[i] 0 b c c+v[i]*(Y) X v[i] v[i] … f Y f+v[i]*(g) v[i] v[i] g 0 g+v[i]*0 X Accélération (théorique) du calcul séquentiel d’un facteur = nombre étages du pipeline, ici 8 (si vecteur v suffisamment long, voir TD1) coeff coeff + X*Y Y 9 2. Le parallélisme de données Parallélisme de données: map/reduce (1) Généralement bien adapté à une structure de données (« collection » de données ou de collections) De grande taille => c’est la source de //sme ! Régulière => le degré de //sme dépend juste de la taille de la donnée, et non de sa valeur Ex. classiques: vecteur, matrice, tableau Opérations habituelles : map et reduce 1. Appliquer un traitement similaire à chaque élément, de manière indépendante, afin de transformer la donnée// Pattern « Map » (terminologie prog. Fonctionnelle), ou alpha Traitement: fonction f(x_i) -> y_i, pour i quelconque Appliquer f sur chaque élément x_i afin de calculer/transformer la donnée globale X en Y : f(X) -> Y Pas de dépendance entre les traitements élémentaires, donc, « map » est 1 opération globale naturellement parallélisable. x0 x1 x2 x3 x4 x5 x6 x7 y0 y1 y2 y3 y4 y5 y6 y7 10 5 Parallélisme de données: map/reduce (2) 2. Calculer une valeur unique en combinant (réduisant) l’ensemble des x_i -> nouvelle donnée Pattern « Reduce » (terminologie prog. Fonctionnelle), ou beta Traitement: fonction binaire (pas forcément commutative), associative g(x, y) -> z Appliquer g de sorte que chaque élément x_i de la donnée globale soit pris en compte exactement une fois Calcul parallèle engendre des taches dépendantes 2 à 2 x0 log2 n étapes Degré //sm maxi: n/2 x1 x2 z01 x3 x4 z23 x5 x6 z45 x7 z67 z4567 z0123 z01234567 11 Map et reduce Utilisés ensemble: Un potentiel énorme ! Prouvable que tout calcul qui forcement, consiste à travailler sur des données peut s’exprimer en un enchainement séquentiel (composition de fonctions) de maps et reduces sur ces données Le tout est de trouver les bons operateurs f, g ! Ex. (partiel) multiplication de deux matrices By1 A1x + * * * * * = ………. En // pour tous les x Є [1..n] et y [1..n]: // 1)Exécuter un produit vecteur*vecteur (chaque produit est un map sur vect) 2) Puis réduire par + en un scalaire * * * * // ….. + 12 6 Multiplication matrice map/reduce Une version pas purement « fonctionnelle » ! En // pour tous les x Є [1..n] et y [1..n]: 1)Exécuter un produit vecteur*vecteur (chaque produit est un map sur vect) 2) Puis réduire par + en un scalaire Pour i=0 à (n-1) faire_en_parallele Pour j=0 à (n-1) faire_en_parallele mat[i,j] = reduce(+, map( *, A_[i,…], B[…,j]) ) finPour finPour Une version purement « fonctionnelle » •Une matrice = collection (linéaire, représentation à plat) de n vecteurs •2 matrices M1, M2 combinées en un produit scalaire de leurs vecteurs respectifs en ligne et en colonne (une combinaison complexe de map et reduce): on obtient une collection [ (Ligne1_M1, Colonne1_M2), (Ligne1_M1, Colonne2_M2), … , (Lignen_M1,Colonnen_M2)] => problème difficile: générer, stocker cette var. intermédiaire En // pour toutes les paires de cette collection => c’est un map dont la fonction est : 1) un produit vecteur*vecteur, ce produit est lui-même exprimé comme un map dont la fonction est un * entre chaque élément scalaire de chaque vecteur -> un nouveau vect. suivie 2) d’une réduction de ce nouveau vect. par +, scalaire qui remplace la paire 13 3. Le parallélisme de contrôle Décomposition selon flot de contrôle Découpage fondé sur le ‘flot de contrôle’ du programme afin de délimiter des taches: branchements (2 taches), boucles (1 tache par [1..x] tours de boucle), fonctions (1 tache par appel) (ex: lges // fonctionnels !) Manuel : découpage arbitraire d’une section de code séquentielle (profitant éventuellement du flot des données) Bien adapté si de nombreuses taches engendrées ! : De granularité (quantité de travail) similaire Pas d’attente inutile due à une tache lente Suffisamment grosses pour masquer surcout engendré Ayant le moins de dépendances de données entre elles 14 7 Diviser « pour régner » (ici : « pour paralléliser ») / Divide and Conquer Fondé sur décomposition (souvent) récursive du problème à résoudre en problèmes (si possible) similaires mais plus petits Principe: Découper le problème (si assez gros) en sous-problèmes résoudre tous les sous problèmes en // Etape bloquante pour combiner leurs résultats Pattern algorithmique bien adapté pour profiter de la source de parallélisme « contrôle » beaucoup de taches, et dynamique 15 Programmation de la répartition des taches : devient le fil de contrôle! On ne connaît pas à l’avance le nombre de CPUs disponibles le nombre de taches qui va être généré par l’exécution => la gestion, le contrôle de tout ceci est très complexe Le programme parallèle est organisé en fonction d’une stratégie afin de mieux piloter comment engendrer et répartir des taches Pattern Maitre / esclaves Pattern Sac de taches (« vol » de taches) … généralisation à des squelettes (schémas tout prêts et personnalisables) : ferme, pipeline, M/E, fork/join 16 8 4. Modèles de langages parallèles Modèle de programmation, modèle d’exécution 17 Ambivalence des modèles : exécution ou programmation ? Les langages de programmation parallèle sont parfois aussi des langages (bas niveau) pour l’exécution :=( 18 9 Types de langages // (1) Langages de programmation // implicite Modèle séquentiel plus parallélisation automatique: Analyse des dépendances de données par un compilateur ‘parallélisant’ Difficile Revient très à la mode avec le multi-coeur Le runtime du langage gère entièrement les activités parallèles Le programmeur ne spécifie rien quant au placement et ordonnancement des taches, et manière de répartir les données sur les taches (si modèle d’accès mémoire sous-jacent est réparti) 19 Types de langages // (2) Langages de programmation // explicite Le programmeur est responsable de la parallélisation: Décomposition en taches Placement des taches Gestion Communication et synchronisation Plusieurs classes de langages: Directives de contrôle sur les boucles, délimitation de régions de code parallèle (ex: OpenMP) Distribution de (grandes) structures de données: ex: High Performance Fortran => placement données induit taches // Modèles distribués (répartis): Parallel Virtual Machine , Message Passing Interface, ProActive 20 10 5. Petite introduction à OpenMP Va nous permettre d’exploiter toutes les formes de parallélisme de contrôle En supposant un modèle d’exécution à espace d’adressage unique 21 22 11 OpenMP: Shared Memory Application Programming Interface ► Multiplatform shared memory multi-threads programming ► Compiler directives, library routines, and environnement variables ► For C++ and Fortran ► Cours en ligne sur www.openmp.org ActiveEon Training March 08 23 OpenMP: General Concepts ► An OpenMP program is executed by a unique process ► This process activates threads when entering a parallel region ► Each thread executes a task composed by several instructions ► Two kinds of variables: Local variables Shared variables Thread Program Parallel region Process Set of instructions Private Shared ActiveEon Training March 08 24 12 OpenMP ► The programmer has to introduce OpenMP directives within his code fork parallel region ► When program is executed, a parallel region will be created on the “fork and join” model join ActiveEon Training March 08 25 OpenMP: General Concepts 0 1 ActiveEon Training March 08 3 Nb. Tasks Time ► An OpenMP program is an alternation of sequential and parallel regions ► A sequence region is always executed by the master task ► A parallel region can be executed by several tasks at the same time 2 26 13 OpenMP: General Concepts ► A task is affected to a processor by the Operating System Task Manager Processors ActiveEon Training March 08 27 28 14 OpenMP: Work-sharing Concepts X=a+b Do i= … …….. ………. End do Looplevel parallelism Call sub(..) call sub(..) do i= .. end do Parallel sections Parallel procedure (orphaning) ActiveEon Training March 08 29 OpenMP: Synchronization Concepts ► Concurrency problems ► The need of task synchronization ActiveEon Training March 08 a=2 b=3 S=0 ……… ………. S=? S=6 S=12 Do i= … S=S+a*b End do 30 15 31 32 16 33 OpenMP Basics: Parallel region ► inside a parallel region: by default, variables are shared all concurrent tasks execute the same code Program parallel use OMP_LIB implicit none real ::a logical ::p a=9999. ; p= false. !$OMP PARALLEL !$ p = OMP_IN_PARALLEL() print *, “A value is :”,a & “; p value is: ”,p !$OMP END PARALLEL ► there is a default synchronization barrier at end program parallel the end of a parallel region > export OMP_NUM_THREADS=3; a. out; > A value is 9999. ; p value is: T > A value is 9999. ; p value is: T > A value is 9999. ; p value is: T ActiveEon Training March 08 34 17 OpenMP Basics: Parallel region Program parallel By using the DEFAULT use OMP_LIB implicit none clause one can change the real ::a a=9999. default status of a variable !$OMP PARALLEL DEFAULT(PRIVATE) a=a+10. within a parallel region print *, “A value is : ”,a !$OMP END PARALLEL If a variable has a private end program parallel status (PRIVATE) an instance of it (with an undefined value) will exist in the stack of each task. a=9999 > export OMP_NUM_THREADS=3; a. out; a=10 a=10 > A value is : 10 a=10 > A value is : 10 > A value is : 10 ActiveEon Training March 08 35 OpenMP: Synchronizations Automatic update ► The ATOMIC directive guarantees that a shared variable is read and modified by a single task at a given moment x time=1 x x=f(x,exp) time=0 time=2 x ActiveEon ActiveEon Training Training MarchMarch 08 08 36 18 OpenMP : Synchronizations Critical Region program parallel ► defined with the CRITICAL implicit none integer :: s, p directive s=0 ; p=1 !$OMP PARALLEL !$OMP CRITICAL ► generalization of ATOMIC s = s + 1 p = p * 2 directive !$OMP END CRITICAL !$OMP END PARALLEL ► tasks in the critical region print *, "s=", s, " ; p=", p end program parallel are executed in an undeterministic order but one by one. > xlf_r ... -qsmp=omp prog.f90 > export OMP_NUM_THREADS =4 ; a.out > s= 4 ; p= 16 ActiveEon ActiveEon Training Training MarchMarch 08 08 37 38 19