670 likes | 914 Views
Programmation avec MPI. Professeur: Nilo Stolte Chargé de Cours: Mohammed ELKANOUNI Département de génie logiciel et des TI. Sommaire. Introduction au MPI Programmes MPI Messages Communications point à point Communications collectives Autres fonctions MPI Groupes et communicateurs
E N D
Programmationavec MPI Professeur: Nilo Stolte Chargé de Cours: Mohammed ELKANOUNI Département de génie logiciel et des TI
Sommaire • Introduction au MPI • Programmes MPI • Messages • Communications point à point • Communications collectives • Autres fonctions MPI • Groupes et communicateurs • Construction de son propre type
Qu’est ce MPI • MPI est une librairie, pas un langage • MPI est une spécification de librairie proposée comme une norme pour une large population de vendeurs, développeurs et utilisateurs • Il spécifie les noms, séquencement d’un appel et les résultats des fonctions sous C, C++ et Fortran • MPI décrit ce qu’il faut faire mais pas comment faire
Historique • Avril 1992: début du workshop sur "Standards for Message Passing in a Distributed Memory Environment" • Novembre 1992: ébauche du standard MPI • Novembre 1993: standard MPI 1.0 • Juin 1995: standard MPI 1.1 • Décembre 1995: première version du MPI 2.0 • Juin 1997: MPI/RT-1.0 (MPI à temps réel) • Mars 2001: MPI/RT-1.1
Objectifs du MPI • Portabilité • Performance • Fiabilité • Simplicité • Spécification indépendante du langage
Plate-formes ciblés par MPI • Machines connectées par réseau: • Parallèles • Séquentielles • Ensemble de machines hétérogènes • Systèmes d’exploitation: • Unix • Linux • Windows NT et 2000
Implémentations MPI (Posix) • LAM-MPI de l'université de Notre Dame • MPICH d'Argonne National Laboratory • MPICH-PM/CLUMP du Parallel and Distributed System Software Laboratory • MPICH-T3E de l'université de l'État du Mississipi • MPICH-MADELEINE de l'École Normale Supérieure de Lyon • MPI/Pro de Software Technology, Inc • MP-MPICH de l'université de LBFS • CHIMP/MPI de Edinburgh Parallel Computing Centre (EPCC) • CRI/EPCC MPI for Cray T3D de Cray Research Incorporated via Edinburgh Parallel Computing Centre • MPIAP de Australian National University - CAP Research Program
Implémentations MPI (Windows) • MPICH-NT d'Argonne National Laboratory • MPI/Pro de Software Technology, Inc • WMPI de Critical Software, Inc. • NT-MPICH de l'université LBFS • WINMPICH de l'université d’État du Mississipi La majorité des implémentations sont disponibles gratuitement
Guides du MPI • MPICH (installation, utilisation, administration) • http://www-unix.mcs.anl.gov/mpi/mpich/ • LAM-MPI: • http://www.lam-mpi.org/using/docs/
Livres sur MPI • Using MPI, William Gropp, Ewing Lusk, and Anthony Skjellum, MIT Press: • http://www-unix.mcs.anl.gov/mpi/usingmpi/ • MPI:The complete reference, Marc Snir, Steve Otto, Steven Huss-Lederman, David Walker, Jack Dongarra, MIT Press: • http://www.netlib.org/utk/papers/mpi-book/mpi-book.html • http://www.netlib.org/utk/papers/mpi-book/mpi-book.ps
Modèle de programmation MPI • SPMD: Single Program, Multiple Data • Plusieurs processus lancés sur une ou plusieurs machines • Chaque processus à ses propres variables locales • Partage de données se fait par passage de message: • Point à point (un à un) • Collection de données (plusieurs à un) • Broadcast (un à plusieurs)
Composition d’un programme • Entête du fichier: • #include "mpi.h" • #include <mpi.h> • Fonction main • void main(int argc,char *argv[]) • Format des fonctions: • int MPI_Xxxxxx( parameter, ...);
Initialisation • int MPI_Init(int *argc, char ***argv); • argc, argvsont les arguments de la fonction main • La première fonction MPI à appeler dans un programme • Doit être appelée une seule fois dans un programme
Finalisation • int MPI_Finalize( ); • La dernière fonction MPI à appeler dans un programme • Le programmeur doit s’assurer que toutes les communications sont terminées • Aucune fonction MPI ne peut être appelée après la finalisation
Communicateurs • Lors de l’appel deMPI_Init, on crée un communicateurMPI_COMM_WORLD • Toutes les communications nécessitent un communicateur • Les processus MPI ne peuvent se communiquer que s’ils partagent le même communicateur MPI_COMM_WORLD 0 1 3 2 4
Identificateur • Renvoi du nombre de processus MPI_Comm_size (MPI_COMM comm, int *size) • comm: communicateur • Size: nombre de processus dans le groupe comm • Renvoi de l’identificateur du processus courant MPI_Comm_rank (MPI_COMM comm, int *rank) • comm: communicateur • Identificateur (0, ..size-1) du processus appelant
Programme hello1.c #include <stdio.h> #include "mpi.h" void main (int argc, char *argv[]) { int err; err = MPI_Init(&argc, &argv); printf("Hello world!\n"); err = MPI_Finalize();
Compilation et exécution (MPICH) • Compilation: • mpicc –o nomEXE fichier.c • Exécution: (avec 4 processus) • /opt/mpich_cluster/bin/mpirun –np 4 hello1_cl • /opt/mpich_shmem/bin/mpirun –np 4 hello1_sm • Exécution: (spécification de fichier d’exécution) • /opt/mpich_cluster/bin/mpirun –p4pg hello1.pg hello1_cl
Compilation et exécution (LAM-MPI) • Ajouter les variables d’environnement LAMHOME dans le fichier de démarrage .cshrc • setenv LAMHOME /opt/lam-mpi • Ajouter le chemin de bin dans .cshrc • set path=$LAMHOME/bin $path • Compilation: • mpicc –o nomEXE fichier.c • Lancer les démons dans les machines désirées: • lamboot –v hostfile (hostfile contient les noms des machines) • Exécution: (avec 4 processus) • mpirun –np 4 nomEXE
Programme hello2.c #include <stdio.h> #include "mpi.h" void main (int argc, char *argv[]) { int err, np, myid; err = MPI_Init(&argc, &argv); if (err != MPI_SUCCESS) { printf ("Erreur d'initialisation de MPI\n"); exit(1); }
Programme hello2.c MPI_Comm_size (MPI_COMM_WORLD, &np); MPI_Comm_rank (MPI_COMM_WORLD, &myid); printf("Hello World ! Je suis le processus no. %d de %d processus\n", myid, np); MPI_Finalize(); }
Communication P. à P. • Communication entre 2 processus • Processus envoi un message au processus destinataire • La communication se fait à l’intérieur du communicateur • Processus destinataire est identifié par son identificateur dans le communicateur communicateur destinataire 1 5 3 2 4 source
Types de communication • Envoi synchrone: Exige la synchronisation de l’émetteur et du récepteur (se termine lorsque la réception est complétée ) • Envoi avec buffer: se termine toujours sans tenir compte si la réception est complétée • Envoi standard: soit synchrone ou avec buffer • Réception: se termine lorsque le message est arrivé
Envoi d’un message • int MPI_Send (void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm); • buftampon à envoyer • countnombre d’éléments de type datatypeà envoyer • datatypetype de données dans buf • destidentificateur du destinataire • tagétiquette du message • commcommunicateur (groupe de processus)
Envoi d’un message • Lorsque MPI_Send est appelée, une des 2 situations peut arrive • Le message peut être copié dans un buffer interne et transféré plus tard au destination • Le message reste dans les variables du programme jusqu’à ce que la destination soit prête à recevoir les messages • Dans 1, une fois que la copie dans le buffer est terminée, le processus continue l’instruction suivant
Réception d’un message • int MPI_Recv (void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status); • buftampon à revoir • countnombre d’éléments de type datatype à recevoir • datatype type de données dans buf • sourceidentificateur de l’expéditeur. • source = MPI_ANY_SOURCE indique n’importe quelle source • tagétiquette du message • tag= MPI_ANY_TAG indique n’importe quelle étiquette
Réception d’un message • int MPI_Recv (void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status); • commcommunicateur (groupe de processus) • statusstructure de statut retourné • status.MPI_SOURCE: identificateur de l’expéditeur • status.MPI_TAG: étiquette du message
Réception et envoi d’un message • MPI_Send et MPI_Recv bloquent le processus appelant jusqu’à ce que la communication est terminée • Si le message passé à MPI_Send est plus long que les buffers internes disponibles, le processus se bloque jusqu’à la réception ou la disponibilité de buffers.
Réception et envoi d’un message • Les messages envoyés par différents processus sont dans un ordre aléatoire (non déterministe) • Si un processus A envoie plusieurs messages au processus B. B recevra par contre les messages de A en ordre (déterministe)
Type de données • Un message MPI contient un ensemble d’éléments de type de données MPI • Types de données MPI: • Type de base • Type composé à partir de type de base
Deadlock • Arrive lorsque 2 ou plusieurs processus sont bloqués et chacun attend l’exécution de l’autre • Exemple: /* simple deadlock */ #include <stdio.h> #include "mpi.h" void main (int argc, char **argv) { int myrank; MPI_Status status; double a[100], b[100];
Deadlock MPI_Init(&argc, &argv); /* Initialize MPI */ MPI_Comm_rank(MPI_COMM_WORLD, &myrank); /* Get rank */ if( myrank ==0 ){ MPI_Recv( b, 100, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &status ); MPI_Send( a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD ); } else if( myrank ==1 ){ MPI_Recv( b, 100, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD, &status ); MPI_Send( a, 100, MPI_DOUBLE, 0, 19, MPI_COMM_WORLD ); } MPI_Finalize(); /* Terminate MPI */ }
Éviter le Deadlock • Pour chaque MPI_Recv d’un processus il doit y avoir un MPI_Send dans un autre processus if( myrank ==0 ){ MPI_Recv( b, 100, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &status ); MPI_Send( a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD ); } else if( myrank ==1 ){ MPI_Send( a, 100, MPI_DOUBLE, 0, 19, MPI_COMM_WORLD ); MPI_Recv( b, 100, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD, &status ); } MPI_Finalize(); /* Terminate MPI */ }
Éviter le Deadlock • Utiliser les communication non bloquantes
Éviter le Deadlock • Utiliser les communications non bloquantes • On peut faire des traitements en attente de la fin de la communication • Tester à chaque fois si le message est arrivé ou non sans blocage (MPI_Test) • Tester à chaque fois si le message est arrivé ou non avec blocage (MPI_Wait)
Communications collectives • Barrière de synchronisation des processus • Émission d’un message d’un processus aux autres processus • Réduction globale des opérations comme: somme, min, max • Collection des données de plusieurs processus à un processus • Distribution d’un processus aux autres
Barrière de synchronisation int MPI_Barrier (MPI_Comm comm ) • Cette fonction bloque le processus appelant jusqu’à ce que le groupe de processus appelle cette fonction • Permet la synchronisation des processus
Émission (Broadcast) • int MPI_Bcast (void *buffer, int count, MPI_Datatype dataType, int root, MPI_Comm comm); • buffertampon de donnée à émettre • countnombre d’éléments dans buffer • dataTypetype de donnée • rootidentification du processus émetteur • commCommunicateur (groupe de processus, incluant l’émetteur root, qui recevra les données)
Émission (Broadcast) send_count = 1; root = 0; MPI_Bcast ( &a, send_count, MPI_INT, root, comm )
Réduction (reduce) • int MPI_Reduce (void *sendBuf, void *recvBuf, int count, MPI_Datatype dataType, MPI_OP op, int root, MPI_Comm comm); • senBufTampon d’envoie, • recvBufTampon de réception, significatif seulement pour root • countNombre d’éléments dans sendBuf • dataTypeType de donnée dans sendBuf • opOpération utilisée pour la réduction • rootIdentificateur du processus qui effectue la réduction des données • commGroupe des processus participants, incluant root
Réduction (reduce) count = 1; rank = 0; MPI_Reduce ( &a, &x, count, MPI_REAL, MPI_SUM, rank, MPI_COMM_WORLD );