Vous êtes sur la page 1sur 28

Travaux pratiques

MPI

• Présentation de MPI
• Schéma général d’un programme MPI
• Exécution d’un programme C quelques commandes Unix
• Quelques fonctions MPI
• Exemples de programmes
• Communication
• Calcul de P
• Gestion des groupes
• Gestion des communicateurs
• Projets de TP
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 1
Présentation de MPI (Message Passing Interface)

• Bibliothèque standard à inclure dans un programme C (#include "mpi.h") ou


Fortran (INCLUDE ’mpif.h’)
• Ancêtre : PVM (Parallel Virtual Machine) en 1991
• Plusieurs implantations : MPI-1(1994), MPICH2(2000) et OpenMPI(2009)
• Autres bibliothèques : OpenMP(2010),…
• Souvent utilisée dans des architectures à mémoire distribuée
• Modèle SPMD (Single Programme Multiple Data)
• Le même programme est installé dans chaque processeur (ou machine)
• Des instances multiples du programme traitent partiellement ou totalement
les données
• Chaque instance a un identificateur unique par rapport à un communicateur
• L’instance exécute la partie du programme selon son identificateur
• Référence : http://www.open-mpi.org,...
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 2
Schéma général d’un programme MPI

rang  identificateur du processus en cours par rapport à un communicateur


si (rang = identificateur_spécifique) alors
faire un traitement
sinon
faire un autre traitement

p2 p5
p0
p4
p1 p3 p6

Communicateur A Communicateur B
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 3
Exécution d’un programme C
/* fichier hello.c*/
#include <stdio.h>
int main() {
printf("Hello World!");
return 0;
}

Compilation:
$gcc hello.c (ou gcc –o hello.exe hello.c)
Exécution:
$./a (ou /home/……./a.exe ou ./hello)
Résultat:
$ Hello World!
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 4
Quelques commandes Unix
$pwd
$ls -l
$hostname
$mpirun -n 1 hostname (ou mpiexec -np 1 hostname)
$mpirun -n 7 hostname
$mpirun hostname
$mpirun -n 5 hello
$mpirun -n 12 hello
$mpirun -machinefile machine.txt -n 4 hostname
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 5
Quelques fonctions MPI (1/2)
int MPI_Init(int *argc, char ***argv)
int MPI_Finalize()
int MPI_Comm_rank(MPI_Comm comm, int *rank)
int MPI_Comm_size(MPI_Comm comm, int *size)
int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest,
int tag, MPI_Comm comm)
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag,
MPI_Comm comm, MPI_Status *status)
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root,
MPI_Comm comm)
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group)
int MPI_Group_incl(MPI_Group group, int n, const int ranks[],
MPI_Group *newgroup)
int MPI_Comm_create(MPI_Comm comm, MPI_Group group,
MPI_Comm *newcomm)
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 6
Quelques fonctions MPI (2/2)
int MPI_Reduce(void *sendbuf, void *recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, int root,MPI_Comm comm)
Int MPI_Allreduce( void *sendbuf, void *recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, MPI_Comm comm )
Opérations :
MPI_MAX : maximum MPI_MIN : minimum
MPI_SUM : sum MPI_PROD : product
MPI_LAND : logical and MPI_BAND : bit-wise and
MPI_LOR : logical or MPI_BOR : bit-wise or
MPI_LXOR: logical xor MPI_BXOR : bit-wise xor
MPI_MAXLOC : max value + location MPI_MINLOC : min value + location

Liste complète (≈360 fonctions) : https://www.open-mpi.org/doc/v1.8


Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 7
Exemples de programmes

• Exemple 1 : Communication entre processus


• Exemple 2 : Calcul de P
• Exemple 3 : Gestion des groupes
• Exemple 4 : Gestion des communicateurs
• Exercices

Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 8


Algorithme de communication
p  nombre total des processus
rang  identificateur du processus
si (rang ≠ 0) alors
message  ″Hello world du processus″ + rang
envoyer(message,0)
sinon
écrire(″Hello world du processus 0 : nombre de processus ″,p)
pour source=1 à (p-1) faire
recevoir(message,source)
p0
écrire(message)

p1 p2 p3
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 9
Programme de communication (1/3)
/* programme helloMPI.c*/
#include <stdio.h>
#include <string.h>
#include "mpi.h"

int main(int argc, char* argv[]){


int my_rank; /* rank of process */
int p; /* number of processes */
int source; /* rank of sender */
int dest; /* rank of receiver */
int tag=0; /* tag for messages */
char message[100]; /* storage for message */
MPI_Status status ; /* return status for receive */
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 10
Programme de communication (2/3)
/* start up MPI */
MPI_Init(&argc, &argv);
/* find out process rank */
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
/* find out number of processes */
MPI_Comm_size(MPI_COMM_WORLD, &p);

if (my_rank !=0){
/* create message */
sprintf(message, "Hello MPI World from process %d!", my_rank);
dest = 0; /* use strlen+1 so that '\0' get transmitted */
MPI_Send(message, strlen(message)+1, MPI_CHAR,dest,
tag,MPI_COMM_WORLD);
}
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 11
Programme de communication (3/3)

else{
printf("Hello MPI World From process 0: Num processes: %d\n",p);
for (source = 1; source < p; source++) {
MPI_Recv(message, 100, MPI_CHAR, source, tag,
MPI_COMM_WORLD, &status);
printf("%s\n",message);
}
}

/* shut down MPI */


MPI_Finalize();
return 0;
}

Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 12


Exercice 1
a) Compilation
$mpicc -o helloMPI.exe helloMPI.c -lm
b) Exécution
$mpirun -n 5 helloMPI.exe
c) Création de helloMPIMod.c
supprimer l’appel MPI_Send
exécuter le programme
Que se passe-t-il ?
d) Création de course.c
supprimer les appels MPI_Send
supprimer la boucle lorsque my-rank=0 (processus p0)
remplacer sprintf par printf (un affichage par processus)
exécuter le programme à 2 reprises
Que se passe-t-il ?

Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 13


Algorithme du calcul de P
Calc_pi(rank, num_procs)
si (rank = 0) alors
num_intervals  1000
diffuser(num_intervals)
h  1/num_intervals
sum0
pour i = rank + 1 à num_intervals pas num_procs
x=h * (i – 0,5)
sum = sum + 4*racine_carrée(1 – x2)
mypi = h* sum
reduce(mypi,pi)
si (rank = 0) alors écrire(″PI=″, pi)
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 14
Schéma du calcul de P

Hypoyhèse :
num_procs = 3 (p0, p1 et p2)
num_intervals =10 donc h = 0,1 1

p0 calcule les valeurs


x=0,05, x=0,35, x=0,65 et x=0,95
p1 calcule les valeurs
x=0,15, x=0,45 et x=0,75
p2 calcule les valeurs
x=0,25, x=0,55 et x=0,85 p0 p1 p2 p0 p1 p2 p0 p1 p2 p0

1
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 15
Programme du calcul de P (1/5)
/* fichier calculPi.c */
#include <mpi.h>
#include <stdio.h>
#include <string.h>
void calc_pi(int rank, int num_procs){
int i;
int num_intervals;
double h;
double mypi;
double pi;
double sum;
double x;
/* set number of intervals to calculate */
if (rank == 0) {
num_intervals = 1000;
}
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 16
Programme du calcul de P (2/5)
/* tell other tasks how many intervals */
MPI_Bcast(&num_intervals, 1, MPI_INT, 0, MPI_COMM_WORLD);

/* now everyone does their calculation */


h = 1.0 / (double) num_intervals;
sum = 0.0;
for (i = rank + 1; i <= num_intervals; i += num_procs) {
x = h * ((double)i - 0.5);
sum += (4.0 * sqrt(1.0 - x*x));
}
mypi = h * sum;

/* combine everyone's calculations */


MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0,MPI_COMM_WORLD);
if (rank == 0) {
printf("PI is approximately %.16f\n", pi);
}
}
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 17
Programme du calcul de P (3/5)
int main(int argc, char *argv[]) {
int my_rank; /* rank of process */
int num_procs; /* number of processes */
int source; /* rank of sender */
int dest = 0; /* rank of receiver */
int tag = 0; /* tag for messages */
char message[100]; /* storage for message */
MPI_Status status ; /* return status for receive */
/* start up MPI */
MPI_Init(&argc, &argv);
/* find out process rank */
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
/* find out number of processes */
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 18
Programme du calcul de P (4/5)
if (my_rank != 0) {
/* create message */
snprintf(message,26, "Greetings from process %d!", my_rank);
/* use strlen+1 so that '\0' get transmitted */
MPI_Send(message, strlen(message)+1, MPI_CHAR,
dest, tag, MPI_COMM_WORLD);
}
else {
printf("Num processes: %d\n",num_procs);
for (source = 1; source < num_procs; source++) {
MPI_Recv(message, 100, MPI_CHAR, source, tag,
MPI_COMM_WORLD, &status);
printf("Process 0 received \"%s\"\n",message);
}

Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 19


Programme du calcul de P (5/5)
/* now return the compliment */
snprintf(message, 26, "Hi, how are you? ");
}
MPI_Bcast(message, strlen(message)+1, MPI_CHAR, dest,
MPI_COMM_WORLD);
if (my_rank != 0) {
printf("Process %d received \"%s\"\n", my_rank, message);
}

/* calculate PI */
calc_pi(my_rank, num_procs);

/* shut down MPI */


MPI_Finalize();
return 0;
} Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 20
Exercice 2
a) Compilation
$mpicc -o helloMPI.exe helloMPI.c
b) Exécution
$mpirun -n 4 helloMPI.exe
c) Corriger le programme pour calculer P
1
d) Créer calculMod.c tel que P = 4 * ∫ 0
dx/(1 + x2)
e) Quelle est la version qui donne les meilleures précisions relativement à
num_intervals réduit sachant que les 25 chiffres de P sont :
Pi25 = 3,141592653589793238462643
f) Déterminer le temps d’exécution des deux versions en utilisant
MPI_Wtime()

Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 21


Algorithme de gestion des groupes
NBPROCS=8
rank1={0,1,2,3}, rank2=[4,5,6,7}
rank  identificateur du processus
p nombre total des processus
si (rank < NBPROCS / 2) alors
inclure(rank,groupe1)
Sinon
inclure (rank,groupe2)
recevoir(message,source)
écrire(message)

Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 22


P
Programme de gestion des groupes (1/2)
#include "mpi.h"
#include <stdio.h>
#define NPROCS 8

int main(argc,argv) int argc; char *argv[]; {


int rank, new_rank, sendbuf, recvbuf, ranks1[4]={0,1,2,3},ranks2[4]={4,5,6,7};
MPI_Group orig_group, new_group;
MPI_Comm new_comm;

MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
sendbuf = rank;

/* Extract the original group handle */


MPI_Comm_group(MPI_COMM_WORLD, &orig_group);
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 23
Programme de gestion des groupes (2/2)
/* Divide tasks into two distinct groups based upon rank */
if (rank < NPROCS/2)
MPI_Group_incl(orig_group, NPROCS/2, ranks1, &new_group);
else
MPI_Group_incl(orig_group, NPROCS/2, ranks2, &new_group);

/* Create new communicator and then perform collective communications */


MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm);

MPI_Allreduce(&sendbuf, &recvbuf, 1, MPI_INT, MPI_SUM, new_comm);


MPI_Group_rank (new_group, &new_rank);
printf("rank= %d newrank= %d recvbuf= %d\n",rank,new_rank,recvbuf);

MPI_Finalize();
}
Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 24
Algorithme de gestion des communicateurs
mon_rang  identificateur du processus
P  nombre total des processus
si (mon_rang < NBPROCS 0) alors
inclure(mon_rang,groupe1)
Sinon
inclure (mon_rang,groupe2)
recevoir(message,source)
écrire(message)

Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 25


Programme de gestion des communicateurs
#include <stdio.h>
#include <mpi.h>
main(int argc, char **argv) {
MPI_Comm row_comm, col_comm;
int myrank, size, P=4, Q=3, p, q;
MPI_Init (&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &myrank);
MPI_Comm_size (MPI_COMM_WORLD, &size); /* Determine row and
column position */
p = myrank / Q; q = myrank % Q; /* pick a row-major mapping */ /* Split
comm into row and column comms */
MPI_Comm_split(MPI_COMM_WORLD, p, q, &row_comm); /* color by
row, rank by column */ MPI_Comm_split(MPI_COMM_WORLD, q, p,
&col_comm); /* color by column, rank by row */
printf("[%d]:My coordinates are (%d,%d)\n",myrank,p,q);
MPI_Finalize();
} Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 26
Exercice 3

a) Compilation
$mpicc -o groupe.exe groupe.c
b) Exécution
$mpirun groupe.exe

c) Diviser MPI_COMM_WORLD en 3 communicateurs non chevauchés (non-


overlapped) tels que :

processus du rang 0, 3, 6,... appartient au premier groupe


processus du rang 1, 4, 7,... appartient au deuxième groupe
processus du rang 2, 5, 8,... appartient au troisième groupe

Architectures parallèles, M. Eleuldj, Département Génie Informatique, EMI, octobre 2014 27


Références

• Ivan Lavallée, « Algorithmique parallèle et distribuée »


Traité des nouvelles technologies, Hermes, 1990.
• Kai Hwang, « Advanced computer architecture:
Parallelism, Sqcalability, Programmability », McGraw
Hill Series in Computer Science, 1993.
• http://www.unix.mcs.anl.gov/mpi/tutorial/perf/index.ht
ml
• http://www.unix.mcs.anl.gov/mpi « MPI : A message
Passing Interface Standard », Message Passing
Interface Forum, 1995 28

Vous aimerez peut-être aussi