Introduction à MPI Références
Transcription
Introduction à MPI Références
Introduction à MPI Daniel Etiemble [email protected] Références • R. Rabenseifner, « Introduction to MPI, University of Stuttgart, www.hlrs.de • W. Gropp, E. Lusk, A. Skjellum, « Using MPI », The MIT Press Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 2 1 Le paradigme « passage de messages » • Chaque processeur travaille sur un programme – Écrit dans un langage séquentiel (C/C++ ou Fortran) – Typiquement le même sur chaque processeur (SPMD) – Les variables de chaque processeur ont • Le même nom • Des emplacements mémoire (mémoire distribuée) et des données différentes • Toutes les variables sont privées – Communique via des routines d’envoi et de réception (passage de messages Données Programme Données Données Données Données Données Programme Programme Programme Programme Programme Réseau d’interconnexion Maîtrise Informatique 2003 3 D. Etiemble Calcul parallèle Distribution des données et du travail • La valeur de myrank est fournie par une routine de bibliothèque • Un programme d’initialisation MPI démarre le système de size processus • Les décisions de distribution sont basées sur myrank myrank=0 Données myrank=1 Données myrank=2 Données myrank=3 Données Programme Programme Programme Programme myrank= size -1 Données Programme Réseau d’interconnexion Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 4 2 Initialisation de MPI #include <mpi.h> Main (int argc, char **argv) { MPI_Init (&argc, &argv); …. • Communicator MPI_COMM_WORLD – Tous les processus d’un programme MPI sont combinés dans MPI_COMM_WORLD (prédéfini dans mpi.h) – Chaque processus a son rang dans un communicateur • De 0 • À (size – 1) – Fonctions • Rang : identifie les différents processus – Int MPI_Comm_rank (MPI_Comm comm, int *rank) • Taille : nombre de processus dans un communicateur – Int MPI_Comm_size (MPI_Comm comm, int *size) Maîtrise Informatique 2003 5 D. Etiemble Calcul parallèle Messages • Les messages sont des paquets de données entre programmes • Information nécessaire – Processus émetteur • Adresse source • Type de données source • Taille des données source – Processus récepteur • Adresse destination • Type de donnée destination • Taille du tampon destination Adresse Y Réception Y, P, t Envoi X, Q, t Adresse X Espace d’adressage local Espace d’adressage local Processus Q Processus P Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 6 3 Messages • Un message contient un certain nombre d’éléments d’un certain type de données – Type de données de base – Type de données dérivés (des types de base et de types dérivés) • Les types de données de base MPI – MPI_CHAR – MPI_SHORT, MPI_INT, MPI_LONG – MPI_UNSIGNED_CHAR, MPI_UNSIGNED_SHORT, MPI_UNSIGNED, MPI_UNSIGNED_LONG – MPI_FLOAT, MPI_DOUBLE, MPI_LONG_DOUBLE – MPI_BYTE – MPI_PACKED Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 7 Communication point à point • Forme la plus simple de passage de message • Un processus envoie un message à un autre processus • La communication a lieu à l’intérieur d’un communicateur (MPI_COMM_WORLD) • Les processus sont identifiés par leur rang dans le communicateur • Différent types de communication point à point – Envoi synchrone • L’émetteur obtient l’information que le message a été reçu – Envoi asynchrone • L’émetteur sait seulement que le message est parti. Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 8 4 Envoi – réception d’un message • Envoi – int MPI_Send (void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) – buf est le début du message avec count éléments, chacun décrit avec un type de données (datatype) – dest est le rang du processus destination dans le communicateur comm – tag est une information entière non négative transférée avec le message • Réception – int MPI_Recv (void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status) – buf, count, datatype décrivent le tampon de réception – Reçoit le message envoyé par le processus de source rank dans comm – Information de réception est récupérée dans status – Seuls les messages avec le bon tag sont reçus • Contraintes – – – – – – L’émetteur doit spécifier un rang de destination valide Le récepteur doit spécifier un rang source valide Le communicateur doit être le même Les étiquettes doivent correspondre Les types de données doivent correspondre Le tampon de réception doit être assez grand. Maîtrise Informatique 2003 Calcul parallèle 9 D. Etiemble Exemple : ping pong #include "mpi.h" #define N 50000 /* N is the number of rounds */ #define B 5000 /* B is the buffer size for the message, in bytes */ main(int argc, char *argv[]) { int myid, opponent, trips; char ball[B]; MPI_Status stat; MPI_Comm_rank(MPI_COMM_WORLD, &myid); opponent = (myid+1)%2; /* Get rank */ if (myid==1) MPI_Send(ball, B, MPI_CHAR, opponent, 0, MPI_COMM_WORLD); for (trips=0; trips<N;++trips) { MPI_Recv(ball, B, MPI_CHAR, opponent, 0, MPI_COMM_WORLD, &stat) MPI_Send(ball, B, MPI_CHAR, opponent, 0, MPI_COMM_WORLD); Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 10 5 Opérations bloquantes et non bloquantes • Les opérations sont locales (envoi d’un message, réception d’un message) • Opérations bloquantes – Les émissions d’envoi synchrone sont bloquantes jusqu’à réception d’un accusé de réception – Les réceptions bloquent jusqu’à ce que le message soit envoyé – Concernent la fin d’une opération – Les routines bloquantes rendent la main quand l’opération est terminée • Opérations non bloquantes – Rendent la main immédiatement et permettent au programme de continuer – Plus tard, le programme doit tester ou attendre la fin de l’opération non bloquante – Une opération non bloquante immédiatement suivie d’une attente est équivalente à une opération bloquante Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 11 Modes de communication • Emission – MPI_SSEND • Envoi synchrone : se termine quand la réception a commencé – MPI_BSEND • Envoi asynchrone (« buffered ») : se termine toujours (sauf erreur) indépendamment du récepteur. Nécessite la définition d’un tampon (par l’application) via MPI_BUFFR_ATTACH – MPI_SEND • Envoi standard, soit synchrone soit asynchrone (utilise un tampon interne) – MPI_RSEND • Envoi si le récepteur est prêt : démarre seulement si la réception correspondante est déjà indiquée – MPI_RECV • Réception : se termine quand le message est arrivé Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 12 6 Communication non bloquantes Envoi non bloquant MPI_Isend (…) Autre travail MPI_Wait(…) MPI_Issend (buf, count, datatype, dest, tag, comm, OUT &request_handle); MPI_Wait (INOUT &request_handle, &status) Réception non bloquante MPI_Irecv (…) Autre travail MPI_Wait(…) MPI_Irecv (buf, count, datatype, source, tag, comm, OUT &request_handle); MPI_Wait (INOUT &request_handle, &status) Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 13 Les communications collectives • Les routines de communication collective sont des routines de plus haut niveau • Plusieurs processus simultanés (tous les processus d’un communicateur communiquent) • Peuvent être construites à partir des communications point à point • Toutes les opérations collectives sont bloquantes • Pas d’étiquettes • Les tampons de réception doivent avoir exactement la même taille • Les principales communications collectives – – – – Diffusion (broadcast) : un vers plusieurs Dispersion (scatter) Réductions : combinaison de plusieurs processus pour produire un résultat Les barrières de synchronisation Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 14 7 Les communications collectives • Diffusion – Int MPI_Bcast (void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm) • Dispersion – Int MPI_Scatter (void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) • Réunion – Int MPI_Gather (void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) • Réduction globale – MPI_Reduce (&inbuf, &resultbuf, 1, MPI_Datatype, MPI_OP, root, MPI_Comm comm) où MPI_OP = • MPI_MAX, MPI_MIN, MPI_SUM, MPI_PROD • MPI_LAND, MPI_BAND, MPI_LOR, MPI_BOR, MPI_LXOR, MPI_BXOR • MPI_MAXLOC, MPI_MPI_MINLOC (Max/min et position du max/min) – Variantes • MPI_ALLREDUCE (résultat dans tous les processus) • MPI_REDUCE_SCATTER • MPI_SCAN Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 15 Mesure de temps d’exécution • C – Double MPI_Wtime (void); – Temps en secondes Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 16 8 Autres caractéristiques (non traitées) • Les types de données dérivées • Les topologies virtuelles Maîtrise Informatique 2003 Calcul parallèle 17 D. Etiemble Exemple : Calcul de π #include <mpi.h> #include <math.h> int main(argc, argv) int argc; char *argv[]; { int done=0, n=100000, myid, numprocs, i; double mupi, pi, h, sum, x; MPI_Init (&argc, &argv) MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myid); MPI_Bcast(&n, 1,MPI_INT, 0, MPI_COMM_WORLD); if (myid==0) printf(); } MPI_Finalize(); Return 0; } h=1.0/(double) n; sum=0.0; for (i=myid+1;i<= n; i+=numprocs) { x = ((double)i-0.5)*h; sum+ = 4.0/(1.0+x*x); } mypi = pas * sum; MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 18 9 Multiplication de matrices (1) http://www.tcnj.edu/~crew/2000/reference/howto/mm_c.html main(int argc, char **argv) { int numtasks, /* number of tasks in partition */ taskid, /* a task identifier */ numworkers, /* number of worker tasks */ /* source, /* task id of message source */ #define NRA 8 number of rows in matrix A dest, /* task id of message destination */ #define NCA 5 number of columns in matrix A and rows in B nbytes, /* number of bytes in message */ #define NCB 3 number of columns in matrix B mtype, /* message type */ */ intsize, /* size of an integer in bytes */ dbsize, /* size of a double float in bytes */ #define NRA 16 /* number of rows in matrix A */ rows, /* rows of matrix A sent to each worker */ #define NCA 5 /* number of columns in matrix A and rows in B*/ averow, extra, offset, /* used to determine rows sent #define NCB 4 /* number of columns in matrix B */ to each worker */ #define MASTER 0 /* taskid of first task */ i, j, k, /* misc */ #define FROM_MASTER 1 /* setting a message type */ count; #define FROM_WORKER 2 /* setting a message type */ double a[NRA][NCA], /* matrix A to be multiplied */ MPI_Status status; b[NCA][NCB], /* matrix B to be multiplied */ c[NRA][NCB]; /* result matrix C */ #include <stdio.h> #include "mpi.h" intsize = sizeof(int); dbsize = sizeof(double); MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &taskid); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); numworkers = numtasks-1; Maîtrise Informatique 2003 Calcul parallèle 19 D. Etiemble Multiplication de matrices (2) http://www.tcnj.edu/~crew/2000/reference/howto/mm_c.html • Tâches du maîtres – Initialiser les matrices – Envoyer les données des matrices aux esclaves – Attendre les résultats – Imprimer les résultats /**************************** master task ********** if (taskid == MASTER) { printf("Number of worker tasks = %d\n",numworkers); • Tâches des esclaves printf("\nMATRIX A\n"); for (i=0; i<NRA; i++) { for (j=0; j<NCA; j++) { a[i][j]= i+j; printf(" %6.2f ", a[i][j]); } printf("\n"); } printf("\nMATRIX B\n"); for (i=0; i<NCA; i++) { for (j=0; j<NCB; j++) { b[i][j]= i*j; printf(" %6.2f ", b[i][j]); } printf("\n"); } Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 20 10 Multiplication de matrices (3) http://www.tcnj.edu/~crew/2000/reference/howto/mm_c.html /* send matrix data to the worker tasks */ averow = NRA/numworkers; extra = NRA%numworkers; offset = 0; mtype = FROM_MASTER; for (dest=1; dest<=numworkers; dest++) { rows = (dest <= extra) ? averow+1 : averow; printf("****** sending %d rows to task %d\n",rows,dest); MPI_Send(&offset, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD); MPI_Send(&rows, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD); count = rows*NCA; printf("buffer size for A is %d\n", count); MPI_Send(&a[offset][0], count, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD); count = NCA*NCB; printf("buffer size for B is %d\n", count); MPI_Send(&b, count, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD); offset = offset + rows; } /* wait for results from all worker tasks */ mtype = FROM_WORKER; for (i=1; i<=numworkers; i++) { source = i; MPI_Recv(&offset, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status); MPI_Recv(&rows, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status); count = rows*NCB; printf("*** receiving info for C\n"); MPI_Recv(&c[offset][0], count, MPI_DOUBLE, source, mtype, MPI_COMM_WORLD, &status); } Maîtrise Informatique 2003 Calcul parallèle /* print results */ printf("Here is the result matrix\n"); for (i=0; i<NRA; i++) { printf("\n"); for (j=0; j<NCB; j++) printf("%6.2f ", c[i][j]); } printf ("\n"); D. Etiemble } /* end of master section */ 21 Multiplication de matrices (4) http://www.tcnj.edu/~crew/2000/reference/howto/mm_c.html /**************************** worker task ************************************/ if (taskid > MASTER) { mtype = FROM_MASTER; source = MASTER; printf("**** within worker\n"); MPI_Recv(&offset, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status); MPI_Recv(&rows, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status); count = rows*NCA; MPI_Recv(&a, count, MPI_DOUBLE, source, mtype, MPI_COMM_WORLD, &status); count = NCA*NCB; MPI_Recv(&b, count, MPI_DOUBLE, source, mtype, MPI_COMM_WORLD, &status); for (k=0; k<NCB; k++) for (i=0; i<rows; i++) { c[i][k] = 0.0; for (j=0; j<NCA; j++) c[i][k] = c[i][k] + a[i][j] * b[j][k]; printf(" result for Matrix C index[%d][%d] is %6.2f\n", i, j, c[i][k]); } mtype = FROM_WORKER; MPI_Send(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD); MPI_Send(&rows, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD); MPI_Send(&c, rows*NCB, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD); } /* end of worker */ MPI_Finalize(); } /* of main */ Maîtrise Informatique 2003 Calcul parallèle D. Etiemble 22 11