• Aucun résultat trouvé

1.3 Outils de programmation et de parallélisation

1.3.2 Outils hybrides

Les outils de programmation permettant de cibler différents types d’architectures ont aussi été développés. Le niveau adopté par les différentes API/interfaces n’est pas toujours le même. Par exemple, d’un coté OpenCL fait le choix du bas niveau, tandis qu’un outil comme HMPP va, à l’instar d’OpenMP pour les GPP multicoeurs, chercher à aller au plus simple pour effec- tuer une parallélisation. Nous allons présenter brièvement les deux modèles nommés ci-dessus, ainsi qu’OpenACC, un nouveau standard émergent.

1.3.2.1 OpenCL

OpenCL est un standard ouvert et gratuit dédié à la programmation parallèle de machines hétérogènes. Il fournit aux développeurs un environnement uniformisé permettant de pro- grammer différents types de machines telles qu’un ensemble de GPP multicoeurs, de GPU, d’architectures de type Cell ou encore d’autre processeurs comme certains DSP.

Développé par Khronos group, l’objectif principal d’OpenCL est de fournir un ensemble d’applications, depuis l’embarqué jusqu’au HPC, à l’aide d’une abstraction bas-niveau, mais tout aussi portable. Il faut savoir que le consortium qui à mis au point ces spécifications est composé des principaux acteurs du marché, à savoir : AMD, Apple, ARM, Intel, Nvidia, Sony, et plusieurs autres grands groupes. Ils espèrent qu’OpenCL se place comme fondation d’un environnement informatique dédié au calcul parallèle incluant outils, middleware et applica- tions. C’est ce même consortium qui maintient et gère l’évolution d’OpenGL et d’OpenAL.

OpenCL s’appuie sur trois modèles : plateforme, exécution et mémoire.

Modèle de plateforme

Un hôte est connecté à un ou plusieurs dispositifs compatibles OpenCL. Chaque dispositif est composé d’un ou de plusieurs coeurs de calcul.

Modèle d’exécution

• Kernel : fonction de calcul basique avec parallélisme de données ou de tâches.

• Programme : ensemble de kernels et d’autres fonctions, qu’on peut voir sous forme de bibliothèque.

• File de kernels : exécutable de manière FIFO ou possibilité d’ordonnancement manuel. Modèle mémoire

Comme le montre la figure 8, la structure est calquée sur les architectures des dernières gé- nérations de GPU. Plusieurs unités de calculs, elles-mêmes sous divisées en plusieurs coeurs incluant deux niveaux de mémoires internes, et un externe au niveau de l’hôte. Ce modèle est suffisamment généraliste pour s’adapter à la future puce Intel Xeon Phi. Concernant les GPP, OpenCL est pris en charge, particulièrement pour du parallélisme de tâches, mais ce n’est clai- rement pas l’objectif premier.

Concernant ces derniers, une volonté commune de normalisation a émergé sous la forme d’OpenCL. Son lancement a été grandement favorisé par Mac OS qui inclut l’accès à l’API OpenCL dans le but d’accélérer des tâches ponctuelles. Les principaux partenaires du consor- tium étant Apple, Nvidia et AMD, le modèle de programmation se prête parfaitement aux GPU. Mais le but d’OpenCL est aussi de cibler d’autres architectures que les GPU comme par exemple les GPP multicoeurs ainsi que d’éventuelles puces exotiques telles que l’Intel Xeon Phi, où la tendance est clairement à la multiplication des coeurs.

FIGURE1.24 – Modèle mémoire adopté par OpenCL.

1.3.2.2 HMPP

L’environnement de développement Hybrid Multi-core Parallel Programming (HMPP) est développé par CAPS. Il comprend un ensemble d’outils dédiés à la parallélisation hybride pour des systèmes multicoeurs. Cela regroupe des accélérateurs de type GPU (Nvidia ou AMD) ou des multi-coeurs SIMD. L’environnement comprend un compilateur pour Fortran et C et un runtime qui permet d’utiliser les outils de développement et drivers des architectures cibles.

Interface logicielle

HMPP comprend un ensemble de directives telles que celles d’OpenMP de manière à modi- fier le moins possible le code source en séparant les portions de codes à accélérer de manière explicite. Les directives HMPP sont basées sur trois types :

• Codelet : permet de définir une fonction à accélérer,

• Execution : permet de spécifier l’exécution d’un codelet dans le programme,

• Data Transfers : les données peuvent être envoyées avant l’exécution d’un codelet et ré- cupérées ensuite après l’exécution.

Une directive codelet déclare qu’un calcul va être exécuté sur un accélérateur. Le type d’ar- chitecture ciblée peut être indiqué, mais HMPP sélectionnera par défaut le premier accélérateur compatible s’il n’est pas spécifié. Afin d’optimiser le portage pour une architecture ciblée, le cal- cul peut être spécifié en fonction des paramètres, de leur taille, de leur valeur, etc. De plus, si l’accélérateur n’est pas disponible, le code de base peut toujours être exécuté et le comporte- ment de l’application préservé. L’exécution d’un codelet peut être synchrone ou asynchrone. HMPP peut être vu comme couche logicielle faisant le lien entre un environnement de pro- grammation spécifique et le calcul au sens large. HMPP peut donc être particulièrement inté- ressant lors de l’utilisation de kernels pour des cas spécifiques (comme l’utilisation d’un kernel spécifié uniquement pour des vecteurs de grande taille).

Environnement d’exécution

Le runtime dont dispose HMPP est une bibliothèque gérant les appels et les calculs envoyés aux accélérateurs matériels (HWA). Cette bibliothèque alloue et initialise le HWA de manière à permettre exécution de codelets. Elle gère aussi la communication entre l’hôte et le HWA et

gère les appels asynchrones.

Une application HMPP peut être compilée et exécutée avec un compilateur classique, qui ignorera les directives HMPP. Cette application est parsée par le pré-processeur pour extraire les parties contenues par les directives HMPP et les transformer en appels au runtime HMPP. L’édition de liens dynamique permet de modifier l’architecture cible ou de changer de code- let sans avoir à recompiler l’application. HMPP se place donc comme une solution permettant d’accélérer certaines portions de code.

Pendant la génération du code, le développeur peut consulter et modifier le code spécifié pour un accélérateur avant la compilation finale qui est réalisée pour une cible spécifique. Ce principe permet à un expert d’effectuer une phase d’optimisation manuelle. En théorie, cela permet de faire gagner du temps au développeur qui s’affranchit de l’encapsulation des ap- pels, des transferts mémoire, etc.). La figure 1.25 présente un schéma des différentes étapes de compilation pour un code ciblant GPP et GPU.

FIGURE1.25 – Etapes de compilation d’un code HMPP.

1.3.2.3 OpenACC

OpenACC regroupe un ensemble de pragmas haut-niveau qui permettent au C, C++ et For- tran de programmer des architectures massivement parallèles avec une facilité d’utilisation telle que celle d’OpenMP. Il s’agit de l’alternative la moins intrusive à disposition. OpenACC dispose d’un langage relativement riche permettant d’indiquer l’emplacement mémoire de données, de transférer ces données, ou encore de paralléliser boucles ou sections de code. A l’instar d’OpenCL, OpenACC va permettre de sélectionner une plateforme et une architecture et de récupérer différentes informations les concernant.

Le développement d’OpenACC est soutenu par PGI (The Portland Group), au travers de leur compilateur. Actuellement le compilateur ne prend en charge que le C et Fortran, et se

limite à la plateforme GPU Nvidia. Cependant, le standard a pour but de cibler aussi bien les GPU AMD, ainsi que l’Intel Xeon Phi. PGI propose un système de profling qui permet d’utili- ser, pour la plateforme Nvidia, l’outil de profiling « computeprof ».

OpenACC propose un modèle d’exécution très semblable à ceux d’OpenCL ou CUDA, avec trois niveaux : gang, worker et vector. Si l’on compare à CUDA, le gang correspond au bloc de threads, le worker, un warp, et enfin, le vector correspond au thread. Comme pour CUDA, le partage de données entre gangs n’est pas possible. Ce choix permet d’obtenir un meilleur passage à l’échelle, quel que soit le nombre d’unités de calcul. Ce modèle permet a priori de s’adapter aux architectures. Cela veut aussi dire que pour tirer le meilleur des performances d’une architecture, il sera toujours nécessaire d’adapter le code manuellement et spécifique- ment pour cette architecture.

Même si le standard est encore très récent, il semble que ce type d’outils soit beaucoup plus adapté à des développements de dimensions importantes. En effet, le système de directives évite des réécritures complètes de code que va demander par exemple OpenCL.