You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Travaux pratique d'Informatique Parallèle et Distribuée, UMONS/Polytech, TP 1 1<br />
1.Programmation de systèmes à mémoire partagée avec l'API OpenMP<br />
1.1.Objectifs<br />
Les objectifs de la séance sont de:<br />
1.2.Généralités<br />
● se familiariser avec la syntaxe d'OpenMP<br />
● réaliser des programmes multithreadés exploitant les multiples cores/processeurs<br />
OpenMP est une API permettant la programmation d'applications parallèles à mémoire partagée<br />
en langage C/C++ ou Fortran.<br />
Son fonctionnement repose sur la définition de sections de code parallèles permettant un partage<br />
du calcul à réaliser et d'un ensemble d'étapes de synchronisation. L'exécution est multithreadée et n'a<br />
donc d'intérêt que sur des machines à mémoire partagée multiprocesseurs et/ou multicores (ce qui est le<br />
cas des PC utilisés dans la salle informatique).<br />
De nombreux compilateurs open source (e.g. gcc à partir de la version 4.2) et propriétaires (e.g.<br />
IBM, Intel, Portland Group) implémentent la spécification OpenMP.<br />
1.3.Généralités sur la programmation multi-threadée<br />
Un programme multithreadé se caractérise par un ensemble de fils d'exécution se déroulant<br />
simultanément sur des unités de traitements différentes (core/processeur) au sein d'un unique processus.<br />
L'ordonnancement des fils d'exécution et le partage du temps de calcul sur la machine sont réalisés par le<br />
système d'exploitation (e.g. le noyau Linux).<br />
La création d'une telle application nécessite donc d'identifier les sections denses en terme de<br />
quantité de calculs et de déterminer une manière de diviser le travail en différentes parties. Le processus<br />
principal (thread principal) donne alors naissance à un ensemble de threads qui s'exécutent en parallèle:<br />
Thread<br />
principal<br />
Section<br />
parallèle<br />
Thread<br />
principal<br />
FORK JOIN<br />
(synchronisation)<br />
UMONS/Polytech<br />
Pierre Manneback, Sébastien Frémal, Sébastien Noël <strong>2012</strong>13
Travaux pratique d'Informatique Parallèle et Distribuée, UMONS/Polytech, TP 1 2<br />
1.4.Utilisation d'OpenMP avec gcc<br />
Lors des séances de TP, nous utiliserons le compilateur GNU gcc en spécifiant l'option de<br />
compilation fopenmp afin de lui permettre d'interpréter les directives OpenMP. La compilation d'un<br />
code code.c se fera donc de la manière suivante:<br />
gcc code.c o executable fopenmp<br />
L'entête omp.h doit également être inclus en début de code:<br />
#include <br />
Une section parallèle OpenMP est spécifiée par une construction du type:<br />
#pragma omp parallel<br />
{<br />
...<br />
}<br />
Lorsqu'un thread principal atteint une section parallèle, il crée un groupe de n threads dont il<br />
devient le maître. Le nombre n de threads créés dépend du nombre d'unités de traitement sur la machine<br />
utilisée. Implicitement, les threads s'attendent mutuellement en sortie d'une section parallèle sauf si<br />
l'option nowait à été spécifiée dans la déclaration de la section:<br />
#pragma omp parallel nowait<br />
Les variables déclarées avant la section parallèle et devant être manipulées par les threads sont<br />
spécifiées dans la déclaration de la section parallèle en tant que partagée (shared) ou privée (private):<br />
#pragma omp parallel private(i,j) → chaque thread dispose d'une copie locale de i et j<br />
#pragma omp parallel shared(n) → chaque thread partage l'accès à une unique variable n<br />
Une opération de réduction (e.g. somme globale) peut être opérée sur une variable: de cette<br />
manière, chaque thread travaille sur une variable privée et une réduction de la valeur des variables est<br />
opérée en sortie de la section parallèle:<br />
#pragma omp parallel reduction(+:i)<br />
→ chaque thread dispose d'une copie de i et la somme<br />
de toutes les valeurs de i est réalisée en sortie de<br />
section parallèle<br />
Un test peut être réalisé si l'on souhaite conditionner la création d'un groupe de threads suivant la<br />
valeur d'un paramètre donné:<br />
#pragma omp parallel if ( n > 3 )<br />
→ le groupe de threads n'est créé que si le test est vrai<br />
UMONS/Polytech<br />
Pierre Manneback, Sébastien Frémal, Sébastien Noël <strong>2012</strong>13
Travaux pratique d'Informatique Parallèle et Distribuée, UMONS/Polytech, TP 1 3<br />
a) Partage du travail<br />
Quatre « schémas » sont mis à disposition par OpenMP pour diviser le travail entre les différents<br />
threads au sein d'une section parallèle:<br />
#pragma omp for<br />
for(i=0;i
Travaux pratique d'Informatique Parallèle et Distribuée, UMONS/Polytech, TP 1 4<br />
• Barrier<br />
Une autre directive permet de synchroniser tous les threads de la section parallèle en attendant<br />
que tous atteignent un certain point dans le programme:<br />
#pragma omp barrier<br />
c) Fonctions OpenMP<br />
Un ensemble de fonctions est mis à disposition pour réaliser certaines opérations sur<br />
l'environnement OpenMP.<br />
void omp_set_num_threads(int num_threads) Spécifie le nombre de threads à utiliser (doit être<br />
déclaré avant une section parallèle)<br />
int omp_get_num_threads(void) Retourne le nombre de threads dans la section<br />
parallèle<br />
int omp_get_thread_num(void) Retourne le numéro du thread appelant<br />
int omp_get_num_procs(void) Retourne le nombre d'unités de traitement<br />
double omp_get_wtime(void) Retourne le nombre de secondes écoulées<br />
UMONS/Polytech<br />
Pierre Manneback, Sébastien Frémal, Sébastien Noël <strong>2012</strong>13
Travaux pratique d'Informatique Parallèle et Distribuée, UMONS/Polytech, TP 1 5<br />
1.5.Exercices<br />
a) Exercice 1<br />
Écrire un programme affichant un message quelconque(e.g. « Hello world »).<br />
Intégrer cet affichage à une section parallèle et ajouter au message les informations suivantes:<br />
● le nombre de threads créés<br />
● le numéro du thread affichant le message<br />
● le nombre d'unités de traitement sur la machine utilisée<br />
Ajouter ensuite une boucle parallèle afin d'afficher le message 10 fois.<br />
b)Exercice 2.1<br />
On souhaite réaliser un programme capable de calculer la somme des nombres premiers<br />
inférieurs à une valeur donnée n.<br />
La valeur de n sera passée comme argument dans la ligne de commande:<br />
./ex1 100000<br />
aura pour effet de calculer la somme des nombres premiers inférieurs à 100000 (remarque: en<br />
vue de tester votre programme, le résultat à trouver vaut : 454396537).<br />
Dans un premier temps, aucune directive OpenMP ne sera utilisée, le programme étant alors<br />
exécuté séquentiellement.<br />
Observer le temps d'exécution à l'aide de la commande unix time.<br />
c) Exercice 2.2<br />
time ./ex1 100000<br />
Paralléliser l'exercice 1 à l'aide d'une boucle parallèle OpenMP et d'une variable partagée.<br />
Remarque:<br />
● Protéger l'accès à la variable partagée result.<br />
● Tester différentes politiques d'ordonnancement à l'aide de l'option schedule et<br />
observer leur impact sur le temps de calcul.<br />
d)Exercice 2.3<br />
Utiliser la directive reduction pour remplacer la variable partagée result.<br />
UMONS/Polytech<br />
Pierre Manneback, Sébastien Frémal, Sébastien Noël <strong>2012</strong>13
Travaux pratique d'Informatique Parallèle et Distribuée, UMONS/Polytech, TP 1 6<br />
e) Exercice 3<br />
Lire et comprendre le premier programme séquentiel fourni en annexe.<br />
Ce programme permet la création d'un tableau de particules positionnées aléatoirement dans un<br />
espace virtuel à 3 dimensions. Le nombre de particules est fourni en argument au lancement du<br />
programme. La distance entre les particules prises 2 à 2 est ensuite évaluée et le programme fournit le<br />
numéro des 2 particules les plus proches ainsi que la distance qui les sépare.<br />
Paralléliser ce programme en utilisant les directives OpenMP afin d'obtenir le meilleur temps<br />
d'exécution.<br />
Estimer le nombre minimum de particules en dessous duquel la parallélisation n'améliore pas les<br />
performances; introduire alors un test « if » sur ce nombre minimum conditionnant la création des<br />
threads.<br />
f) Exercice 4<br />
Lire et comprendre le second programme séquentiel fourni en annexe.<br />
Ce programme calcul le nombre de partitions de x en au plus y parties (noté d(x,y)), ce qui<br />
signifie qu'il calcule le nombre de combinaisons d'au plus y chiffres et dont la somme vaut x. Exemple :<br />
d(5,3) = {5} + {4+1} + {3+2} + {1+1+3} + {1+2+2} = 5<br />
Soit d'(x,y) le nombre de partitions qui comprennent exactement y chiffres (soit 2 dans notre<br />
exemple si y vaut 3), alors d(x,y) = d'(x,y) + d(x,y1) (nombre de partitions de x en au plus y parties =<br />
nombre de partitions de x en exactement y parties + nombre de partitions de x en au plus (y1) parties).<br />
Il a été démontré que d'(x,y) = d(xy,y) 1 et ainsi :<br />
d(x,y) = d(xy,y) + d(x,y1)<br />
Paralléliser ce programme en utilisant les directives OpenMP afin d'optimiser le temps de calcul.<br />
1. S. Skiena, Implementing Discrete Mathematics: Combinatorics and Graph Theory<br />
with Mathematica. Reading, MA: AddisonWesley, 1990, p.58<br />
UMONS/Polytech<br />
Pierre Manneback, Sébastien Frémal, Sébastien Noël <strong>2012</strong>13