Programme de formation en G´enie Par Simulation
Introduction ` a la programmation parall` ele
Avec OpenMP et MPI
Guillaume Emond
Polytechnique Montr´eal Montr´eal, QC
Novembre 2016
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
4 Conclusion
Loi d’Amdahl
La loi d’Amdahl permet de calculer l’acc´el´eration th´eorique(A), obtenu en parall´elisant un programme s´equentiel, selon le nombre de processeurs (n) utilis´es et la fraction parall´elisable du code(p).
A= 1
(1−p) +p/n (1)
Il s’agit toujours d’une borne sup´erieur de l’acc´el´eration r´eelle.
API de parall´ elisation
3 niveaux de parall´ elisation
• Thread : PThread,PTh,TBB, openMP
• Processus : MPI, PVM, LINDA
• GPU : Cuda, openCL
Pourquoi openMP ou MPI ?
• OpenMP et MPI sont simples d’utilisation
• Ce sont les api les plus r´ependus dans le monde scientifique
• Gratuits et portables
Processus
Un processus est un programme en cours d’ex´ecution qui est constitu´e de :
• un num´ero d’identification
• un espace d’adressage
• un ´etat (´Elu, Prˆet, Bloqu´e)
• une priorit´e
• une liste d’instructions (Compteur Ordinal)
• descripteurs de fichier Figure–Espace d’adressage d’un
Thread
• Un mˆeme processus a la possibilit´e d’avoir plus d’un fil d’ex´ecution (stack).
• Ces fils d’ex´ecution partagent les ressources du processus.
• Chaque thread poss`ede :
• un identificateur
• sa pile d’ex´ecution
• son compteur ordinal
• un ´etat
Figure– Multithreaded process
Avantages threads vs processus
• Le partage des ressources entre threads est beaucoup plus facile et efficace que pour les processus.
• Probl`emes de concurrence des ressources.
• La cr´eation et les changements de contexte entre threads est beaucoup plus rapide.
• Les threads ne s’appliquent pas aux architectures `a m´emoire distribu´ee.
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
4 Conclusion
Open Multi-Processing
• Programmation en m´emoire partag´ee
• API C,C++ et Fortran.
• Disponible sur Linux, Unix, Mac OS X, Microsoft Windows et Solaris (www.openmp.org)
• Permet de progressivement parall´eliser un programme s´equentiel sans restructurer l’enti`eret´e du programme.
Quelques mod` eles
Mod` ele d’´ execution
• ”Fork-Join”
• Open mp consiste `a ins´erer des blocs parall`eles dans un
programme s´equentiel.
• Possibilit´e d’avoir des r´egions parall`eles imbriqu´ees.
Mod` ele de m´ emoire
• Variables partag´ees.
• Variables priv´ees.
Syntaxe
C/C++ : #pragma omp directive [clause]
Fortran : !$OMP DIRECTIVE [CLAUSE]
: !$OMP END DIRECTIVE [CLAUSE]
• Directives : parallel, for (parallel for), sections (parallel sections), single, critical, atomic, master, target, simd...
• Clauses : shared, private, firstprivate, lasprivate, default, reduction, copyin, if, ordered, schedule, nowait, safelen, linear, aligned, collasped, device, map...
• Les clauses disponibles pour chaque directive peuvent changer.
Fonctions de support : threads
• omp (set/get) num threads : sp´ecifie/retourne le nombre de threads.
• omp get max threads : retourne le nombre maximal possible de threads.
• omp get thread num : retourne le num´ero du thread courant.
• omp get num proc : retourne le nombre de processeurs disponibles.
• omp in parallel : pour savoir si on se trouve dans une r´egion parall`ele.
• omp get wtime : temps ´ecoul´e en secondes par thread.
• omp get wtick : temps ´ecoul´e en cycle d’horloge par thread.
Fonctions de support : threads
• omp (set/get) nested : permission d’avoir des r´egions parall`eles imbriqu´ees.
• omp (set/get) set max active levels : profondeur maximale d’imbrication
• omp get active level : retourne la profondeur courante de la r´egion parall`ele imbriqu´ee.
• omp stacksize : retourne la taille des piles pour les threads.
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
4 Conclusion
Parallel
• Cr´eation des fils d’ex´ecution au d´ebut de la section parall`ele.
• Le nombre de threads cr´e´es est g´en´eralement sp´ecifi´e dans la variable d’environnementOMP NUM THREAD ou par d´efault (2 x core).
• Il y a une synchronisation `a la fin de la section.
• Chaque thread ex´ecute les instructions dans le bloc parall`ele mais agit diff´erement selon son identificateur.
Exemple : Parallel
// H e l l o W o r l d p a r a l l e l
# i n c l u d e < s t d i o . h >
# i n c l u d e < omp . h >
int m a i n( int argc, c h a r **a r g v ) {
#p r a g m a omp p a r a l l e l {
int r a n k= o m p _ g e t _ t h r e a d _ n u m() ; int s i z e= o m p _ g e t _ n u m _ t h r e a d s() ;
p r i n t f( " H e l l o w o r l d ! I ’ m % d of % d \ n ",rank, s i z e ) ; }
r e t u r n 0;
}
export OMP NUM THREADS=4 gcc –fopenmp -o HelloWorld HelloWorld.c ./HelloWorld
Hello world ! I’m 0 of 4 Hello world ! I’m 1 of 4 Hello world ! I’m 3 of 4 Hello world ! I’m 2 of 4
For
• Parall´elisation d’une boucle for (si chaque it´eration est ind´ependante des autres).
• Doit ˆetre appel´e depuis un environnement parall`ele ou avec omp parallel for.
• Chaque thread s’occupe d’un sous-intervalle de la boucle.
• Plusieurs types de division des sous-domaines possibles : static, dynamic, guided ou auto.
Exemple : for
// f o n c t i o n e f f e c t u a n t la m o y e n n e de c h a q u e e l e m e n t s a v e c s e s v o i s i n s d i r e c t e s // o u t p u t [ 1 . . . n ]
// i n p u t [ 0 . . . n ]
int p a r a l l e l A v e r a g e(d o u b l e* output, c o n s t d o u b l e* input, c o n s t int l e n g t h) {
#p r a g m a omp p a r a l l e l for
for (int i=1; i<length-1; i++) {
o u t p u t[i-1] = (i n p u t[i-1] + i n p u t[i] + i n p u t[i+ 1 ] ) /3;
} r e t u r n 0;
}
Single et Sections
• Single permet d’encapsuler un bloc d’instructions qui ne sera ex´ecut´e que par un seul thread.
• Sections permet de s´eparer des tˆaches diff´erentes et de les ex´ecuter respectivement par 1 seul fil d’ex´ecution.
• Le thread qui ex´ecutera une section ou le single est al´eatoire.
• La directive master permet de faire un single en garantissant que le bloc sera ex´ecut´e par le thread parent (id=0).
Exemple :Single et Sections
Sections
# p r a g m a omp p a r a l l e l { f u n c t i o n _ 0() ;
#p r a g m a omp s e c t i o n s{ f u n c t i o n _ 1() ;
#p r a g m a omp s e c t i o n{ f u n c t i o n _ 2() ; }
#p r g m a omp s e c t i o n{
f u n c t i o n _ 3() ; f u n c t i o n _ 4() ; }
} }
Single
# p r a g m a omp p a r a l l e l {
#p r a g m a omp for /* b l o c p a r a l l e l 1 */
#p r a g m a omp s i n g l e{
/* b l o c s e q u e n t i e l */
}
/* b l o c p a r a l l e l 2 */
}
Autres directives
• omp task
• omp taskloop
• omp taskloop simd
• omp simd / declare simd
• omp target / declare target
• omp teams
• etc...
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
4 Conclusion
shared, private...
La port´ee des variables doit ˆetre d´efinie pour chaque r´egion parall`ele.
• shared : une seule copie de la variable pour tous les threads.
• private : chaque thread poss`ede une copie de la variable. La variable vis´ee est ind´efinie avant et apr`es la r´egion.
• firstprivate : variable priv´ee initialis´ee avec la valeur en entr´ee.
• lastprivate : la valeur de sortie est donn´ee par le thread qui effectue la derni`ere it´eration de la boucle.
• copyprivate : permet de propager une variable d’une r´egion single aux autres threads
shared, private
// P r o d u i t M a t r i c e - v e c t e u r
# p r a g m a omp p a r a l l e l for d e f a u l t( n o n e ) p r i v a t e ( i , j , sum ) s h a r e d ( m , n , a , b , c ) for (i=0; i<m; i++) {
sum = 0 . 0 ;
for (j=0; j<n; j++)
sum += b[i][j]*c[j];
a[i] = sum;
}
reduction
• Pour les boucles for.
• Permet de sp´ecifier une variable pour une r´eduction avec un op´erateur commutatif et associatif.
+,∗,&&,k,
// f a i r e u n e s o m m e d e s e l e m e n t s d ’ un v e c t e u r .
d o u b l e s o m m e(d o u b l e* a, int s i z e) { int i;
d o u b l e sum =0;
#p r a g m a omp p a r a l l e l for p r i v a t e(i) r e d u c t i o n(+:sum)
for(i=0; i<s i z e; i++) {
sum += a[i];
}
r e t u r n sum;
}
collapse
• Dans un omp for, seule la premi`ere boucle est parall´elis´ee.
• Avec la clause collapse, des boucles imbriqu´ees seront consid´er´ees comme une grande boucle.
// f a i r e u n e s o m m e d e s e l e m e n t s d ’ u n e m a t r i c e d o u b l e s o m m e(d o u b l e* a, int width, int h e i g h t) {
int i,j;
d o u b l e sum =0;
#p r a g m a omp p a r a l l e l for p r i v a t e(i,j) c o l l a p s e(2) r e d u c t i o n(+:sum) for(i=0; i<s i z e; i++) {
for(j=0; j<s i z e; j++)
sum += a[i][j];
}
r e t u r n sum;
}
if
• Le bloc parall`ele attach´e au if ne s’ex´ecute que si la condition est vraie.
• Dans le cas contraire, la r´egion s’ex´ecute en s´equentiel.
• Si la taille du probl`eme est petite, il est parfois pr´ef´erable de rester en s´equentiel `a cause du surcoˆut de opemMP.
nowait
• Permet d’enlever la barri`ere implicite `a la fin d’un bloc. Ainsi l’ex´ecution de deux r´egions parall`eles distinctes peuvent se chevaucher.
• La directive omp barrier permet de synchroniser tous les threads de la r´egion.
# p r a g m a p a r a l l e l s h a r e d ( a , b , c , y , z ) { #p r a g m a omp for s c h e d u l e(s t a t i c) n o w a i t
for (int i=0; i<n; i++) c[i] = (a[i] + b[i]) / 2 . 0 ;
# p r a g m a omp for s c h e d u l e (s t a t i c) n o w a i t
for (int i=0; i<n; i++) z[i] = c[i]*c[i];
# p r a g m a omp b a r r i e r ;
# p r a g m a omp for s c h e d u l e (s t a t i c) n o w a i t
for (int i=1; i<=n; i++) y[i] = z[i-1] + a[i];
}
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
Probl` eme ? ? ?
# i n c l u d e < s t d i o . h >
# i n c l u d e < omp . h >
int m a i n( int argc, c h a r **a r g v ) { int N = 1 0 0 ;
d o u b l e a[N];
d o u b l e t o t a l = 0;
for(int i=0; i<N; i++) a[i]=i;
#p r a g m a omp p a r a l l e l n u m _ t h r e a d s(4) {
#p r a g m a omp for for(int i=0; i<N; i++) {
t o t a l += a[i]
} } r e t u r n t o t a l;
}
r´eponse actuelle : 3745 r´eponse attendue : 4950
critical et atomic
Afin de r´egler un probl`eme de concurrence, Il faut que l’acc`es aux donn´ees cibl´ees soit prot´eg´e soit par des verrous ou en ´etant locales.
• #pragma omp critical [name] : Une seule r´egion critique du mˆeme nom peut s’ex´ecuter en mˆeme temps. Cette directive utilise des verrous afin de prot´eger la r´egion.
• #pragma omp atomic{x operateur= expression}
# p r a g m a omp p a r a l l e l n u m _ t h r e a d s (4) { int i,j;
#p r a g m a omp for for(i=0; i<N; i++) {
#p r a g m a omp c r i t i a l{
t o t a l += a[i]
} } }
# p r a g m a omp p a r a l l e l n u m _ t h r e a d s (4) { int i,j;
#p r a g m a omp for for(i=0; i<N; i++) {
#p r a g m a omp a t o m i c{
t o t a l += a[i]
}
Quelques conseils
• Attention aux probl`emes de concurrence. S’assurer que les fonctions appel´ees sont ”thread safe”
• Choisir des morceaux assez gros pour minimiser le surcoˆut mais assez petits pour ´equilibrer le travail de chaque thread.
• Attention `a l’odre des indices lors du parcours de matrice.
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
Message Passing Interface
• Ce n’est pas une librairie mais un standard. Il exite plusieurs impl´ementations diff´erentes (openMPI, MPICH, MVAPICH, IBM MPI, etc...)
• Habituellement support´e en C,C++ et Fortran et sur la plupart des syst`emes d’exploitations.
• Programmation sur architechture `a m´emoire distribu´ee.
• Un programme MPI est constitu´e de processus autonomes qui ex´ecutent leur code respectif (MIMD) dans leur espace d’adressage respectif. MPI est un environnment servant uniquement `a la communication entre ces processus.
Syntaxe
C/C++ : ierr = MPI Xxxx(parametre1, ...)
ierr = MPI Bsend(&buf,count,type,dest,tag,comm) Fortran : MPI XXXX(parametre1, ..., ierr)
MPI BSEND(&buf,count,type,dest,tag,comm,ierr)
Fonctions de base
• MPI INIT : initialisation de l’environnment MPI. Il ne doit ˆetre appel´e qu’une seule fois dans le programme.
• MPI FINALIZE : terminaison des communications.
• MPI COMM RANK : retourne le num´ero du processus.
• MPI COMM SIZE : retourne le nombre de processus dans le communicateur (MPI COMM WORLD).
• MPI ABORD : terminaison de tous les processus MPI.
Hello World MPI
mpiexec ./HelloWorldMPI.c -np 4
# i n c l u d e " mpi . h "
# i n c l u d e < s t d i o . h >
int m a i n( argc, a r g v ) { int rank, s i z e;
M P I _ I n i t( &argc, &a r g v ) ;
M P I _ C o m m _ r a n k( M P I _ C O M M _ W O R L D, &r a n k ) ; M P I _ C o m m _ s i z e( M P I _ C O M M _ W O R L D, &s i z e ) ;
p r i n t f( " H e l l o w o r l d ! I ’ m % d of % d \ n ",rank, s i z e ) ; M P I _ F i n a l i z e() ;
r e t u r n 0;
}
Hello world ! I’m 3 of 4 Hello world ! I’m 2 of 4 Hello world ! I’m 0 of 4
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
4 Conclusion
Contenu d’un message Le contenu
• buffer : adresse de la variable qui est envoy´ee ou qui recevra les donn´ees.
• count : nombre d’´el´ements dans le buffer
• datatype : type de la donn´ee pass´ee dans le message. Il ne peut y en avoir qu’un seul par message. Le syst`eme peut effectuer des
conversions si n´ecessaire.
L’enveloppe
• source : L’identificateur de l’envoyeur.
• dest : L’identificateur du receveur.
• tag : Valeur enti`ere identifiant le message (possibilit´e de wildcard `a la r´eception : MPI ANY TAG).
Exemple de communication
# i n c l u d e " mpi . h "
int m a i n( int argc, c h a r *a r g v[]) {
c h a r m e s s a g e[ 2 0 ] ; int m y r a n k;
M P I _ S t a t u s s t a t u s;
M P I _ I n i t( &argc, &a r g v ) ;
M P I _ C o m m _ r a n k( M P I _ C O M M _ W O R L D, &m y r a n k ) ; if (m y r a n k == 0) { /* c o d e f o r p r o c e s s z e r o */
s t r c p y(message," Hello , t h e r e ") ;
M P I _ S e n d(message, s t r l e n(m e s s a g e) , M P I _ C H A R, 1 , 99 , M P I _ C O M M _ W O R L D) ; }
e l s e if (m y r a n k == 1) { /* c o d e f o r p r o c e s s o n e */
M P I _ R e c v(message, 20 , M P I _ C H A R, 0 , 99 , M P I _ C O M M _ W O R L D, &s t a t u s) ; p r i n t f(" r e c e i v e d :% s :\ n ", m e s s a g e) ;
}
M P I _ F i n a l i z e() ; r e t u r n 0;
}
Mode de communication
Standard, Buffered, Synchronous, Ready
• MPI XSEND(buf,count,datatype,dest,tag,comm)
1. MPI SEND : peut se comporter comme un BSEND ou SSEND selon le choix de MPI.
2. MPI BSEND : termine lorsque le message est compl`etement copi´e dans un tampon.
3. MPI SSEND : termine lorsqu’un RECV correspondant est appel´e.
4. MPI RSEND : ne peut ˆetre appel´e que si un RECV correspondant est en attente.
• MPI RECV(buf,count,datatype,source,tag,comm,status)
Termine lorsque le message est totalement copi´e. Un RECV peut terminer avant le SEND.
interblocage
// E X E M P L E 1
M P I _ C o m m _ r a n k(comm, &r a n k) if (r a n k= = 0 ) {
M P I _ B s e n d(sendbuf, count, M P I _ D O U B L E, 1 , tag1, c o m m) M P I _ S s e n d(sendbuf, count, M P I _ D O U B L E, 1 , tag2, c o m m) }
e l s e i f (r a n k= = 1 ) {
M P I _ R e c v(recvbuf, count, M P I _ D O U B L E, 0 , tag2, comm, s t a t u s) M P I _ R e c v(recvbuf, count, M P I _ D O U B L E, 0 , tag1, comm, s t a t u s) }
// E X E M P L E 2
M P I _ C o m m _ r a n k(comm, &r a n k) if (r a n k= = 0 ) {
M P I _ S e n d(sendbuf, count, M P I _ R E A L, 1 , tag, c o m m) M P I _ R e c v(recvbuf, count, M P I _ R E A L, 1 , tag, comm, s t a t u s) }
e l s e i f (r a n k= = 1 ) {
M P I _ S e n d(sendbuf, count, M P I _ R E A L, 0 , tag, c o m m) M P I _ R e c v(recvbuf, count, M P I _ R E A L, 0 , tag, comm, s t a t u s) }
SendReceive
On combine les appels send et receive afin de simplifier les ´echanges de message.Cela ´evite les risque d’interblocages.
• MPI SENDRECV(sendbuf,sendcount,sendtype,dest,sendtag, recvbuf,recvcount,recvtype,source,recvtag,comm,status)
• MPI SENDRECV REPLACE(buf,count,datatype,dest,sendtag, source,recvtag,comm,status)
Exemple : SendRecv
intrank,s i z e;
M P I _ s t a t u s s t a t u s;
f l o a t r p[2048] ,rs[2048] ,rc[ 2 0 4 8 ] ; ...
for(t=0;t<m a x _ t i m e;t++) { if(r a n k < (size-1) {
M P I _ S e n d r e c v(rc,2048 ,M P I _ F L O A T,r a n k+1 ,1 ,rs,2048 ,M P I _ F L O A T,r a n k+1 ,0 ,M P I _ C O M M _ W O R L D) ; }
if(r a n k > 0) {
M P I _ S e n d r e c v(rc,2048 ,M P I _ F L O A T,rank-1 ,0 ,rp,2048 ,M P I _ F L O A T,rank-1 ,1 ,M P I _ C O M M _ W O R L D) ; }
i t e r e _ c h a l e u r(rp,rs,rc) }
Exemple : SendRecv
intrank,s i z e;
M P I _ s t a t u s s t a t u s;
f l o a t rp[2048] ,rs[2048] ,rc[ 2 0 4 8 ] ; ...
for(t=0;t<m a x _ t i m e;t++) { if(r a n k= = 0 ) {
M P I _ S e n d r e c v(rc,2048 ,M P I _ F L O A T,r a n k+1 ,1 ,rs,2048 ,M P I _ F L O A T,r a n k+1 ,0 ,M P I _ C O M M _ W O R L D) ; i t e r e _ c h a l e u r(NULL,rs,rc)
}
e l s e i f(r a n k==(size-1) ) {
M P I _ S e n d r e c v(rc,2048 ,M P I _ F L O A T,rank-1 ,0 ,rp,2048 ,M P I _ F L O A T,rank-1 ,1 ,M P I _ C O M M _ W O R L D) ; i t e r e _ c h a l e u r(rp,NULL,rc)
}e l s e{
if(r a n k%2) { // n o e u d i m p a i r e
M P I _ S e n d r e c v(rc,2048 ,M P I _ F L O A T,rank-1 ,0 ,rp,2048 ,M P I _ F L O A T,rank-1 ,1 , M P I _ C O M M _ W O R L D) ;
M P I _ S e n d r e c v(rc,2048 ,M P I _ F L O A T,r a n k+1 ,2 ,rs,2048 ,M P I _ F L O A T,r a n k+1 ,3 , M P I _ C O M M _ W O R L D) ;
}
e l s e{ // n o e u d p a i r e
M P I _ S e n d r e c v(rc,2048 ,M P I _ F L O A T,r a n k+1 ,1 ,rs,2048 ,M P I _ F L O A T,r a n k+1 ,0 , M P I _ C O M M _ W O R L D) ;
M P I _ S e n d r e c v(rc,2048 ,M P I _ F L O A T,rank-1 ,3 ,rs,2048 ,M P I _ F L O A T,rank-1 ,2 , M P I _ C O M M _ W O R L D) ;
Exemple : SendRecv
Communication non-bloquante
Les op´erations SEND et RECV sont s´epar´ees en deux appels. Le premier permet de commencer la communication sans attendre que l’´ecriture ou la lecture soit termin´ee. Le second permet de savoir quand l’op´eration est termin´ee. Cela permet de superposer les communications et les calculs.
• MPI IXSEND(buf,count,datatype,dest,tag,comm,request)
• MPI IRECV(buf,count,datatype,source,tag,comm,request)
L’objet request contient des informations sur le mode de communication, sur l’enveloppe et le status de la communication
Communication non-bloquante
Pour compl´eter une communication, on utilise les commandes suivantes :
• MPI WAIT(request,status)
• MPI WAITANY(count,array of request,index,status)
• MPI WAITALL(count,array of request,array status)
• MPI WAITSOME(incount,array request,outcount, array index,array status)
• MPI TEST(request,flag,status)
• MPI TESTANY(count,array of request,index,flag,status)
• MPI TESTALL(count,array of request,flag,array status)
• MPI TESTSOME(incount,array request,outcount, array index,array status)
Exemple : communication non-bloquante
// C o m m u n i c a t i o n c i r c u l a i r e
# i n c l u d e < s t d i o . h >
# i n c l u d e " mpi . h "
int m a i n (int argc, c h a r* a r g v[]) {
int n u m t a s k s, rank, next, prev, buf[2] , t a g 1=1 , t a g 2=2;
M P I _ R e q u e s t r e q s[ 4 ] ; M P I _ S t a t u s s t a t s[ 4 ] ; M P I _ I n i t(&argc,&a r g v) ;
M P I _ C o m m _ s i z e(M P I _ C O M M _ W O R L D, &n u m t a s k s) ; M P I _ C o m m _ r a n k(M P I _ C O M M _ W O R L D, &r a n k) ; p r e v = rank-1; n e x t = r a n k+1;
if(r a n k == 0) p r e v = n u m t a s k s - 1;
if(r a n k == (n u m t a s k s - 1) ) n e x t = 0;
M P I _ I r e c v(&buf[0] , 1 , MPI_INT, prev, tag1, M P I _ C O M M _ W O R L D, &r e q s[ 0 ] ) ; M P I _ I r e c v(&buf[1] , 1 , MPI_INT, next, tag2, M P I _ C O M M _ W O R L D, &r e q s[ 1 ] ) ; M P I _ I s e n d(&rank, 1 , MPI_INT, prev, tag2, M P I _ C O M M _ W O R L D, &r e q s[ 2 ] ) ; M P I _ I s e n d(&rank, 1 , MPI_INT, next, tag1, M P I _ C O M M _ W O R L D, &r e q s[ 3 ] ) ; M P I _ W a i t a l l(4 , reqs, s t a t s) ;
p r i n t f(" T a s k % d c o m m u n i c a t e d w i t h t a s k s % d & % d \ n ",rank,prev,n e x t) ;
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
4 Conclusion
communications collectives
Communications collectives
• MPI BCAST(buf,count,datatype,root,comm)
• MPI GATHER(sendbuf,sendcount,sendtype, recvbuf,recvcount,recvtype,root,comm)
• MPI SCATTER(sendbuf,sendcount,sendtype, recvbuf,recvcount,recvtype,root,comm)
• MPI ALLGATHER(sendbuf,sendcount,sendtype, recvbuf,recvcount,recvtype,comm)
• MPI ALLTOALL(sendbuf,sendcount,sendtype, recvbuf,recvcount,recvtype,comm)
R´ eduction
Possibilit´e de faire une r´eduction avec des op´erations pr´ed´efinies ou d´efinies par l’usager(MPI OP CREATE).
• MPI REDUCE(sendbuf,recvbuf,count,datatype,op,root,comm)
• MPI ALLREDUCE(sendbuf,recvbuf,count,datatype,op,comm) Les op´erations pr´ed´efinies sont :
MAX,MIN,SUM,PROD,LAND,BAND,LOR,BOR,LXOR,BXOR,MAXLOC et MINLOC
Exemple : calcul de pi
// g e n e r e c o o r d o n n e e x et y
v o i d r a n d o m _ c o o r d(d o u b l e* x,d o u b l e* y) int m a i n(int argc, c h a r *a r g v[]) {
int rank, size, i e r r; M P I _ S t a t u s s t a t u s;
int r o o t = 0;
d o u b l e N _ t r y = 1 0 0 0 0 0 d o u b l e h i t _ l o c a l =0;
d o u b l e h i t _ t o t a l = 0;
i e r r = M P I _ I n i t(&argc,&a r g v) ;
i e r r = M P I _ C o m m _ s i z e(M P I _ C O M M _ W O R L D,&s i z e) ; i e r r = M P I _ C o m m _ r a n k(M P I _ C O M M _ W O R L D,&r a n k) ; for(int i=0; i< N _ t r y; i++) {
d o u b l e x,y,n o r m; r a n d o m _ c o o r d(&x,&y) ; n o r m = x*x +y*y
if (n o r m < 1) {h i t _ l o c a l++}
}
i e r r = M P I _ R e d u c e(&h i t _ l o c a l,&h i t _ t o t a l,1 ,M P I _ D O U B L E, MPI_SUM,root,M P I _ C O M M _ W O R L D)
if(r a n k == r o o t) {
d o u b l e pi = 4*h i t _ t o t a l/N _ t r y;
}
i e r r = M P I _ F i n a l i z e() ;
Figure –Calcul de pi
Autre type d’op´ eration globale
• MPI REDUCE SCATTER(sendbuf,recvbuf,recvcount, datatype,op,comm) : redistribue le r´esultat de la r´eduction
• MPI SCAN(sendbuf,recvbuf,count,datatype,op,comm) : r´eduction avec pr´efixe
• MPI EXSCAN(sendbuf,recvbuf,count,datatype,op,comm)
• MPI BARRIER(comm)
Les points importants
• Attention aux situations d’interblocage.
• Les communications non bloquantes permettent d’effectuer des calculs en mˆeme temps.
• S’assurer que les communications sont parall`eles (si possible)
Table des mati` eres
1 Programmation parall`ele
2 OpenMP Directives Clauses
Concurrences et synchronisation
3 MPI
Messages
Communications collectives
A retenir ! `
• La loi d’Amdhal.
• La diff´erence entre un thread et un processus.
• OpenMP cr´ee des groupes de threads afin d’ins´erer des blocs parall`eles dans un code.
• MPI est un standard de communication inter-processus.
• Faites attention aux probl`emes de concurrence et aux situations d’interblocages.
• Une panoplie de tutoriels sur openMPI et MPI sont disponibles sur internet.
• On retrouve les documentations officielles aux adresses suivantes : - www.openmp.org
- mpi-forum.org
questions ?
G. Emond (PolyMtl) GPS-OpenMP/MPI 2016 60 / 60