Partager via


1. Introduction

Ce document spécifie une collection de directives du compilateur, de fonctions de bibliothèque et de variables d’environnement que vous pouvez utiliser pour spécifier le parallélisme en mémoire partagée dans les programmes C et C++. Les fonctionnalités décrites dans ce document sont appelées collectivement l’interface de programme d’application OpenMP C/C++ (API). L’objectif de cette spécification est de fournir un modèle de programmation parallèle qui permet à un programme d’être portable entre les architectures de mémoire partagée provenant de différents fournisseurs. Les compilateurs de nombreux fournisseurs prennent en charge l’API OpenMP C/C++. Pour plus d’informations sur OpenMP, y compris l’interface du programme d’application OpenMP Fortran, consultez le site web suivant :

https://www.openmp.org

Les directives, fonctions de bibliothèque et variables d’environnement définies dans ce document vous permettent de créer et de gérer des programmes parallèles tout en autorisant la portabilité. Les directives étendent le modèle de programmation séquentielle C et C++ avec des constructions de données multiples de programme unique (SPMD), des constructions de partage de travail et des constructions de synchronisation. Ils soutiennent également le partage et la privatisation des données. Les compilateurs qui prennent en charge l’API C et C++ OpenMP incluent une option de ligne de commande pour le compilateur qui active et autorise l’interprétation de toutes les directives du compilateur OpenMP.

1.1 Portée

Cette spécification couvre uniquement la parallélisation dirigée par l’utilisateur, où vous définissez explicitement les actions que le compilateur et le système d’exécution prennent pour exécuter le programme en parallèle. Les implémentations C et C++ OpenMP ne sont pas requises pour rechercher les dépendances, les conflits, les blocages, les conditions de concurrence ou d’autres problèmes qui entraînent une exécution incorrecte du programme. Vous êtes chargé de vous assurer que l’application utilisant les constructions de l’API C et C++ OpenMP s’exécute correctement. La parallélisation et les directives automatiques générées par le compilateur pour faciliter cette parallélisation ne sont pas abordées dans ce document.

1.2 Définition des termes

Les termes suivants sont utilisés dans ce document :

  • barrier

    Point de synchronisation auquel tous les threads d’une équipe doivent atteindre. Chaque thread attend que tous les threads de l’équipe arrivent à ce stade. Il existe des obstacles explicites identifiés par les directives et les obstacles implicites créés par la mise en œuvre.

  • construct

    Une construction est une instruction. Il se compose d’une directive, suivie d’un bloc structuré. Certaines directives ne font pas partie d’une construction. (Voir openmp-directive dans l’annexe C).

  • directive

    Un C ou C++ #pragma suivi de l’identificateur omp , d’un autre texte et d’une nouvelle ligne. La directive spécifie le comportement du programme.

  • extension dynamique

    Toutes les instructions dans l’étendue lexicale, ainsi que toute instruction à l’intérieur d’une fonction exécutée à la suite de l’exécution d’instructions dans l’étendue lexicale. Une extension dynamique est également appelée région.

  • étendue lexicale

    Instructions lexicalement conservées dans un bloc structuré.

  • thread principal

    Thread qui crée une équipe lorsqu’une région parallèle est entrée.

  • région parallèle

    Instructions qui se lient à une construction parallèle OpenMP et peuvent être exécutées par de nombreux threads.

  • private

    Une variable privée nomme un bloc de stockage unique au thread faisant référence. Il existe plusieurs façons de spécifier qu’une variable est privée : une définition au sein d’une région parallèle, d’une directive, d’une threadprivate privateclause firstprivateou lastprivatereduction d’une clause ou d’utiliser la variable comme for variable de contrôle de boucle dans une for boucle immédiatement après une for ou parallel for une directive.

  • region

    Étendue dynamique.

  • région série

    Instructions exécutées uniquement par le thread principal en dehors de l’étendue dynamique de n’importe quelle région parallèle.

  • serialize

    Pour exécuter une construction parallèle avec :

    • une équipe de threads constitués d’un seul thread (qui est le thread principal pour cette construction parallèle),

    • ordre d’exécution de série pour les instructions dans le bloc structuré (le même ordre que si le bloc ne faisait pas partie d’une construction parallèle) et

    • aucun effet sur la valeur retournée par omp_in_parallel() (en dehors des effets des constructions parallèles imbriquées).

  • partagé

    Une variable partagée nomme un bloc de stockage unique. Tous les threads d’une équipe qui accèdent à cette variable accèdent également à ce bloc de stockage unique.

  • bloc structuré

    Un bloc structuré est une instruction (unique ou composée) qui a une entrée unique et une seule sortie. S’il existe un saut dans ou hors d’une instruction, cette instruction est un bloc structuré. (Cette règle inclut un appel à longjmp(3C) ou l’utilisation de throw, bien qu’un appel soit exit autorisé.) Si son exécution commence toujours à l’ouverture { et se termine toujours à la fermeture }, une instruction composée est un bloc structuré. Une instruction d’expression, une instruction de sélection, une instruction d’itération ou try un bloc est un bloc structuré si l’instruction composée correspondante obtenue en l’encadrant { et } serait un bloc structuré. Une instruction jump, une instruction étiquetée ou une instruction de déclaration n’est pas un bloc structuré.

  • team

    Un ou plusieurs threads collaborent dans l’exécution d’une construction.

  • thread

    Entité d’exécution disposant d’un flux de contrôle série, d’un ensemble de variables privées et d’accès aux variables partagées.

  • variable

    Identificateur, éventuellement qualifié par les noms d’espaces de noms, qui nomme un objet.

1.3 Modèle d’exécution

OpenMP utilise le modèle de jointure de fourche d’exécution parallèle. Bien que ce modèle de jointure de fourche puisse être utile pour résoudre différents problèmes, il est adapté pour les applications de grande taille basées sur des tableaux. OpenMP est destiné à prendre en charge les programmes qui s’exécutent correctement en tant que programmes parallèles (de nombreux threads d’exécution et une bibliothèque de prise en charge OpenMP complète). Il s’agit également des programmes qui s’exécutent correctement en tant que programmes séquentiels (directives ignorées et une bibliothèque de stubs OpenMP simple). Toutefois, il est possible et autorisé à développer un programme qui ne se comporte pas correctement lorsqu’il est exécuté séquentiellement. En outre, différents degrés de parallélisme peuvent entraîner des résultats numériques différents en raison de changements dans l’association d’opérations numériques. Par exemple, une réduction d’ajout en série peut avoir un modèle différent d’associations d’ajouts qu’une réduction parallèle. Ces différentes associations peuvent modifier les résultats de l’ajout à virgule flottante.

Un programme écrit avec l’API C/C++ OpenMP commence l’exécution en tant que thread unique d’exécution appelé thread principal. Le thread principal s’exécute dans une région série jusqu’à ce que la première construction parallèle soit rencontrée. Dans l’API OpenMP C/C++, la parallel directive constitue une construction parallèle. Lorsqu’une construction parallèle est rencontrée, le thread principal crée une équipe de threads et le maître devient maître de l’équipe. Chaque thread de l’équipe exécute les instructions dans l’étendue dynamique d’une région parallèle, à l’exception des constructions de partage de travail. Tous les threads de l’équipe doivent rencontrer des constructions de partage de travail dans le même ordre, et un ou plusieurs des threads exécutent les instructions dans le bloc structuré associé. La barrière implicite à la fin d’une construction de partage de travail sans nowait clause est exécutée par tous les threads de l’équipe.

Si un thread modifie un objet partagé, il affecte non seulement son propre environnement d’exécution, mais également ceux des autres threads du programme. La modification est garantie d’être terminée, du point de vue d’un autre thread, au point de séquence suivant (tel que défini dans le langage de base) uniquement si l’objet est déclaré volatile. Sinon, la modification est garantie d’être terminée après le premier thread de modification. Les autres threads ensuite (ou simultanément) voient une flush directive qui spécifie l’objet (implicitement ou explicitement). Lorsque les flush directives implicites par d’autres directives OpenMP ne garantissent pas l’ordre correct des effets secondaires, il incombe au programmeur de fournir des directives explicites supplémentaires flush .

Une fois la construction parallèle terminée, les threads de l’équipe se synchronisent à une barrière implicite, et seul le thread principal continue l’exécution. N’importe quel nombre de constructions parallèles peuvent être spécifiées dans un seul programme. Par conséquent, un programme peut fork et joindre plusieurs fois pendant l’exécution.

L’API OpenMP C/C++ permet aux programmeurs d’utiliser des directives dans les fonctions appelées à partir de constructions parallèles. Les directives qui n’apparaissent pas dans l’étendue lexicale d’une construction parallèle, mais qui peuvent se trouver dans l’étendue dynamique sont appelées directives orphelines . Avec les directives orphelines, les programmeurs peuvent exécuter des parties majeures de leur programme en parallèle, avec seulement des modifications minimales apportées au programme séquentiel. Avec cette fonctionnalité, vous pouvez coder des constructions parallèles aux niveaux supérieurs de l’arborescence des appels de programme et utiliser des directives pour contrôler l’exécution dans l’une des fonctions appelées.

Les appels non synchronisés aux fonctions de sortie C et C++ qui écrivent dans le même fichier peuvent entraîner une sortie dans laquelle les données écrites par différents threads apparaissent dans un ordre non déterministe. De même, les appels non synchronisés aux fonctions d’entrée qui lisent à partir du même fichier peuvent lire des données dans un ordre non déterministe. L’utilisation non synchronisée des E/S, de sorte que chaque thread accède à un fichier différent, produit les mêmes résultats que l’exécution série des fonctions d’E/S.

1.4 Conformité

Une implémentation de l’API C/C++ OpenMP est conforme à OpenMP si elle reconnaît et conserve la sémantique de tous les éléments de cette spécification, comme indiqué dans les chapitres 1, 2, 3, 4 et annexe C. Annexes A, B, D, E et F sont à des fins d’information uniquement et ne font pas partie de la spécification. Les implémentations qui incluent uniquement un sous-ensemble de l’API ne sont pas conformes à OpenMP.

L’API C et C++ OpenMP est une extension du langage de base pris en charge par une implémentation. Si le langage de base ne prend pas en charge une construction de langage ou une extension qui apparaît dans ce document, l’implémentation OpenMP n’est pas nécessaire pour la prendre en charge.

Toutes les fonctions de bibliothèque C et C++ standard et les fonctions intégrées (c’est-à-dire, les fonctions dont le compilateur a des connaissances spécifiques) doivent être thread-safe. L’utilisation non synchronisée de fonctions thread-safe par différents threads à l’intérieur d’une région parallèle ne produit pas de comportement non défini. Toutefois, le comportement peut ne pas être identique à celui d’une région série. (Une fonction de génération de nombres aléatoires est un exemple.)

L’API C/C++ OpenMP spécifie que certains comportements sont définis par l’implémentation . Une implémentation OpenMP conforme est nécessaire pour définir et documenter son comportement dans ces cas. Pour obtenir la liste des comportements définis par l’implémentation, consultez l’annexe E.

1.5 Références normatives

  • ISO/IEC 9899:1999, Technologie de l’information - Langages de programmation - C. Cette spécification d’API OpenMP fait référence à ISO/IEC 9899:1999 en tant que C99.

  • ISO/IEC 9899:1990, Technologies de l’information - Langages de programmation - C. Cette spécification de l’API OpenMP fait référence à ISO/IEC 9899:1990 comme C90.

  • ISO/IEC 14882:1998, Technologies de l’information - Langages de programmation - C++. Cette spécification de l’API OpenMP fait référence à ISO/IEC 14882:1998 en C++.

Là où cette spécification d’API OpenMP fait référence à C, la référence est faite au langage de base pris en charge par l’implémentation.

1.6 Organisation