Télécharger la présentation
Publié parCorinne Faure Modifié depuis plus de 10 années
1
MPI et programmation par passage de messages
Matthieu EXBRAYAT Maîtrise d’informatique
2
Modèles mémoire Shared memory Shared disk Shared nothing Remarque
Mémoire partagée, disques partagés Implantations « haut de gamme » Croissance limitée Shared disk Mémoire répartie, Implantation physique assez rare (ou ferme de disques) Shared nothing Mémoire et disques répartis Cluster de PC, implantation courante Remarque implantation physique vs implantation logique
3
Mémoire Répartie (shared nothing)
Fonctionnement parallèle = envoi de messages Envoi / Réception Permet la synchronisation Avantages Portabilité, extensibilité Inconvénients Gestion explicite des appels distants = programmation à 2 niveaux
4
MPI : Message Passing Interface
MPI = spécification standard (consortium) Plusieurs implantations Gratuites Portables Intérêt Cadre « simple » pour la programmation par envoi de messages Sémantique « maîtrisée » Portabilité et stabilité (protocole bas niveau pas géré par développeur) Permet architecture hétérogène
5
MPI Contient Constantes, types et fonctions pour C, C++, Fortran (77 et 90) Primitives de comm. point à point Primitives de comm. collectives Regroupement de processus Interface de suivi des performances
6
MPI ne contient pas Opérations en mémoire partagée
EDI (programmation / débogage) Il existe des extensions Gestion de processus Lancement explicite au départ RPC Gestion des threads E/S Parallèles (disponible dans MPI 2)
7
Principe d’un programme MPI
On écrit un programme contenant les opérations locales + les échanges via MPI (initialisation et échanges) On compile On lance par mpirun –np n monprog n=nombre de machines La liste des machines peut être définie explicitement Mpi crée n copies de l’exécutable sur les machines cibles Exécution asynchrone des processus (+synchro sur échange messages) Terminaison des processus
8
Différents types d’appel
Local (manipulation locale d’objets MPI) Non-local : échange avec autre(s) processus Bloquant : le processus reprend la main après l’opération (ressources disponibles) Non-bloquant : le processus reprend la main avant la fin de l’opération (nécessite contrôle) Point-à-point : Echange entre deux processus Collectif : Tous les processus du groupe appellent la même fonction NB : nous utiliserons le groupe par défaut, qui regroupe tous les processus
9
MPI et C Les fonctions commencent par MPI_
Elles retournent un code d’erreur (qui vaut MPI_SUCCESS en cas de réussite) Les arguments de type tableau sont indexés à partir de 0 (C classique…)
10
Connection et déconnection à MPI
MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &num_procs); MPI_Comm_rank(MPI_COMM_WORLD, &myid); MPI_Get_processor_name(processor_name, &namelen); MPI_Finalize();
11
MPI_Send : envoi bloquant
int MPI_Send(void *buf,int count, MPI_Datatype datatype,int dest, int tag, MPI_Comm comm) buf : adresse mémoire (début des informations à transmettre) count : nombre de valeurs à envoyer datatype : type de valeur dest : numéro du processus destinataire tag : numéro associé au message comm : communicateur = groupe de processus. Nous utilisons le groupe global : MPI_COMM_WORLD
12
Des détails… Avant l’appel à MPI_Send, les infos à envoyer sont placées dans une zone de mémoire contigüe (tableau de taille count) Si count = 0 : pas de données (utilisable pour synchro) Les types de données : MPI_CHAR signed char MPI_SHORT signed short int MPI_INT signed int MPI_LONG signed long int MPI_FLOAT float MPI_DOUBLE double MPI_PACKED Comment envoyer un seul entier ?
13
MPI_Receive : réception bloquante
int MPI_Recv (void* buf,int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status) buf : emplacement où stocker les valeurs reçues count : capacité de buf (erreur si débordement, placement au début si remplissage incomplet) source : machine émettrice (numéro ou MPI_ANY_SOURCE) tag : numéro ou MPI_ANY_TAG status : infos sur la réception (structure) : status.MPI_SOURCE status.MPI_TAG status.MPI_ERROR int MPI_Get_count(MPI_Status *status,MPI_DATATYPE datatype, int *count))
14
Bloquant ? Une opération est bloquante dans le sens où elle ne termine qu’après avoir terminé l’utilisation du buffer : send se termine après l’envoi effectif (!= réception) receive se termine après la réception effective un send peut-il être lancé avant le receive correspondant ?
15
Ordre d’acheminement MPI garanti l’ordre d’acheminement entre un émetteur et un destinataire donnés. L’ordre global n’est par contre pas garanti (plusieurs émetteurs vers un même destinataire, par exemple).
16
Envoi et réception combinés
Si deux processus souhaitent échanger des informations, il est possible d’appeler MPI_Sendrecv int MPI_Sendrecv (void* sendbuf, int sendcount, MPI_Datatype sendtype, int dest, int sendtag, void* recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status) Procède comme deux threads qui géreraient un envoi et une réception envoi et réception sont bloquants Les buffers sont nécessairement différents (disjoints) Les tags peuvent être différents.
17
Processus NULL On peut faire des envoi vers MPI_PROC_NULL (si destinataire inactif pour une raison donnée) Se termine dès que possible. Aucun effet Utilisable aussi en réception.
18
Envoi et réception non bloquants
Le processus reprend la main dès que la demande d’envoi ou de réception est faite. Le processus contrôle ensuite si l’envoi ou la réception a été effectué Permet des recouvrement calcul- communication (particulièrement intéressant pour réception)
19
Syntaxe int MPI_ISend(void *buf,int count, MPI_Datatype datatype,int dest, int tag, MPI_Comm comm, MPI_Request *request) int MPI_IRecv (void* buf,int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request) int MPI_Wait(MPI_Request * request, MPI_Status * status) int MPI_Test(MPI_Request * request, int *flag, MPI_Status * status)
20
Opérations collectives
MPI définit certains algorithmes parallèles de base : diffusion, réduction… Définition cohérente avec send et receive, mais : correspondance entre message et buffer de réception (taille) opérations bloquantes pas de tag.
21
Barrière de synchronisation
Permet de s’assurer d’un point de synchro (car pas de certitudes à partir des send et receive, même bloquants). int MPI_Barrier(MPI_Comm comm) Opération globale au groupe de processus
22
Broadcast int MPI_Bcast(void * buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm) Envoi depuis le processus de rang root vers tous les autres
23
Gather Un processus collecte des informations venant de tous les processus et les assemble (dans un tableau) int MPI_Gather(void *sendbuf,int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) Tous les processus (root y-compris) envoient des infos vers root. Le placement se fait dans l’ordre des rangs de processus. en général, recvcount = sendcount
24
Scatter Scatter : un processus distribue des informations (stockées dans un tableau) vers tous les processus int MPI_Scatter(void *sendbuf,int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) Tous les processus (root y-compris) reçoivent des infos de root. La distribution se fait dans l’ordre des rangs de processus. en général, recvcount = sendcount
25
Reduce On dispose d’un certain nombre de calculs de préfixes pré-implantés int MPI_Reduce(void* sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) MPI_MAX, MPI_MIN, MPI_SUM, MPI_PROD MPI_LAND, MPI_LOR, MPI_LXOR MPI_BAND, MPI_BOR, MPI_BXOR MPI_MAXLOC, MPI_MINLOC (paire valeur/index)
26
Scan On dispose d’un certain nombre de calculs de préfixes pré-implantés int MPI_Scan(void* sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) Mêmes opérateurs que pour Reduce
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.