Partager via


3. Fonctions de bibliothèque d’exécution

Cette section décrit les fonctions de bibliothèque d’exécution C et C++ OpenMP. L’en-tête <omp.h> déclare deux types, plusieurs fonctions qui peuvent être utilisées pour contrôler et interroger l’environnement d’exécution parallèle et verrouiller les fonctions qui peuvent être utilisées pour synchroniser l’accès aux données.

Le type omp_lock_t est un type d’objet capable de représenter qu’un verrou est disponible ou qu’un thread possède un verrou. Ces verrous sont appelés verrous simples.

Le type omp_nest_lock_t est un type d’objet capable de représenter soit qu’un verrou soit disponible, soit l’identité du thread propriétaire du verrou et un nombre d’imbrications (décrit ci-dessous). Ces verrous sont appelés verrous imbriqués.

Les fonctions de bibliothèque sont des fonctions externes avec une liaison « C ».

Les descriptions de ce chapitre sont divisées en rubriques suivantes :

3.1 Fonctions d’environnement d’exécution

Les fonctions décrites dans cette section affectent et surveillent les threads, les processeurs et l’environnement parallèle :

3.1.1 fonction omp_set_num_threads

La omp_set_num_threads fonction définit le nombre par défaut de threads à utiliser pour les régions parallèles ultérieures qui ne spécifient pas de num_threads clause. Le format est le suivant :

#include <omp.h>
void omp_set_num_threads(int num_threads);

La valeur du paramètre num_threads doit être un entier positif. Son effet dépend du fait que l’ajustement dynamique du nombre de threads est activé. Pour obtenir un ensemble complet de règles sur l’interaction entre la fonction et l’ajustement omp_set_num_threads dynamique des threads, consultez la section 2.3.

Cette fonction a les effets décrits ci-dessus lorsqu’elle est appelée à partir d’une partie du programme où la omp_in_parallel fonction retourne zéro. S’il est appelé à partir d’une partie du programme où la omp_in_parallel fonction retourne une valeur différente de zéro, le comportement de cette fonction n’est pas défini.

Cet appel est prioritaire sur la variable d’environnement OMP_NUM_THREADS . La valeur par défaut du nombre de threads, qui peut être établie en appelant omp_set_num_threads ou en définissant la OMP_NUM_THREADS variable d’environnement, peut être remplacée explicitement sur une seule parallel directive en spécifiant la num_threads clause.

Pour plus d’informations, consultez omp_set_dynamic.

Références croisées

  • fonction omp_set_dynamic
  • fonction omp_get_dynamic
  • Variable d’environnement OMP_NUM_THREADS
  • clause num_threads

3.1.2 fonction omp_get_num_threads

La omp_get_num_threads fonction retourne le nombre de threads actuellement dans l’équipe exécutant la région parallèle à partir de laquelle elle est appelée. Le format est le suivant :

#include <omp.h>
int omp_get_num_threads(void);

La num_threads clause, la omp_set_num_threads fonction et la OMP_NUM_THREADS variable d’environnement contrôlent le nombre de threads d’une équipe.

Si le nombre de threads n’a pas été défini explicitement par l’utilisateur, la valeur par défaut est définie par l’implémentation. Cette fonction est liée à la directive englobante parallel la plus proche. Si elle est appelée à partir d’une partie série d’un programme ou d’une région parallèle imbriquée sérialisée, cette fonction retourne 1.

Pour plus d’informations, consultez omp_set_dynamic.

Références croisées

3.1.3 fonction omp_get_max_threads

La omp_get_max_threads fonction retourne un entier qui est garanti être au moins aussi grand que le nombre de threads qui seraient utilisés pour former une équipe si une région parallèle sans num_threads clause devait être vue à ce stade dans le code. Le format est le suivant :

#include <omp.h>
int omp_get_max_threads(void);

Le code suivant exprime une limite inférieure sur la valeur de omp_get_max_threads:

threads-used-for-next-team<= omp_get_max_threads

Notez que si une autre région parallèle utilise la num_threads clause pour demander un nombre spécifique de threads, la garantie sur la limite inférieure du résultat de omp_get_max_threads ne plus contenir.

La omp_get_max_threads valeur de retour de la fonction peut être utilisée pour allouer dynamiquement un stockage suffisant pour tous les threads de l’équipe formés à la région parallèle suivante.

Références croisées

3.1.4 fonction omp_get_thread_num

La omp_get_thread_num fonction retourne le numéro de thread, au sein de son équipe, du thread qui exécute la fonction. Le nombre de threads se situe entre 0 et omp_get_num_threads()-1, inclus. Le thread principal de l’équipe est le thread 0.

Le format est le suivant :

#include <omp.h>
int omp_get_thread_num(void);

Si elle est appelée à partir d’une région série, omp_get_thread_num retourne 0. Si elle est appelée à partir d’une région parallèle imbriquée sérialisée, cette fonction retourne 0.

Références croisées

  • fonction omp_get_num_threads

3.1.5 fonction omp_get_num_procs

La omp_get_num_procs fonction retourne le nombre de processeurs disponibles pour le programme au moment où la fonction est appelée. Le format est le suivant :

#include <omp.h>
int omp_get_num_procs(void);

3.1.6 omp_in_parallel fonction

La omp_in_parallel fonction retourne une valeur différente de zéro si elle est appelée dans l’étendue dynamique d’une région parallèle s’exécutant en parallèle ; sinon, elle retourne 0. Le format est le suivant :

#include <omp.h>
int omp_in_parallel(void);

Cette fonction retourne une valeur différente de zéro lorsqu’elle est appelée à partir d’une région s’exécutant en parallèle, y compris les régions imbriquées sérialisées.

3.1.7 omp_set_dynamic fonction

La omp_set_dynamic fonction active ou désactive l’ajustement dynamique du nombre de threads disponibles pour l’exécution de régions parallèles. Le format est le suivant :

#include <omp.h>
void omp_set_dynamic(int dynamic_threads);

Si dynamic_threads correspond à une valeur différente de zéro, le nombre de threads utilisés pour l’exécution de régions parallèles à venir peut être ajusté automatiquement par l’environnement d’exécution pour mieux utiliser les ressources système. Par conséquent, le nombre de threads spécifiés par l’utilisateur est le nombre maximal de threads. Le nombre de threads dans l’équipe exécutant une région parallèle reste fixe pendant la durée de cette région parallèle et est signalé par la omp_get_num_threads fonction.

Si dynamic_threads prend la valeur 0, l’ajustement dynamique est désactivé.

Cette fonction a les effets décrits ci-dessus lorsqu’elle est appelée à partir d’une partie du programme où la omp_in_parallel fonction retourne zéro. S’il est appelé à partir d’une partie du programme où la omp_in_parallel fonction retourne une valeur différente de zéro, le comportement de cette fonction n’est pas défini.

Un appel à avoir omp_set_dynamic la priorité sur la variable d’environnement OMP_DYNAMIC .

La valeur par défaut de l’ajustement dynamique des threads est définie par l’implémentation. Par conséquent, les codes utilisateur qui dépendent d’un nombre spécifique de threads pour une exécution correcte doivent désactiver explicitement les threads dynamiques. Les implémentations ne sont pas requises pour fournir la possibilité d’ajuster dynamiquement le nombre de threads, mais elles sont nécessaires pour fournir l’interface pour prendre en charge la portabilité sur toutes les plateformes.

Spécifique à Microsoft

La prise en charge actuelle et omp_get_dynamic omp_set_dynamic est la suivante :

Le paramètre d’entrée à omp_set_dynamic ne pas affecter la stratégie de threading et ne modifie pas le nombre de threads. omp_get_num_threads retourne toujours le nombre défini par l’utilisateur, s’il est défini ou le numéro de thread par défaut. Dans l’implémentation microsoft actuelle, omp_set_dynamic(0) désactive le threading dynamique afin que l’ensemble existant de threads puisse être réutilisé pour la région parallèle suivante. omp_set_dynamic(1) active le thread dynamique en ignorant l’ensemble existant de threads et en créant un nouvel ensemble pour la région parallèle à venir. Le nombre de threads dans le nouveau jeu est identique à l’ancien jeu et est basé sur la valeur de retour de omp_get_num_threads. Par conséquent, pour optimiser les performances, utilisez-les omp_set_dynamic(0) pour réutiliser les threads existants.

Références croisées

3.1.8 fonction omp_get_dynamic

La omp_get_dynamic fonction retourne une valeur différente de zéro si l’ajustement dynamique des threads est activé et retourne 0 sinon. Le format est le suivant :

#include <omp.h>
int omp_get_dynamic(void);

Si l’implémentation n’implémente pas l’ajustement dynamique du nombre de threads, cette fonction retourne toujours 0. Pour plus d’informations, consultez omp_set_dynamic.

Références croisées

  • Pour obtenir une description de l’ajustement dynamique des threads, consultez omp_set_dynamic.

3.1.9 fonction omp_set_nested

La omp_set_nested fonction active ou désactive le parallélisme imbriqué. Le format est le suivant :

#include <omp.h>
void omp_set_nested(int nested);

Si l’imbrication est évaluée à 0, le parallélisme imbriqué est désactivé, qui est la valeur par défaut, et les régions parallèles imbriquées sont sérialisées et exécutées par le thread actuel. Sinon, le parallélisme imbriqué est activé et les régions parallèles imbriquées peuvent déployer des threads supplémentaires pour former des équipe imbriquée s.

Cette fonction a les effets décrits ci-dessus lorsqu’elle est appelée à partir d’une partie du programme où la omp_in_parallel fonction retourne zéro. S’il est appelé à partir d’une partie du programme où la omp_in_parallel fonction retourne une valeur différente de zéro, le comportement de cette fonction n’est pas défini.

Cet appel est prioritaire sur la variable d’environnement OMP_NESTED .

Lorsque le parallélisme imbriqué est activé, le nombre de threads utilisés pour exécuter des régions parallèles imbriquées est défini par l’implémentation. Par conséquent, les implémentations compatibles OpenMP sont autorisées à sérialiser des régions parallèles imbriquées même lorsque le parallélisme imbriqué est activé.

Références croisées

3.1.10 fonction omp_get_nested

La omp_get_nested fonction retourne une valeur différente de zéro si le parallélisme imbriqué est activé et 0 s’il est désactivé. Pour plus d’informations sur le parallélisme imbriqué, consultez omp_set_nested. Le format est le suivant :

#include <omp.h>
int omp_get_nested(void);

Si une implémentation n’implémente pas le parallélisme imbriqué, cette fonction retourne toujours 0.

3.2 Fonctions de verrouillage

Les fonctions décrites dans cette section manipulent les verrous utilisés pour la synchronisation.

Pour les fonctions suivantes, la variable de verrouillage doit avoir le type omp_lock_t. Cette variable doit uniquement être accessible via ces fonctions. Toutes les fonctions de verrouillage nécessitent un argument qui a un pointeur à omp_lock_t taper.

Pour les fonctions suivantes, la variable de verrouillage doit avoir le type omp_nest_lock_t. Cette variable doit uniquement être accessible via ces fonctions. Toutes les fonctions de verrouillage imbriquées nécessitent un argument qui a un pointeur à omp_nest_lock_t taper.

Les fonctions de verrouillage OpenMP accèdent à la variable de verrou de telle sorte qu’elles lisent et mettent à jour la valeur la plus actuelle de la variable de verrou. Par conséquent, il n’est pas nécessaire qu’un programme OpenMP inclue des directives explicites flush pour s’assurer que la valeur de la variable de verrouillage est cohérente entre différents threads. (Il peut y avoir besoin de flush directives pour rendre les valeurs d’autres variables cohérentes.)

Fonctions omp_init_lock et omp_init_nest_lock 3.2.1

Ces fonctions fournissent le seul moyen d’initialiser un verrou. Chaque fonction initialise le verrou associé au verrou de paramètre à utiliser lors des appels à venir. Le format est le suivant :

#include <omp.h>
void omp_init_lock(omp_lock_t *lock);
void omp_init_nest_lock(omp_nest_lock_t *lock);

L’état initial est déverrouillé (autrement dit, aucun thread ne possède le verrou). Pour un verrou imbriqué, le nombre initial d’imbrication est égal à zéro. Il est non conforme d’appeler l’une de ces routines avec une variable de verrou qui a déjà été initialisée.

Fonctions omp_destroy_lock et omp_destroy_nest_lock 3.2.2

Ces fonctions vérifient que le verrou de variable de verrouillage pointé n’est pas initialisé. Le format est le suivant :

#include <omp.h>
void omp_destroy_lock(omp_lock_t *lock);
void omp_destroy_nest_lock(omp_nest_lock_t *lock);

Il est non conforme d’appeler l’une de ces routines avec une variable de verrou non initialisée ou déverrouillée.

Fonctions omp_set_lock et omp_set_nest_lock 3.3

Chacune de ces fonctions bloque le thread qui exécute la fonction jusqu’à ce que le verrou spécifié soit disponible, puis définit le verrou. Un verrou simple est disponible s’il est déverrouillé. Un verrou imbriqué est disponible s’il est déverrouillé ou s’il appartient déjà au thread qui exécute la fonction. Le format est le suivant :

#include <omp.h>
void omp_set_lock(omp_lock_t *lock);
void omp_set_nest_lock(omp_nest_lock_t *lock);

Pour un verrou simple, l’argument de la omp_set_lock fonction doit pointer vers une variable de verrou initialisée. La propriété du verrou est accordée au thread exécutant la fonction.

Pour un verrou imbriqué, l’argument de la omp_set_nest_lock fonction doit pointer vers une variable de verrou initialisée. Le nombre d’imbrications est incrémenté et le thread est accordé ou conserve la propriété du verrou.

Fonctions omp_unset_lock et omp_unset_nest_lock 3.2.4

Ces fonctions permettent de libérer la propriété d’un verrou. Le format est le suivant :

#include <omp.h>
void omp_unset_lock(omp_lock_t *lock);
void omp_unset_nest_lock(omp_nest_lock_t *lock);

L’argument de chacune de ces fonctions doit pointer vers une variable de verrou initialisée appartenant au thread exécutant la fonction. Le comportement n’est pas défini si le thread ne possède pas ce verrou.

Pour un verrou simple, la omp_unset_lock fonction libère le thread qui exécute la fonction à partir de la propriété du verrou.

Pour un verrou imbriqué, la omp_unset_nest_lock fonction décrémente le nombre d’imbrications et libère le thread exécutant la fonction de propriété du verrou si le nombre résultant est égal à zéro.

Fonctions omp_test_lock et omp_test_nest_lock 3.2.5

Ces fonctions tentent de définir un verrou, mais ne bloquent pas l’exécution du thread. Le format est le suivant :

#include <omp.h>
int omp_test_lock(omp_lock_t *lock);
int omp_test_nest_lock(omp_nest_lock_t *lock);

L’argument doit pointer vers une variable de verrou initialisée. Ces fonctions tentent de définir un verrou de la même manière que omp_set_lock et omp_set_nest_lock, sauf qu’elles ne bloquent pas l’exécution du thread.

Pour un verrou simple, la omp_test_lock fonction retourne une valeur différente de zéro si le verrou est correctement défini ; sinon, il retourne zéro.

Pour un verrou imbriqué, la omp_test_nest_lock fonction retourne le nouveau nombre d’imbrications si le verrou est correctement défini ; sinon, il retourne zéro.

3.3 Routines de minutage

Les fonctions décrites dans cette section prennent en charge un minuteur d’horloge murale portable :

3.3.1 fonction omp_get_wtime

La omp_get_wtime fonction retourne une valeur à virgule flottante double précision égale à la durée écoulée de l’horloge murale en secondes depuis un certain « temps dans le passé ». Le « temps passé » réel est arbitraire, mais il est garanti de ne pas changer pendant l’exécution du programme d’application. Le format est le suivant :

#include <omp.h>
double omp_get_wtime(void);

Il est prévu que la fonction sera utilisée pour mesurer les temps écoulés, comme indiqué dans l’exemple suivant :

double start;
double end;
start = omp_get_wtime();
... work to be timed ...
end = omp_get_wtime();
printf_s("Work took %f sec. time.\n", end-start);

Les heures retournées sont des « heures par thread », ce qui signifie qu’elles ne sont pas requises pour être globalement cohérentes entre tous les threads participant à une application.

3.3.2 fonction omp_get_wtick

La omp_get_wtick fonction retourne une valeur à virgule flottante double précision égale au nombre de secondes entre les cycles d’horloge successifs. Le format est le suivant :

#include <omp.h>
double omp_get_wtick(void);