Introduction À MPI - Message Passing Interface
Introduction À MPI - Message Passing Interface
Introduction À MPI - Message Passing Interface
Philippe M ARQUET
[email protected]
Hello world
Une application
Communications collectives
Regroupement des données
Communicateurs
Différents modes de communications
Et maintenant ?
Compilation et exécution de programmes MPI
p processus : P0 à Pp−1
Les processus Pi,i>0 envoient un message (chaîne de caractères) à P0
P0 recoit p − 1 messages et les affiche
P0
I/O
#include <stdio.h>
#include "mpi.h"
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &p);
if (my_rank != 0) {
/* Creation du message */
sprintf(message, "Hello from process %d!", my_rank);
dest = 0;
/* strlen + 1 => le ’\0’ final est envoye */
MPI_Send(message, strlen(message)+1, MPI_CHAR, dest,
tag, MPI_COMM_WORLD);
} else { /* my_rank == 0 */
for (source = 1; source < p; source++) {
MPI_Recv(message, 100, MPI_CHAR, source, tag,
MPI_COMM_WORLD, &status);
printf("%s\n", message);
}
}
MPI_Finalize();
} /* main */
Introduction à MPI – Message Passing Interface – p. 10/71
Structure d’un programme MPI
Qui suis-je ?
int MPI_Comm_rank (MPI_Comm comm, int *rank) ;
Communicateur : collection de processus pouvant communiquer
Communicateur MPI_COMM_WORLD predéfini : tous les processus
Combien sommes-nous ?
int MPI_Comm_size (MPI_Comm comm, int *size) ;
nh nh
[a + q , a + (q + 1) ]
p p
Il a besoin de
p → MPI_Comm_size ()
q → MPI_Comm_rank ()
a, b, n → codage en dur dans le programme (à suivre...)
Collecte par le processus 0 des différentes intégrales
/* On utilise MPI */
MPI_Init(&argc, &argv);
/* Qui suis-je ? */
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
/* Combien sommes-nous ? */
MPI_Comm_size(MPI_COMM_WORLD, &p);
Affichage du résultat
if (my_rank == 0) {
printf("Estimation : %f\n", total);
}
Terminaison
MPI_Finalize();
} /* main */
void Get_data(int my_rank, int p, float *a_ptr, float *b_ptr, int *n_ptr
int source = 0;
int dest;
int tag = 30;
MPI_Status status;
if (my_rank == source){
printf("Donner a, b, et n\n");
scanf("%f %f %d", a_ptr, b_ptr, n_ptr);
for (dest = 1; dest < p; dest++){
MPI_Send(a_ptr, 1, MPI_FLOAT, dest, tag, MPI_COMM_WORLD);
MPI_Send(b_ptr, 1, MPI_FLOAT, dest, tag, MPI_COMM_WORLD);
MPI_Send(n_ptr, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);
}
} else {
MPI_Recv(a_ptr, 1, MPI_FLOAT, source, tag, MPI_COMM_WORLD, &status
MPI_Recv(b_ptr, 1, MPI_FLOAT, source, tag, MPI_COMM_WORLD, &status
MPI_Recv(n_ptr, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
}
} /* Get_data */ Introduction à MPI – Message Passing Interface – p. 28/71
Communications collectives
Deux communications
« un vers tous » : Get_data ()
« tous vers un » : collecte des résultats
Communication arborescente
Complexité en O(p) complexité en O(log 2 (p))
Quelle structure pour mon arbre ?
Dépend de la structure de la machine parallèle
⇒ utilisation de fonctions MPI
Communication collective = fonction SPMD
if (my_rank == root)
{
printf("Donner a, b, et n\n");
scanf("%f %f %d", a_ptr, b_ptr, n_ptr);
}
MPI_Bcast(a_ptr, 1, MPI_FLOAT, root, MPI_COMM_WORLD);
MPI_Bcast(b_ptr, 1, MPI_FLOAT, root, MPI_COMM_WORLD);
MPI_Bcast(n_ptr, 1, MPI_INT, root, MPI_COMM_WORLD);
} /* Get_data2 */
local_a = a + my_rank*local_n*h;
local_b = local_a + local_n*h;
integral = Trap(local_a, local_b, local_n, h);
MPI_Reduce(&integral, &total, 1,
MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD);
if (my_rank == 0) {
printf("Estimation : %f\n", total);
}
Synchronisation ou rendez-vous
Pas d’échange d’informations
Tous les processus sont assurés que tous ont ralliés le point de
synchronisation
int MPI_Barrier (MPI_Comm comm) ;
if (my_rank == root){
printf("Enter a, b, and n\n");
scanf("%f %f %d",
&(indata->a), &(indata->b), &(indata->n));
}
Build_derived_type(indata, &message_type);
MPI_Bcast(indata, count, message_type,
root, MPI_COMM_WORLD);
} /* Get_data3 */
if (my_rank == root){
printf("Donner a, b, et n\n");
scanf("%f %f %d", a_ptr, b_ptr, n_ptr);
Synchrone
rendez-vous entre l’émetteur et le récepteur
Asynchrone
émission dès que le message est prêt
réception postérieure à l’émission
Asynchrone non bloquante
rendre la main au plus vite à l’appelant
demande d’exécution de communication
MPI_Send() et MPI_Recv()
Deux implantations possibles
recopie du message dans un buffer
communication bloquante
Recopie dans un buffer
permet de libérer l’émetteur dès la copie faite
coût de cette copie
protocole utilisée sur IBM si message inférieur à MP_EAGER_LIMIT octets
Rendez-vous
évite la recopie
communication synchrone
attention aux étreintes fatales (dead-lock)
protocole utilisée sur IBM si message supérieur à MP_EAGER_LIMIT octets
Compilateur C/C++/Fortran
scripts mpcc/mpCC/mpxlf
compilation + édition de liens avec la bibliothèque MPI
compilation de programes MPI C/C++/Fortran multithreadés : mpcc_r,
mpCC_r, mpxlf_r
options d’optimisation -qarch=pwr3 -03 -qstrict
Exécution d’un programme parallèle
Exécutable accessible sur tous les nœuds de la machine
(par exemple : sous le répertoire de login et pas dans /tmp)
Accès par rsh à tous les nœuds ($HOME/.rhosts)
Spécification des noeuds
fichier host.list du répertoire courant
fichier designé par la variable MP_HOSTFILE
fichier contient une liste de noms de noeuds (un nom par ligne)