Vous êtes sur la page 1sur 61

PROGRAMMATION HAUT

PERFORMANCE
Pr. J. Abouchabaka Master Big Data et Cloud Computing
Organisation
2

Cours:
 Le cours est divisé en trois parties

Travaux pratiques:
 Des exercices seront effectués en parallèles avec le
cours.

Mini-projets:
 Des mini-projets vous seront distribués une fois on a
terminé la première partie du cours.
Evaluation
3

 Examen final: 40%


 Travaux pratiques: 30%
 Mini-projets: 30%
4

Sommaire
I. Programmation en MPI
II. Programmation en OpenMP
III. Programmation Hybride
Partie I : Programmation en MPI
Plan de la partie
6

1. Introduction
2. Environnements
3. Communications point à point
4. Communications collectives
5. Optimisations
6. Types de données dérivés
7. Topologies
8. Communicateurs
7 1. Introduction
1.1 Historique de MPI
1.2 Définitions
1.3 Concepts de l’échange de messages
1.1 Historique de MPI
8

 Novembre 92 (Supercomputing’92 ) : ((formalisation))


d’un groupe de travail créé en avril 92

 et décision d’adopter les structures et les méthodes du


groupe HPF (High Performance Fortran).

 Brouillon de MPI-1 présenté en novembre 93


(Supercomputing ’93), finalisé en mars 1994.

 Cette version vise à la fois la portabilité et la garantie


de bonnes performances.
1.1 Historique de MPI
9

 MPI-2 publié en juillet 97, suite à des travaux ayant


commencé au printemps 95.

 Standard non élaboré par les organismes officiels de


normalisation (ISO, ANSI, etc.).

 D’autres versions sont apparues par la suite:


 MPI-1.2 (Juillet 1997) et MPI-1.3 (Mai 2008)
 MPI-2.1 (Sep 2008), et MPI-2.2 (Sep 2009)
 Sep 2012: le MPI-3.0 standard a été approuvé.
1.2 Définitions
10

Le modèle de programmation séquentiel :


 le programme est exécuté par un et un seul processus;
 toutes les variables du programme sont allouées dans la
mémoire centrale allouée au processus;
 un processus s’exécute sur un processeur physique de la
machine.
1.2 Définitions
11

Le modèle de programmation par échange de


messages :
 le programme est écrit dans un langage classique (Fortran,
C ou C++) ;
 chaque processus exécute éventuellement des parties
différentes d’un programme ;
 toutes les variables du programme sont privées et résident
dans la mémoire locale allouée à chaque processus ;
 une donnée est échangée entre deux ou plusieurs processus
via un appel, dans le programme, à des sous-programmes
particuliers.
1.2 Définitions
12
1.2 Définitions
13

Le modèle d’exécution SPMD :


 Single Program, Multiple Data ;
 le même programme est exécuté par tous les processus;

 toutes les machines supportent ce modèle de


programmation et certaines ne supportent que celui-là ;
 c’est un cas particulier du modèle plus général MPMD
(Multiple Program, Multiple Data), qu’il peut d’ailleurs
émuler.
1.2 Définitions
14
1.2 Définitions
15

Exemple en C d’émulation MPMD en SPMD


1.3 Concepts d’échange de messages
16

 Si un message est envoyé à un processus, celui-ci


doit ensuite le recevoir
1.3 Concepts d’échange de messages
17

 Un message est constitué de paquets de données


transitant du processus émetteur au(x) processus
récepteur(s)
 En plus des données (variables scalaires, tableaux,
etc.) à transmettre, un message doit contenir les
informations suivantes :
 l’identificateur du processus émetteur ;
 le type de la donnée ;
 sa longueur ;
 l’identificateur du processus récepteur.
1.3 Concepts d’échange de messages
18
1.3 Concepts d’échange de messages
19

 Les messages échangés sont interprétés et gérés


par un environnement qui peut être comparé :
à la téléphonie ;
 à la télécopie ;

 au courrier postal ;

 à une messagerie électronique ;

 etc.

 Le message est envoyé à une adresse déterminée


1.3 Concepts d’échange de messages
20

 Le processus récepteur doit pouvoir classer et


interpréter les messages qui lui ont été adressés

 L’environnement en question est MPI-1 (Message


Passing Interface). Une application MPI est un
ensemble de processus autonomes exécutant chacun
leur propre code et communiquant via des appels à
des sous-programmes de la bibliothèque MPI
1.3 Concepts d’échange de messages
21

 Ces sous-programmes peuvent être classés dans les


grandes catégories suivantes :
 environnement ;
 communications point à point ;

 communications collectives ;

 types de données dérivés ;

 topologies ;

 groupes et communicateurs.
22 2. Environnement
2.1 Description
2.2 Exemple
TP 1
2.1 Description
23

 Toutes les opérations effectuées par MPI portent sur des


communicateurs. Le communicateur par défaut est
MPI_COMM_WORLD qui comprend tous les processus actifs.
2.1 Description
24

 A tout instant, on peut connaître le nombre de processus gérés


par un communicateur donné par la fonction MPI_Comm_size():

 De même, la fonction MPI_Comm_rank() permet d’obtenir le


rang d’un processus (i.e. son numéro d’instance compris entre 0
et la valeur renvoyée par MPI_Comm_size() – 1) :
2.2 Exemple
25
TP 1
26

Gestion de l’environnement de MPI : affichage d’un message par


chacun des processus, mais différent selon qu’ils sont de rang pair
ou impair.
Corrigé du TP 1
27

#include "mpi.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
int rang, nb_processus;
MPI_Init( &argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rang);
MPI_Comm_size(MPI_COMM_WORLD, &nb_processus);

if ( (rang % 2) == 0)
printf("Coucou, je suis le processus pair %d\n", rang);
else
printf("Coucou, je suis le processus impair %d\n", rang);

MPI_Finalize();
return 0;
}
28 3. Communications point à point
3.1 Notions générale
3.2 Types de données de base
3.3 Autres possibilités
3.4 Exemple : anneau de communication
3.5 Construction et reconstruction de messages
TP2 : ping-pong
3.1 Notions générale
29

 Une communication dite point à point a lieu entre


deux processus, l’un appelé processus émetteur et
l’autre processus récepteur (ou destinataire).
3.1 Notions générale
30

 L’émetteur et le récepteur sont identifiés par leur


rang dans le communicateur.

 Ce que l’on appelle l’enveloppe d’un message est


constituée :
 du rang du processus émetteur ;
 du rang du processus récepteur ;
 de l’étiquette (tag) du message ;
 du nom du communicateur qui définira le contexte de
communication de l’opération.
3.1 Notions générale
31

 Les données échangées sont typées (entiers, réels,


etc. ou types dérivés personnels).

 Il existe dans chaque cas plusieurs modes de


transfert, faisant appel à des protocoles différents
qui seront vus après.
3.1 Notions générale
32
3.2 Types de données de base
33
3.3 Autres possibilités
34

 A la réception d’un message, le rang du processus et l’étiquette


peuvent être des ((jokers)), respectivement MPI_ANY_SOURCE et
MPI_ANY_TAG.

 Une communication avec le processus ((fictif)) de rang


MPI_PROC_NULL n’a aucun effet.

 Il existe des variantes syntaxiques, MPI_Sendrecv() et


MPI_Sendrecv_replace(), qui enchaînent un envoi et une réception.

 On peut créer des structures de données plus complexes à l’aide de


sous-programmes tels que MPI_Type_contiguous(),
MPI_Type_vector(), MPI_Type_indexed() et MPI_Type_struct()
(notion vu après).
3.3 Autres possibilités
35
3.3 Autres possibilités
36
3.3 Autres possibilités
37

 Attention ! Il convient de noter que si le sous-programme MPI_Send()


est implémenté de façon bloquante (notion vu après) dans la version
de la bibliothèque MPI mise en oeuvre, le code précédent serait en
situation de verrouillage si à la place de l’ordre MPI_Sendrecv() on
utilisait un ordre MPI_Send() suivi d’un ordre MPI_Recv().
 En effet, chacun des deux processus attendrait un ordre de
réception qui ne viendrait jamais, puisque les deux envois resteraient
en suspens. Pour des raisons de portabilité, il faut donc absolument
éviter ces cas-l.
3.4 Exemple : anneau de communication
38
3.4 Exemple : anneau de communication
39

 Si tous les processus font un envoi puis une réception,


toutes les communications pourront potentiellement
démarrer simultanément et n’auront donc pas lieu en
anneau (outre le problème déjà mentionné de
portabilité, au cas où l’implémentation du MPI_Send()
est faite de façon bloquante dans la version de la
bibliothèque MPI mise en œuvre) :
3.4 Exemple : anneau de communication
40

 Pour que les communications se fassent réellement en anneau, à


l’image d’un passage de jeton entre processus, il faut procéder
différemment et faire en sorte qu’un processus initie la chaîne :
3.4 Exemple : anneau de communication
41

 Pour que les communications se fassent réellement en anneau, à


l’image d’un passage de jeton entre processus, il faut procéder
différemment et faire en sorte qu’un processus initie la chaîne :

Pr. J. Abouchabaka
3.4 Exemple : anneau de communication
42

 Pour que les communications se fassent réellement en anneau, à


l’image d’un passage de jeton entre processus, il faut procéder
différemment et faire en sorte qu’un processus initie la chaîne :
3.4 Exemple : anneau de communication
43

 Pour que les communications se fassent réellement en anneau, à


l’image d’un passage de jeton entre processus, il faut procéder
différemment et faire en sorte qu’un processus initie la chaîne :
3.4 Exemple : anneau de communication
44

 Pour que les communications se fassent réellement en anneau, à


l’image d’un passage de jeton entre processus, il faut procéder
différemment et faire en sorte qu’un processus initie la chaîne :
3.4 Exemple : anneau de communication
45

 Pour que les communications se fassent réellement en anneau, à


l’image d’un passage de jeton entre processus, il faut procéder
différemment et faire en sorte qu’un processus initie la chaîne :
3.4 Exemple : anneau de communication
46

 Pour que les communications se fassent réellement en anneau, à


l’image d’un passage de jeton entre processus, il faut procéder
différemment et faire en sorte qu’un processus initie la chaîne :
3.4 Exemple : anneau de communication
47

 Pour que les communications se fassent réellement en anneau, à


l’image d’un passage de jeton entre processus, il faut procéder
différemment et faire en sorte qu’un processus initie la chaîne :
3.4 Exemple : anneau de communication
48

Pr. J. Abouchabaka
3.4 Exemple : anneau de communication
49
3.5 Construction et reconstruction de messages
50
3.5 Construction et reconstruction de messages
51
3.5 Construction et reconstruction de messages
52

Pr. J. Abouchabaka
TP2 : ping-pong
53

 Communications point à point : ping-pong entre deux processus


 Envoyer un message contenant 1000 réels du processus 0 vers le
processus 1 (il s’agit alors seulement d’un ping)
 Faire une version ping-pong où le processus 1 renvoie le message reçu
au processus 0 et mesurer le temps de communication à l’aide de la
fonction MPI_Wtime()
 Faire une version où l’on fait varier la taille du message dans une boucle
et mesurer les temps de communication respectifs ainsi que les débits
 Les mesures de temps peuvent se faire de la façon suivante :
Corrigé du TP2: version 1
54

/*
* TP2 : Communications point à point : envoi d'un message du
processus 0 au processus 1
*
*/

#include "mpi.h"
#include <stdlib.h>
#include <stdio.h>

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


int rang,iter;
int nb_valeurs=1000;
int etiquette=99;
double valeurs[nb_valeurs];
MPI_Status statut;
Corrigé du TP2: version 1
55

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rang);

if (rang == 0) {
for (iter = 0; iter<nb_valeurs; iter++)
valeurs[iter] = rand() / (RAND_MAX + 1.);
MPI_Send(valeurs,nb_valeurs,MPI_DOUBLE,1,etiquette,MPI_COMM_WORLD);
} else if(rang == 1) {

MPI_Recv(valeurs,nb_valeurs,MPI_DOUBLE,0,etiquette,MPI_COMM_WORLD,&statut)
;
printf("Moi, processus 1, j'ai recu %d valeurs (derniere = %g)"
"du processus 0.\n", nb_valeurs, valeurs[nb_valeurs-1]);
}

MPI_Finalize();
return 0;
}
Corrigé du TP2: version 2
56

/*
* TP2 : Communications point à point : envoi d'un message du
processus 0 au processus 1
*
*/

#include "mpi.h"
#include <stdlib.h>
#include <stdio.h>

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


int rang,iter;
int nb_valeurs=1000;
int etiquette=99;
double valeurs[nb_valeurs];
MPI_Status statut;
Corrigé du TP2: version 2
57

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rang);

if (rang == 0) {
for (iter = 0; iter<nb_valeurs; iter++)
valeurs[iter] = rand() / (RAND_MAX + 1.);
temps_debut=MPI_Wtime();
MPI_Send(valeurs,nb_valeurs,MPI_DOUBLE,1,etiquette,MPI_COMM_WORLD);
MPI_Recv(valeurs,nb_valeurs,MPI_DOUBLE,1,etiquette,MPI_COMM_WORLD,&statut);
temps_fin=MPI_Wtime();
printf("Moi, processus 0, j'ai envoye et recu %d valeurs"
"(derniere = %g) du processus 1 en %f secondes.\n",
nb_valeurs, valeurs[nb_valeurs-1], temps_fin-temps_debut);
} else if(rang == 1) {
MPI_Recv(valeurs,nb_valeurs,MPI_DOUBLE,0,etiquette,MPI_COMM_WORLD,&statut);
MPI_Send(valeurs,nb_valeurs,MPI_DOUBLE,0,etiquette,MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
Corrigé du TP2: version 3
58

/*
* TP2 : Communications point à point : envoi d'un message du
processus 0 au processus 1
*
*/

#include "mpi.h"
#include <stdlib.h>
#include <stdio.h>

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


int rang,iter;
int nb_valeurs=1000;
int etiquette=99;
double valeurs[nb_valeurs];
MPI_Status statut;
Corrigé du TP2: version 3
59

MPI_Init(&argc, &argv);

nb_valeurs[0]=0,nb_valeurs[1]=1,nb_valeurs[2]=10,nb_valeurs[3]=100;
nb_valeurs[4]=1000,nb_valeurs[5]=10000,nb_valeurs[6]=100000;
nb_valeurs[7]=1000000,nb_valeurs[8]=7000000;

MPI_Comm_rank(MPI_COMM_WORLD, &rang);

valeurs = (double *) malloc(nb_valeurs_max*sizeof(double));

for(iter=0; iter<nb_tests; iter++) {


if (rang == 0) {
for (iter2 = 0; iter2<nb_valeurs[iter]; iter2++)
valeurs[iter2] = rand() / (RAND_MAX + 1.);
temps_debut=MPI_Wtime();
MPI_Send(valeurs,nb_valeurs[iter],MPI_DOUBLE,1,etiquette,MPI_COMM_WORLD);
MPI_Recv(valeurs,nb_valeurs[iter],MPI_DOUBLE,1,etiquette,
MPI_COMM_WORLD,&statut);
temps_fin=MPI_Wtime();
Corrigé du TP2: version 3
60
if (nb_valeurs[iter] != 0) {
printf("Moi, processus 0, j'ai envoye et recu %8d valeurs"
"(derniere = %4.2f) du processus 1 en %8.6f secondes, soit "
"avec un debit de %7.2f Mo/s.\n",
nb_valeurs[iter], valeurs[nb_valeurs[iter]-1],
temps_fin-temps_debut,
2.*nb_valeurs[iter]*8/1000000./(temps_fin-temps_debut));
} else
printf("Moi, processus 0, j'ai envoye et recu %8d valeurs en %8.6f "
"secondes, soit avec un debit de %7.2f Mo/s.\n",
nb_valeurs[iter], temps_fin-temps_debut,
2.*nb_valeurs[iter]*8/1000000./(temps_fin-temps_debut));
} else if(rang == 1) {
MPI_Recv(valeurs,nb_valeurs[iter],MPI_DOUBLE,0,etiquette,
MPI_COMM_WORLD,&statut);
MPI_Send(valeurs,nb_valeurs[iter],MPI_DOUBLE,0,etiquette,MPI_COMM_WORLD);
}
}

MPI_Finalize();
return 0;
}
Fin de la Séance

Vous aimerez peut-être aussi