Vous êtes sur la page 1sur 45

Introduction à MPI

1
Plan

MPI : Message Passing Interface


Premiers programmes/premières fonctions

Les communications point à point

2
MPI = Message Passing Interface ;

Définition
I bibliothèque, plus exactement API de haut niveau, pour la
programmation parallèle obéissant au paradigme de l’échange
de message ;
I Interfaces C/C++ et Fortran disponibles

Contexte
I MPI est adaptéà la programmation parallèle distribuée ;
I MPI est née de la collaboration d’universitaires et d’entreprises.
I Très répandu dans le monde du calcul intensif.

3
Fonctionnalités MPI
La bibliothèque MPI permet de gérer :
1. l’environnement d’exécution ;
2. les communications point à point ;
3. les communications collectives ;
4. les groupes de processus ;
5. les topologies de processus ;
MPI permet en outre de gérer :
1. les communications unidirectionnelles ;
2. la création dynamique de processus ;
3. le multithreading ;
4. les entrées/sorties parallèles (MPI/IO).
beaucoup de fonctionnalités (environ 120 fonctions pour MPI 1,
plus de 200 pour MPI 2).

Néanmoins, la maı̂trise des communications point à point et


collectives est suffisante pour paralléliser un code de façon efficace ;

4
Pourquoi utiliser MPI

MPI est avant tout une interface ;


MPI est présent sur tout type d’architecture parallèle ;
MPI supporte les parallélismes modérés et massifs ;
Les constructeurs de machines et/ou de réseaux rapides
fournissent des bibliothèques MPI optimisées pour leurs
plate-formes ;
MPI est également disponible pour la plupart des machines du
marché en open source :
I LAM-MPI : http ://www.lam-mpi.org ;
I MPICH : http ://www-unix.mcs.anl.gov/mpi/mpich ;
I OPEN-MPI

5
Plus précisément

MPI : Message Passing Interface


Premiers programmes/premières fonctions

6
Premier programme MPI
#include <stdio.h>
#include <mpi.h>
int main (argc, argv)
int argc ; char *argv[] ;
int rank, size ;

MPI Init (&argc, &argv) ; /* starts MPI */


printf( ”Hello world \n” ) ;
MPI Finalize() ;
return 0 ;

Tous les appels de la bibliothèque MPI commencent par le


préfixe MPI_ ;
Aucun appel à MPI ne peut avoir lieu avant l’appel à
MPI_Init() ;
Aucun appel à MPI ne peut avoir lieu après l’appel à
MPI_Finalize() ;
7
Compilation et exécution
% mpicc essai-1.c -o essai
% mpirun -np 4 essai
Hello world
Hello world [h]
Hello world
Hello world

la procédure mpirun crée 4 processus, chaque processus


exécutant le programme essai ;
les façns d’exécuter MPI ne sont pas portables ! Elles
dépendent des machines, mais elles sécifient au moins le
nombre de processus et l’ensemble des processeurs sur lesquels
MPI va s’exécuter. Par Exemple :
MPICH : mpirun -np 4 -machinefile hosts essai
les façons de compiler dépendent elles aussi des
implémentations allant jusqu’à utiliser un script de
compilation :
MPICH :mpicc essai.c
8
Ensemble des processus : MPI_COMM_WORLD

Lors de l’initiatialisation de l’environnement, MPI regroupe


tous les processus créés sous le communicateur prédéfini
MPI_COMM_WORLD

communicateur = ensemble de processus + contexte de


communications

un communicateur est de type MPI_Comm ; (ici : il est conseillé


d’utiliser MPI_COMM_WORLD

9
Nombre total de processus : MPI_Comm_size

int MPI_Comm_size( MPI_Comm comm, int *size);

MPI_Comm_size retourne dans ∗size la taille du


communicateur comm ;
#include <stdio.h>
#include <mpi.h>
int main (argc, argv)
int argc ; char *argv[] ; % mpirun -np 4
{ int rank, size ; essai
MPI Init (&argc, &argv) ; Hello world :s = 4
MPI Comm size (MPI COMM WORLD, Hello world :s = 4
&size) ; Hello world :s = 4
printf( ”Hello world :s = %d\n”, size ) ; Hello world :s = 4
MPI Finalize() ;
return 0 ;}
10
Rang d’un processus : MPI_Comm_rank

int MPI_Comm_rank(MPI_Comm comm, int *rank);

Pour un communicateur donné, MPI associe à chaque


processus un numéro compris entre 0 et N-1 (N étant la taille
du communicateur) ;
Le numéro unique associé au processus s’appelle le rang du
processus ;
La fonction MPI_Comm_rank retourne le rang du processus
∗rank dans le communicateur comm

11
Exemple
Programme : #include <stdio.h>
#include <mpi.h>
int main (argc, argv)
int argc ; char *argv[] ;
{ int rank, size ;
MPI Init (&argc, &argv) ;
MPI Comm rank (MPI COMM WORLD, &rank) ;
MPI Comm size (MPI COMM WORLD, &size) ;
printf( ”Hello world from process %d of %d\n”, rank, size ) ;
MPI Finalize() ;
return 0 ;}
Execution : % mpirun -np 4 essai
Hello world from process 1 of 4
Hello world from process 0 of 4
Hello world from process 2 of 4
Hello world from process 3 of 4
12
En Résumé

MPI_Init() et MPI_Finalize() doivent être


respectivement la première et la dernière fonction MPI ;

MPI_COMM_WORLD désigne l’ensemble des processus pouvant


communiquer ;

La taille d’un communicateur est retournée par


MPI_Comm_size() ;

Le rang d’un processus est retourné parMPI_Comm_rank() ;

13
Plan

MPI : Message Passing Interface


Premiers programmes/premières fonctions

Les communications point à point

14
Echange de message : envoi (send)/réception (receive)

Un message est caractérisé par :


I une tâche expéditrice ;
I une tâche destinataire
I les données à échanger ;
Pour échanger un message entre tâches
I l’expéditeur doit envoyer le message (send) ;
I le destinataire doit recevoir le message (receive) ;

15
Echange de message :principe
Soit 2 tâches T 0 et T 1
I Elles ont chacune leur propre espace d’adressage ;
I Elle s’exécutent des instructions indépendantes en parallèle ;
Pour mener à bien le calcul parallèle, T 1 a besoin
d’informations de T 0 (point de synchronisation) :
I T 0 doit envoyer des données à T 1 : les données sont pointées
par adr_send et de taille nb_elt;
I T 1 doit recevoir des données à T 0 :
• la taille du message + le destinataire doit être connue par le
destinataire (préallocation de la zone mémoire)

16
Echange de message :principe

L’échange d’information a lieu (par le réseau le plus souvent, on


parle alors de communication)
send bloque T 0 tant que les données ne sont pas envoyées ;
reveive bloque T 1 tant qu’il n’a pas reçu toutes les
données ;

17
Envoi : instruction MPI_SEND

int MPI_Send (

);

18
Envoi : instruction MPI_SEND

int MPI_Send (
void *buf, (adresse des données à envoyer)

);

18
Envoi : instruction MPI_SEND

int MPI_Send (
void *buf, (adresse des données à envoyer)

MPI_Datatype datatype , (type des données à envoyer)

);

18
Envoi : instruction MPI_SEND

int MPI_Send (
void *buf, (adresse des données à envoyer)
int count, (taille du message)
MPI_Datatype datatype , (type des données à envoyer)

);

18
Envoi : instruction MPI_SEND

int MPI_Send (
void *buf, (adresse des données à envoyer)
int count, (taille du message)
MPI_Datatype datatype , (type des données à envoyer)
int dest, (la destination)

MPI_Comm comm, (dans quelle communicateur)


);

18
Envoi : instruction MPI_SEND

int MPI_Send (
void *buf, (adresse des données à envoyer)
int count, (taille du message)
MPI_Datatype datatype , (type des données à envoyer)
int dest, (la destination)
int tag,(drapeau du message)
MPI_Comm comm, (dans quelle communicateur)
);

18
Envoi : instruction MPI_SEND

19
Réception : instruction MPI_recv

int MPI_Rev (

);
Réception : instruction MPI_recv

int MPI_Rev (
void *buf, (adresse des données à recevoir)

);
Réception : instruction MPI_recv

int MPI_Rev (
void *buf, (adresse des données à recevoir)

MPI_Datatype datatype , (type des données à recevoir)

);

20
Réception : instruction MPI_recv

int MPI_Rev (
void *buf, (adresse des données à recevoir)
int count, (la taille du message doit être inférieur ou égale à
cette valeur)
MPI_Datatype datatype , (type des données à recevoir)

);

20
Réception : instruction MPI_recv

int MPI_Rev (
void *buf, (adresse des données à recevoir)
int count, (la taille du message doit être inférieur ou égale à
cette valeur)
MPI_Datatype datatype , (type des données à recevoir)
int source, (la source)

MPI_Comm comm, (dans quelle communicateur)

);

20
Réception : instruction MPI_recv

int MPI_Rev (
void *buf, (adresse des données à recevoir)
int count, (la taille du message doit être inférieur ou égale à
cette valeur)
MPI_Datatype datatype , (type des données à recevoir)
int source, (la source)
int tag,(drapeau du message)
MPI_Comm comm, (dans quelle communicateur)

);

20
Réception : instruction MPI_recv

int MPI_Rev (
void *buf, (adresse des données à recevoir)
int count, (la taille du message doit être inférieur ou égale à
cette valeur)
MPI_Datatype datatype , (type des données à recevoir)
int source, (la source)
int tag,(drapeau du message)
MPI_Comm comm, (dans quelle communicateur)
MPI_Status *status (le statut du message reçu)
);

20
Réception MPI_Recv et MPI_Status

MPI_Status est une structure de données C :


struct MPI Status {
int MPI SOURCE ; /* expéditeur du message reçu : utile avec
MPI ANY SOURCE */
int MPI TAG ; /* étiquette du message reçu : utile avec
MPI ANY TAG */
int MPI ERROR ; /* code si erreur */
};
Si la taille du message reçu n’est pas connue, il est possible
d’extraire cette information avec la fonction MPI Get count :
int MPI_Get_count(MPI_Status *status,
MPI_Datatype daty , int *count) ;

21
Un exemple
Programme : #include <stdio.h>
#include <mpi.h>
int main (argc, argv)
int argc ; char *argv[] ;
{ int rank, size ;
MPI Init (&argc, &argv) ;
MPI Comm rank (MPI COMM WORLD, &rank) ;
if (rank == 0){ err = MPI Send(”hi”, 3, MPI CHAR, 1, 0,
MPI COMM WORLD) ;}
if (rank == 1){
err = MPI Recv(str, 4, MPI CHAR, 0, 0,
MPI COMM WORLD, MPI STATUS IGNORE) ;
printf(”%d recoit : %s”,rank, str) ;}
MPI Finalize() ;
return 0 ;}
Execution : % mpirun -np 4 essai
1 recoit : hi
22
Pour aller encore plus loin

23
Communication bloquantes

Un envoi send est dit bloquant si et seulement si au retour du


send il est possible d’écrire dans le buffer d’envoi sans altérer
le contenu du message.
Une réception recv est bloquante si et seulement si au retour
du recv le buffer de réception contient bien le contenu du
message.

24
Communication synchrone
Définition
Un envoi synchrone bloquant rendra la main quand le message
aura été reçu par le destinataire ;

1. Lors d’un envoi synchrone, l’expéditeur


envoi au destinataire une requête d’envoi
et attend que le destinataire lui réponde ;
2. Quand le destinataire débute sa réception,
il attend une requête d’envoi de
l’expéditeur ;
3. Quand le destinataire a reçu la requête
d’envoi, il répond à l’expéditeur en lui
accordant l’envoi ;
4. L’expéditeur et le destinataire sont alors
synchronisé, le transfert de données (i.e.
le message proprement dit) a lieu ; l’envoi
et la réception sont alors terminés.
25
Inconvénients

26
Communication bufferisée

Définition
Un envoi bufferisé bloquant rendra la main quand le message aura
été copié dans un buffer géré par la bibliothèque de communication.

1. Lors d’un envoi bufferisé, l’expéditeur


copie le message dans un buffer géré par
la bibliothèque de communication ; l’envoi
peut alors rendre la main.
2. La bibliothèque de communication
s’approprie alors le message et peut
l’envoyer au destinataire.
3. Le destinataire reçoit le message dès que
possible.
Communication Standard

fonction MPI_Send ;
Protocole possible pour un envoi standard :
I MPI considère une taille de message T :
• si le message à envoyer est de taille inférieure à T , l’envoi est
bufferisé (découplage entre l’envoi et la réception)
• si le message à envoyer est de taille supérieure à T , alors
l’envoi est synchronisé (pas de copie intermédiaire) ;

28
Communications non-bloquantes

Définition
Une communication est dite non bloquante si et seulement si au
retour de la fonction, la bibliothèque de communication ne garantit
pas que l’échange de message ait eu lieu.

L’accès sûr aux données n’est donc pas garanti après une
communication non bloquante !

Pour pouvoir réutiliser les données du message, il faudra


appeler une fonction supplémentaire qui complètera le
message (i.e. qui assure un accès sûr aux données).
Envoi non bloquant : MPI Isend

30
Terminer une communication non bloquante :

31
Exemple d’utilisation

Objectif
Couvrir les communications par le calcul

32
Récapitulatif (1/2)

33
Récapitulatif (2/2)

34

Vous aimerez peut-être aussi