Introduction au calcul parallèle MPI
Introduction au calcul parallèle MPI
1
Table des matières
1 Introduction 3
2 Environnement MPI 4
2.1 description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2 Du programme source à l’exécution : . . . . . . . . . . . . . . 5
3 Communications 8
3.1 Communications point à point . . . . . . . . . . . . . . . . . . 8
3.2 Communications collectives . . . . . . . . . . . . . . . . . . . 11
3.2.1 Diffusion générale : MPI_BCAST() . . . . . . . . . 11
3.2.2 Diffusion sélective de données réparties : MPI_SCATTER 12
3.2.3 Collecte de données réparties : MPI_GATHER() . . 12
3.2.4 Collecte générale : MPI_ALLGATHER() . . . . . . 13
3.2.5 Synchronisation globale : MPI_BARRIER . . . . . 14
3.3 Opérations de réduction et communications collectives . . . . 14
6 Topologies 31
6.1 Topologies de type cartésien . . . . . . . . . . . . . . . . . . . 31
6.1.1 Création d’une topologie cartésienne . . . . . . . . . . 31
6.1.2 Quelques fonctions utiles . . . . . . . . . . . . . . . . . 32
6.1.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . 34
6.2 Topologies de type graphe . . . . . . . . . . . . . . . . . . . . 35
6.2.1 Création d’une topologie de type graphe . . . . . . . . 35
1
6.2.2 Quelques fonctions utiles . . . . . . . . . . . . . . . . . 36
6.2.3 Exemple de l’Idris : propagation d’un feu de forêt . . . 37
7 Communicateurs 39
7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
7.2 Communicateur issu d’un autre . . . . . . . . . . . . . . . . . 39
7.3 Subdivision de topologie . . . . . . . . . . . . . . . . . . . . . 40
7.4 Intra et intercommunicateur . . . . . . . . . . . . . . . . . . . 42
8 Conclusion 45
2
1 Introduction
Ce cours est issu de la formation faite par l’IDRIS (http : //[Link].f r).
3
2 Environnement MPI
2.1 description
Pour utiliser la bibliothèque MP I, le programme source doit impérativement
contenir :
1. l’appel au module MP I : include mpif.h en fortran77, use MPI en
fortran90, include mpi.h en C/C + +.
2. l’initialisation de l’environnement via l’appel à la subroutine
MPI_INIT(code). Cette fonction retourne une valeur dans la vari-
able code. Si l’initialisation s’est bien passée, la valeur de code est égale
à celle dans MPI_SUCCESS.
3. la désactivation de l’environnement via l’appel à la subroutine
MPI_FINALIZE (code). L’oublie de cette subroutine provoque une
erreur.
4
2.2 Du programme source à l’exécution :
Trois étapes sont nécessaires : l’écriture du programme, sa compilation
puis son exécution.
1. L’écriture : La figure 1 montre un exemple de programme (exercice
Idris) en f ortran90.
2. La compilation du programme peut se faire par l’intermédiaire d’un
Makefile (figure 2). Les options de compilations dépendent du com-
pilateur. La figure montre un exemple de Makefile pour compiler le
programme pairimpair.f 90 (figure 1) avec le compilateur du construc-
teur IBM (XL)
5
Fig. 1: Programme (en Fortran90) processus pair et impair.
6
Fig. 2: Exemple de Makefile pour le programme pairimpair.f 90.
7
3 Communications
3.1 Communications point à point
La communication point à point est une communication entre deux
processus. L’un d’eux envoie un message (c’est l’émetteur), l’autre le
reçoit (c’est le récepteur).
Ce message doit contenir un certain nombre d’informations pour assurer
une bonne réception et interprétation par le récepteur, à savoir :
. le rang du processus émetteur (rang_proc_source),
. le rang du processus récepteur (rang_proc_dest),
. l’étiquette du message (tag_emis pour message émis, tag_recu pour
message reçu),
. le nom du communicateur (comm),
. le type des données échangées (type_emis pour message émis, type_recu
pour message reçu), voir tableau 1 pour le fortran et tableau 2 pour le C,
. le nom données échangées (val_emis pour message émis, val_recu pour
message reçu).
. la taille des données échangées (taille_emis pour message émis,
taille_recu pour message reçu) (scalaire, vecteur, matrice, ...).
Plusieurs modes de transfert sont possibles pour échanger des messages. On
décrit ici des fonctions MP I de communication en mode bloquant, qui
laisse la main une fois que le message est bien reçu. C’est le mode à utiliser
quand on commence à paralléliser un code. On peut ensuite passer à un
autre mode de tranfert pour optimiser le temps de communication (détail
plus tard).
1. MPI_SEND(val_emis, taille_emis, type_emis, rang_proc_dest,
tag_emis, comm, code) pour l’envoi du message suivi de
MPI_RECV(val_recu, taille_recu, type_recu, rang_proc_dest,
tag_recu, comm, statut, code) pour la réception. Quand un message
est envoyé, il faut être sûr qu’il a été bien reçu.
. val_emis (< in >) : élément envoyé,
. taille_emis (< in >) : entier indiquant la taille de l’élément
envoyé (scalaire, vecteur, ...),
. type_emis (< in >) : type de l’élément envoyé,
. rang_proc_dest (< in >) : entier indiquant le rang du processus
qui reçoit le message,
. tag_emis (< in >) : entier désignant l’étiquette du message,
. comm (< in >) : entier désignant le communicateur
(MP I_COMM_W ORLD par défaut),
. code (< out >) : entier donnant un code d’erreur,
8
. val_recu (< in >) : élément reçu,
. taille_recu (< in >) : entier indiquant la taille de l’élément reçu
(scalaire, vecteur, ...). Il doit correspondre à celui indiqué dans
taille_emis.
. type_recu (< in >) : type de l’élément reçu. Il doit aussi
correspondre à celui indiqué dans type_emis.
. tag_recu (< in >) :entier désignant l’étiquette du message,
. statut (< out >) : tableau d’entiers de taille
MP I_ST AT US_SIZE contenant de nombreuses informations
sur le message.
2. MPI_SENDRECV(val_emis, taille_emis, type_emis,
rang_proc_dest, tag_emis, val_recu, taille_recu, type_recu,
rang_proc_source, tag_recu, comm, statut, code) pour l’envoi et la
reception de messages. Attention, si on utilise la même variable pour
l’envoi et la réception (val_emis = val_recu), il y a écrasement.
rang_proc_source (< in >) est un entier indiquant le rang du
processus qui a émis le message
3. MPI_SENDRECV_REPLACE(val_emis_recu,
taille_emis_recu, type_emis_recu, rang_proc_dest, tag_emis,
rang_proc_source, tag_recu, comm, statut, code) pour l’envoi et la
reception de messages en utilisant le même variable val_emis_recu
pour l’envoi et la réception. Cette fois-ci il n’y a pas d’écrasement.
La figure 3 propose un exemple de programme en F ortran90 d’échange de
messages entre deux processus (exercice de l’Idris) :
Remarques :
– On peut utiliser des ”jokers” pour le rang du processus
(rang_proc_dest = MP I_ANY _SOURCE, ie on reçoit de n’importe
9
Fig. 3: Programme (en Fortran90) d’échange de messages entre deux pro-
cessus.
10
type MPI type C
MP I_INT signed int
MP I_UNSIGNED_INT unsigned int
MP I_F LOAT float
MP I_DOUBLE double
MP I_CHAR signed char
MP I_UNSIGNED_CHAR unsigned char
MP I_P ACKED Types hétérogènes
Proc0 Proc0 A
Proc1 A MPI_BCAST() Proc1 A
Proc2 Proc2 A
Proc3 Proc3 A
11
3.2.2 Diffusion sélective de données réparties : MPI_SCATTER
Cette fonction permet à un processus de diffuser des données aux processus
du communicateur indiqué de façon sélective. En fait le processus émetteur
dispose de données qu’il répartit. Chaque processus ( émetteur même
compris) reçoit un paquet de données différent (figures 5 et 7).
MPI_SCATTER(val_emis, taille_emis, type_emis, val_recu,
taille_recu, type_recu,rang_proc_source, comm, code).
Proc0 Proc0 A0
Proc1 A0 A1 A2 A3 MPI_SCATTER() Proc1 A1
Proc2 Proc2 A2
Proc3 Proc3 A3
Proc0 A0 Proc0
Proc1 A1 MPI_GATHER() Proc1 A0 A1 A2 A3
Proc2 A2 Proc2
Proc3 A3 Proc3
12
Fig. 7: Exemple de programme utilisant la fonction MP I_SCAT T ER().
13
Proc0 A0 Proc0 A0 A1 A2 A3
Proc1 A1 MPI_ALLGATHER() Proc1 A0 A1 A2 A3
Proc2 A2 Proc2 A0 A1 A2 A3
Proc3 A3 Proc3 A0 A1 A2 A3
Nom Opération
MP I_SUM somme des éléments
MP I_P ROD produit des éléments
MP I_MAX Recherche du maximum
MP I_MIN Recherche du minimum
14
Proc0 A0 Proc0
Proc1 A1 MPI_REDUCE() Proc1 A
Proc2 A2 Proc2
Proc3 A3 Proc3
A=A0+A1+A2+A3
Proc0 A0 Proc0 A
Proc1 A1 MPI_ALLREDUCE() Proc1 A
Proc2 A2 Proc2 A
Proc3 A3 Proc3 A
A=A0+A1+A2+A3
15
4 Optimisation d’un programme parallèle
L’optimisation d’un code séquentiel concerne la minimisation du temps de
calcul. Lorsqu’on parallélise un code, un autre temps s’ajoute au temps de
calcul, c’est le temps de communication entre les processus (temps total
= temps calcul + temps communication). L’optimisation d’un code
parallèle consiste donc à minimiser le temps de communication entre les
processus. Celui-ci peut être mesuré via la fonction MPI_WTIME().
Avant de se lancer dans l’optimisation d’un programme parallèle, il faut
d’abord comparer le temps de calcul et le temps de communication au
temps total de simulation. Si le temps de communication est prépondérant
devant le temps de calcul, alors on peut passer à la phase d’optimisation.
Cette étape consiste à réduire le temps de communication. Celui-ci contient
un temps de préparation du message et un temps de transfert. Le temps de
préparation contient un temps de latence pendant lequel les paramètres
réseaux sont initialisés. Le reste du temps de préparation des messages
(appelé aussi temps de surcoût) est lié à l’implémentation MP I et au mode
de transfert utilisé (voir figure 11 pour plus de détails).
Il existe plusieurs possibilités pour optimiser le temps de communication,
parmi elles :
– recouvrir les communications par des calculs.
– limiter les modes de transfert qui utilisent la recopie du message dans un
espace mémoire temporaire (buf f ering).
– limiter les appels répétitifs aux fonctions de communication MP I (qui
coûtent cher en temps).
16
4.1 Modes d’envoi des messages avec MP I
1. Standard : MP I choisit ou non de recopier le message à envoyer
dans une zone mémoire tampon du processus émetteur. S’il y a
recopie, l’action d’envoi se termine lorsque la recopie est terminée,
donc avant que la réception du message ait commencée. Ceci permet
de découpler l’envoi de la réception (asynchrone). S’il n’y a pas
recopie du message, l’envoi s’achève une fois que le processus
destinataire a bien reçu le message. L’envoi et la réception sont alors
couplés (synchrone) (figures 12 et 13). MP I bascule automatiquement
du mode asynchrone au mode synchrone suivant la taille des messages
à transférer. Pour les petits messages, il y a recopie dans une zone
tampon et pour les messages de grande taille, il n’y a pas de recopie.
2. Synchroneous (synchrone) : l’utilisateur impose un couplage entre
l’envoi et la réception. L’envoi peut commencer avant même que
l’opération de réception ait été initialisée. L’opération d’envoi
s’achève une fois que l’opération de réception a été postée (par le
processus récepteur) et le message bien reçu (figure 13).
3. Buffered : L’envoi du message s’achève une fois que la recopie du
message dans une zone tampon est terminée. L’envoi et la réception
sont découplés. Attention, l’utilisateur doit effectuer lui-même la
recopie. Ce type d’envoi est déconseillé.
4. Ready : L’envoi du message ne peut commencer que si la réception
correspondante a DÉJÀ été postée, Sinon il y a erreur. Ce type
d’envoi est intéressant pour les applications clients-serveurs.
SYSTEME SYSTEME
2. MPI RECOPIE
3. RECOPIE FINIE
TRANSFERT
ENVOI FINI
REPREND LA MAIN
MEMOIRE MEMOIRE
17
SYSTEME SYSTEME
TRANSFERT
1. DEMANDE D’ENVOI 2. RECEPTION
POSTEE ET TERMINEE
3. ENVOI FINI
REPREND LA MAIN
MEMOIRE MEMOIRE
18
de plus que la fonction MP I_SEND(), requete. L’argument requete
(< out >) :
. identifie l’opération de communication,
. contient des informations sur l’opération de communication, à savoir le
mode d’envoi, la destination du message, ...
. fait correspondre l’opération d’initialisation de la communication et
celle de réalisation de la communication.
. Réception non-bloquante MPI_IRECV() : Le processus récepteur
initialise la réception mais ne la réalise pas. L’appel à la fonction MP I
sera terminée avant que le message ne soit reçu. Ainsi, la réception du
message par le processus récepteur peut être faite simultanément avec des
calculs après l’initialisation et avant la réception effective. Attention,
l’utilisateur doit lui-même s’assurer que le message a bien été reçu avec
des fonctions MP I adaptées (MPI_TEST() et MPI_WAIT()).
Pour s’assurer que l’opération de communication a bien été effectuée,
l’utilisateur peut utiliser deux fonctions MP I :
– MPI_TEST(requete, f lag, statut) : cette fonction permet de tester si
l’opération de communication, identifiée par requete (< in >), est
terminée. MP I_T EST retourne 2 arguments de sortie (< out >) f lag et
statut. Si l’opération de communication est terminée, alors f lag = .true..
Sinon f lag = .f alse..
– MPI_WAIT (requete, statut) : cette fonction oblige l’opération de
communication, identifiée par requete (< in >), à s’achever.
4.3 Synthèse
19
– MP I_ISSEND(val_emis, taille_emis, type_emis, rang_proc_dest,
tag_emis, requete, code)
– MP I_RECV (val_recu, taille_recu, type_recu, rang_proc_dest,
tag_recu, comm, statut, code)
– MP I_IRECV (val_recu, taille_recu, type_recu, rang_proc_dest,
tag_recu, comm, requete, code)
20
5 Types de données dérivés
Dans les communications MP I, les données transférées sont typées. MP I
dispose de types prédéfinis comme MP I_INT EGER, MP I_REAL, ...
On peut créer des structures de données plus complexes, soit homogènes
(constitués de données de même type) soit hétérogènes (constitués de
données de types différents).
La création d’un type dérivé doit être suivi de sa validation via la
fonction MPI_TYPE_COMMIT(). Pour réutiliser le même type
dérivé, il faut d’abord le libérer avec la fonction MPI_TYPE_FREE().
Attention, il faut éviter de passer directement des sections de tableaux.
Mieux vaut passer par les types dérivés !
Fig. 14: création d’un type dérivé colonne à partir d’une matrice de réels
Ai,j , i ∈ [1, 3], j ∈ [1, 4]. nb_element = 3, old_type = MP I_REAL
21
Les données contigües peuvent représenter une colonne d’une matrice de
réels Ai,j , i ∈ [1, 3], j ∈ [1, 4], par exemple (partie colorée en jaune de la
figure 14).
Le pas peut être donné en nombre d’éléments : c’est le cas par exemple
pour passer une ligne d’une matrice de réels Ai,j , i ∈ [1, 3], j ∈ [1, 4],par
exemple (partie colorée en jaune de la figure 15). Dans ce cas, on utilise la
fonction MPI_TYPE_VECTOR(nb_blocs, longueur_bloc, pas,
old_type, new_type, code).
Le pas peut être donné en nombre d’octets : c’est le cas lorsque le type
dérivé est construit à partir de types plus complexes que les types
prédéfinis. Dans ce cas, on utilise la fonction
MPI_TYPE_CREATE_HVECTOR(nb_blocs, longueur_bloc, pas,
old_type, new_type, code) :
22
pas
longueur_bloc
nb_blocs
Fig. 15: création d’un type dérivé ligne à partir d’une matrice de réels Ai,j ,
i ∈ [1, 3], j ∈ [1, 4]. nb_blocs = 4, longueur_bloc = 1, pas = 3, old_type =
MP I_REAL.
Old_type
1 2 3
New_type
0 2 6
23
– nb_blocs (< in >) est le nombre de blocs,
– longueur_bloc (< in >) est un tableau de dimension nb_blocs con-
tenant le nombre d’éléments de type old_type par bloc,
– deplacement (< in >) est un tableau de dimension nb_blocs con-
tenant l’espacement entre chaque bloc. Cet espacement est donné en
multiple de old_type (voir figure 16).
Le pas peut être donné en nombre d’octets quand la structure est construite
à partir d’éléments de type plus complexes que ceux prédéfinis : Dans ce cas
on utilise la fonction : MPI_TYPE_CREATE_HINDEXED
(nb_blocs, longueur_bloc, deplacement, old_type,new_type,code).
– nb_blocs (< in >) est le nombre de blocs,
– longueur_bloc (< in >) est un tableau de dimension nb_blocs
contenant le nombre d’éléments de type old_type par bloc,
– deplacement (< in >) est un tableau de dimension nb_blocs contenant
l’espacement entre chaque bloc. Cet espacement est donné en octets (voir
figure 17) et doit être déclarée comme integer(kind =
MP I_ADDRESS_KIND), dimension(nb_blocs) :: pas.
Old_type = 1octet
1 2 3
New_type
0 3 10
24
On utilise ensuite la fonction
MPI_TYPE_CREATE_STRUCT(nb_elements, longueur_bloc,
deplacement, tableau_types,new_type,code) (voir figure 18).
– nb_elements (< in >) est le nombre d’éléments de la structure, chaque
élément constitue un bloc.
– longueur_bloc (< in >) est un tableau de dimension nb_elements
contenant le nombre d’éléments de chaque bloc de la structure,
– deplacement (< in >) est un tableau de dimension nb_elements
contenant l’adresse de chaque début de bloc par rapport à celle du
premier bloc, en octets. Il doit être déclaré comme : integer(kind =
MP I_ADDRESS_KIND), dimension(nb_blocs) :: deplacement. On
détermine cette adresse via la fonction
MPI_GET_ADDRESS(element_struct,adress_element, code).
– tableau_types (< in >) est un tableau de dimension nb_elements
contenant le type de chaque bloc de la structure.
– new_type (< out >) est le nouveau type de données.
2 1 2 3 1
New_type
0 3 7 13 16
5.3 Exemples
5.3.1 Exemples sur des types de données dérivés homogènes
Exemple1 : Construction d’un type sous matrice avec la fonction
MP I_T Y P E_V ECT OR() : On construit un type dérivé sous-matrice à
partir d’éléments d’une matrice de réels (voir programme figure 19).
25
Fig. 19: Construction de la transposée d’une matrice à l’aide de types
dérivés : programme en F ortran90.
26
Exemple2 : construction de la transposée d’une matrice à l’aide de type
dérivés (figures 20 et 21) (fonctions MP I_T Y P E_V ECT OR et
MP I_T Y P E_CREAT E_HV ECT OR) : on construit un type ligne à
partir d’éléments d’une matrice de réels, puis un type dérivé transpose
(correspondant à la transposée d’une matrice) à partir du type dérivé ligne.
27
Fig. 21: Construction de la transposée d’une matrice à l’aide de types
dérivés : résultat.
28
Fig. 23: Programme montrant l’échange de sous matrices triangulaires entre
deux processus.
29
Fig. 24: Interaction de deux particules avec
MP I_T Y P E_CREAT E_ST RUCT .
30
6 Topologies
MP I permet de définir des topologies virtuelles de type cartésien ou
graphe. Ces topologies font correspondre le domaine de calcul à une grille
de processus et permettent donc de répartir les processus de manière
régulière sur le domaine de calcul. Ceci se révèle très utile pour les
problèmes de type décomposition de domaine.
31
6.1.2 Quelques fonctions utiles
. La fonction MPI_DIMS_CREATE(nb_procs, ndims, dims, code)
détermine le nombre de processus suivant chaque dimension de la grille
en fonction du nombre total de processus.
. nb_procs (< in >) est un entier indiquant le nombre de processus,
. ndims (< in >) est un entier indiquant la dimension d’espace,
. dims (< inout >) est un tableau d’entiers de dimension ndims
indiquant le nombre d’éléments suivant chaque direction. Si en entrée,
dims est un tableau d’entiers nuls, c’est MP I qui répartit les processus
dans chaque direction en fonction du nombre total de processus. Le
tableau 5 montre quelques répartitions de processus en fonction de la
valeur initiale de dims (voir aussi la figure 25).
. code (< out >) est le code d’erreur.
32
Y
0 1 2 3 X
33
6.1.3 Exemple
La figure 26 montre comment on peut utiliser les différentes fonctions MP I
concernant la topologie cartésienne.
34
6.2 Topologies de type graphe
Lorsque la géométrie du domaine de calcul devient complexe, la topologie
de graphe de processus est plus appropriée. On peut alors répartir les
processus sur des sous domaines de géométries complexes elles aussi.
Chaque processus peut avoir un nombre quelconque de voisins.
0 1
1 0, 2, 3
Proc0 Proc1 Proc2
2 1, 3, 4
3 1, 2, 4
Proc4 4 2, 3
35
– comm_nouveau (< out >) : nom du nouveau communicateur (de
type entier).
– code(<out>) : code de retour (de type entier).
36
6.2.3 Exemple de l’Idris : propagation d’un feu de forêt
37
Fig. 29: Affichage à l’écran des impressions du Programme de la figure 28.
Le programme s’arrête au bout de 10 itérations lorsque le critère d’arrêt est
vérifié.
38
7 Communicateurs
7.1 Introduction
Un communicateur est constitué d’un ensemble de processus et d’un
contexte de communication. Ce contexte, mis en place lors de la
construction du communicateur, permet de délimiter l’espace de
communication et est géré par MP I.
Par défaut, c’est le communicateur MPI_COMM_WORLD qui est créé
lors de l’initialisation de l’environnement MP I. Celui-ci contient tous les
processus actifs et c’est au sein de cet ensemble qu’on effectue des
opérations de communication.
39
. clef (< in >) est un entier qui permet à MP I d’affecter un rang aux
processus appartenant au même sous-espace de communication. Il s’agit
d’une numérotation locale. MP I attribue les rangs suivant des valeurs
de clefs croissantes. Il est conseillé de mettre la clef la plus petite sur
le processus détenant l’information à distribuer (il aura ainsi le rang 0
dans la numérotation locale).
. nouveau_comm (< out >) est un entier désignant le nouveau com-
municateur.
. code (< out >) est un entier donnant le code d’erreur.
Un processus à qui on attribue une couleur MPI_UNDEFINED n’appar-
tient qu’à son communicateur initial.
processus P0 P1 P2 P3 P4 P5
rang_global 0 1 2 3 4 5
couleur 10 20 10 20 10 20
clef 6 1 0 2 5 0
rang_local 2 1 0 2 1 0
40
Fig. 31: Programme en F 90 illustrant le partage de l’espace de communica-
tion initial entre processus de rangs pairs et impairs.
41
soit à partir de la fonction MPI_CART_SUB(CommCart, Subdivision,
CommCartD, code) où :
Y Y
2 P2 P5 P8 P12 2 P2 P5 P8 P12
v=c v=c
1 P1 P4 P7 P10 1 P1 P4 P7 P10
v=b v=b
0 P0 P3 P6 P9 0 P0 P3 P6 P9
v=a v=a
X X
0 1 2 3 0 1 2 3
Topologie cartesienne 2D Topologie Cartesienne degeneree 1D
Transfert information
42
Fig. 33: Programme dégénérant une topologie cartésienne 2D en une topolo-
gie cartésienne 1D avec la fonction MP I_CART _SUB().
43
Fig. 34: Programme dégénérant une topologie cartésienne 2D en une topolo-
gie cartésienne 1D avec la fonction MP I_COMM_SP LIT ().
44
8 Conclusion
La bibliothèque MP I permet de faire du calcul parallèle en se basant sur le
principe d’échanges de messages (communications) entre processus, chacun
ayant sa propre mémoire. Ces opérations de communications peuvent être
collectives ou point à point.
Dans un code de calcul parallèle, si le temps de communication devient
prépondérant devant celui de calcul, on peut optimiser le temps de
communication grâce aux différents modes de transfert de messages
proposés par MP I ainsi qu’en recouvrant les communications par des
calculs.
MP I permet aussi de créer des topologies cartésiennes ou de type graphes
(pour des géométries de domaines plus complexes), ce qui est très pratique
lorsqu’on travaille sur des domaines de calcul ou qu’on souhaite faire de la
décomposition de domaine.
MP I permet aussi de partitionner un ensemble de processus en plusieurs
sous-ensembles de processus au sein desquels on pourra effectuer des
opérations de communication. Ainsi, chaque sous-ensemble dispose de son
propre espace de communication ou communicateur.
Dans une nouvelle version de la bibliothèque MP I (MP I − 2), on note
deux évolutions principales : la gestion dynamique des processus et les
Entrées−Sorties parallèles.
45