OpenMP

De Wiki de Calcul Québec
Aller à : Navigation, rechercher
Autres langues :anglais 100% • ‎français 100%

Sommaire

Description

OpenMP (Open Multi-Processing) est une interface de programmation pour le calcul parallèle sur architecture à mémoire partagée. Cette API est supportée sur de nombreuses plateformes, incluant Unix et Windows, pour les langages de programmation C/C++ et Fortran. Il se présente sous la forme d'un ensemble de directives, d'une bibliothèque logicielle et de variables d'environnement.

OpenMP permet de développer rapidement des applications parallèles à petite granularité en restant proche du code séquentiel. L'approche de parallélisation OpenMP, en mémoire partagée, est radicalement différente de l'approche utilisée avec MPI en mémoire distribuée. Il n'y a qu'une seule instance du programme, exécutée en parallèle sur plusieurs processeurs. Des directives insérées dans le programme permettent de gérer la distribution des calculs entre les processeurs.

L'interface OpenMP utilise la notion de fils d'exécution (threads), bien connue en programmation orientée objet. Un fil d'exécution est un peu comme un « processeur virtuel, opérant en séquentiel ». Du point de vue du programmeur, s'il dispose de cinq fils, cela équivaut virtuellement à cinq processeurs qui peuvent effectuer du calcul en parallèle. Il est important de comprendre que le nombre de fils n'est pas associé au nombre de processeurs physiques disponibles dans l'ordinateur. Deux processeurs peuvent, par exemple, exécuter un programme possédant 10 fils. C'est le système d'exploitation qui se charge de partager le temps des processeurs disponibles entre les fils.

Cela étant dit, il est évident que si vous avez à votre disposition quatre processeurs, vous devrez utiliser au minimum quatre fils pour profiter de toute la puissance de calcul, un fil ne pouvant être exécuté sur deux processeurs en même temps. Il pourrait cependant être avantageux, dans certains cas, d'utiliser plus de fils qu'il n'existe de processeurs. Un trop grand nombre de fils n'est cependant pas à conseiller.

Un autre point important concernant les fils est la synchronisation. Lorsque plusieurs fils, d'un même programme, effectuent des calculs en même temps, on ne peut absolument pas présumer de l'ordre dans laquelle ils vont s'effectuer. La méthode exacte de distribution des fils, entre les processeurs, demeure totalement inconnu du programmeur.

Le lien suivant pointe vers un tutoriel pour débuter avec OpenMP sous linux.

Compilation

La compilation d'un code OpenMP s'effectue simplement en ajoutant une option de compilation pour la majorité des compilateurs. Pour les compilateurs GNU (GCC), il s'agit de l'option -fopenmp, pour ceux d'Intel, c'est plutôt -openmp. Pour les autres compilateurs, vérifiez leur documentation.

Les directives

Les directives OpenMP sont insérées dans les programmes Fortran en utilisant des sentinelles. Une sentinelle est un mot clé placé immédiatement après le symbole indiquant un commentaire. Par exemple :

!$OMP directive 
c$OMP directive 
C$OMP directive 
*$OMP directive

En C, les directives sont insérées en utilisant un pragma. On écrit :

#pragma omp directive


Ensemble des directives OpenMP

Fortran C et C++
!$OMP PARALLEL [clause, clause,…]

block
!$OMP END PARALLEL

#pragma omp parallel [clause, clause,…]

structured-block

!$OMP DO [ clause, clause,… ]

do_loop
!$OMP END DO

#pragma omp for [ clause, clause,… ]

for-loop

!$OMP SECTIONS [clause, clause,…]

!$OMP SECTION
block
!$OMP SECTION
block
!$OMP END SECTIONS [NOWAIT]

#pragma omp sections [clause, clause,…] {

[ #pragma omp section ]
structured-block
[ #pragma omp section ]
structured-block
}

!$OMP SINGLE [clause, clause,…]

block
!$OMP END SINGLE [NOWAIT]

#pragma omp single [clause, clause,…]

structured-block

!$OMP PARALLEL DO [clause, clause,…]

DO_LOOP
[ !$OMP END PARALLEL DO ]

#pragma omp parallel for [clause, clause,…]

for-loop

!$OMP PARALLEL SECTIONS [clause, clause,…]

!$OMP SECTION
block
!$OMP SECTION
block
!$OMP END PARALLEL SECTIONS

#pragma omp parallel sections [clause, clause,…] {

[ #pragma omp section ]
structured-block
[ #pragma omp section ]
structured-block
}

!$OMP MASTER

block
!$OMP END MASTER

#pragma omp master

structured-block

!$OMP CRITICAL [(name)]

block
!$OMP END CRITICAL [(name)]

#pragma omp critical [(name)]

structured-block

!$OMP BARRIER #pragma omp barrier
!$OMP ATOMIC

expresion_statement

#pragma omp atomic

expression-statement

!$OMP FLUSH [(list)] #pragma omp flush [(list)]
!$OMP ORDERED

block
!$OMP END ORDERED

#pragma omp ordered

structured-block

!$OMP THREADPRIVATE( /cb/[, /cb/]…) #pragma omp threadprivate ( list )
Les clauses
PRIVATE ( list ) private ( list )
SHARED ( list ) shared ( list )
SHARED | NONE ) none )
FIRSTPRIVATE ( list ) firstprivate ( list )
LASTPRIVATE ( list ) lastprivate ( list )
intrinsic } : list ) reduction ( op : list )
IF ( scalar_logical_expression ) if ( scalar-expression )
COPYIN ( list ) copyin ( list )
NOWAIT nowait

Environnement

Les quatre variables d'environnement suivantes influencent l'exécution d'un programme OpenMP. Selon l'interpréteur de commandes utilisé, elles peuvent être modifiées avec la commande UNIX « export NomVariable=valeur », ou « setenv », etc.

OMP_SCHEDULE
OMP_NUM_THREADS
OMP_DYNAMIC
OMP_NESTED

Dans la plupart des cas, vous voudrez utiliser OMP_NUM_THREADS = ppn où ppn est le nombre de processus réservés par machine. Ceci pourrait être différent pour une application hybride OpenMP/MPI.

La deuxième variable d'environnement la plus importante est probablement OMP_SCHEDULE. Celle-ci contrôle comment sont distribuées les boucles (et plus généralement les sections parallèles). La valeur par défaut dépend du compilateur, et peut être supplantée dans le code source. Les valeurs possibles sont static,n, dynamic,n, guided,n ou auto. Dans les trois premiers cas, n indique le nombre d'itérations gérées par chaque fil d'exécution. Dans le cas static, ce nombre d'itérations est fixe, et les itérations sont distribuées au début de la section parallèle. Dans le cas dynamic, le nombre d'itérations est fixe, mais les itérations sont distribuées pendant l'exécution, en fonction du temps requis par chaque fil pour exécuter ses itérations. Dans le cas guided, n indique le nombre minimal d'itérations. Le nombre d'itérations est d'abord choisi « grand », puis diminue dynamiquement au fur et à mesure que le nombre restant d'itérations diminue. Pour le mode auto, le compilateur et la bibliothèque sont libres de faire des choix.

L'avantage des cas dynamic, guided et auto est qu'ils permettent en théorie de mieux balancer les fils d'exécution, puisqu'ils s'ajustent dynamiquement selon le temps requis par chaque fil. Leur désavantage est par contre que vous ne savez pas à l'avance quel processeur exécutera quel fil, et aura besoin d'accéder à quelle mémoire. Il est ainsi impossible avec ces types de planification, de prévoir l'affinité entre la mémoire et le processeur exécutant le calcul. Ceci peut être particulièrement problématique dans une architecture NUMA.

D'autres variables d'environnement sont aussi disponibles. Certaines sont spécifiques à un compilateur alors que d'autres sont plus génériques. Pour la liste exhaustive pour le compilateur Intel, voir le site suivant, et pour les compilateurs Gnu, voir celui-ci.

Les variables d'environnement spécifiques au compilateur Intel débutent par KMP_ alors que celles spécifiques à Gnu débutent par GOMP_. Pour des performances optimales en accès mémoire, il sera important de fixer les variables

 OMP_PROC_BIND

ainsi que les variables d'affinité,

 KMP_AFFINITY

pour Intel, et

 GOMP_CPU_AFFINITY

pour les compilateurs Gnu. Ceci permettra d'éviter que les fils d'exécution OpenMP se déplacent d'un processeur à l'autre. C'est particulièrement important dans une architecture NUMA telle que retrouvée sur la plupart des architectures modernes.

Exemples

Exemple pour l'utilisation de base d'OpenMP

Exemple pour l'utilisation de l'attribut SAVE

Exemple pour l'utilisation de la directive THREADPRIVATE et de la clause COPYIN

Exemple pour l'utilisation des clauses PRIVATE et FIRSTPRIVATE

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager