• Aucun résultat trouvé

Les modèles de programmation OpenCL

4. Développement d’un code multiarchitectures 65

4.2. Calcul générique sur carte graphique

4.2.3. Les modèles de programmation OpenCL

Le standard de programmation OpenCL permet de développer des modèles de

parallé-lisme par tâches et de données sur processeurs multicœurs. La librairie fournit une interface

de programmation de haut niveau permettant la gestion des calculs et des ressources ainsi

que le profilage des applications. Les calculs de bas niveau sont implémentés en un langage

basé sur le C99. Une application OpenCL se doit de définir les quatre modèles

hiérar-chiques suivants. Les termes techniques sont systématiquement traduits dans cette partie

mais pourront être utilisés en anglais dans la suite.

Le modèle de plateforme

Du point de vue OpenCL, une plateforme est constituée d’un hôte (host) et de un ou

plusieurs appareils (devices). Ces derniers regroupent, de manière générique, bon nombre

de matériel multicœur comme les cartes graphiques mais aussi les processeurs classiques ou

les processeurs spécifiques. L’implémentation consiste en une partie de code exécutée par

la machine hôte (host) et capable d’envoyer et d’exécuter des noyaux de calcul (kernels)

aux appareils(devices). Le code des noyaux est compilé de manière spécifique aux appareils

sur lequel il sera exécuté. Les noyaux sont exécutés par les cœurs(processing elements) de

chaque unité de calcul(compute unit), ce qui reflète l’organisation matérielle des unités de

calculs d’un GPU, comme illustré par la figure 4.6.

Host

Device

Processing element

Compute unit

Figure 4.6. – Modèle de plateforme OpenCL

Le modèle d’exécution

On distingue deux catégories d’unités d’exécution : le programme exécuté par la machine

hôte et les noyaux. À chaque appareil(device)est associé une ou plusieurs files d’attente de

commandes dans lesquelles sont insérées les transferts de données et les appels aux noyaux.

Ces derniers sont définis par un état d’exécution (soumis, en attente, démarré, terminé,

. . .) dont les durées entre transitions sont mesurables par l’outil de profilage intégré. Des

dépendances entre les éléments peuvent être données explicitement, ce qui conduit à

l’ex-pression d’un parallélisme par tâche à travers une exécution asynchrone. La caractéristique

principale est que chaque noyau est exécuté, par un cœur de calcul, comme une fonction

en un point d’un espace d’indice représenté sur la figure 4.7. Cet espace est décomposé en

un ensemble de groupes de travail (work-groups) contenant plusieurs éléments de travail

(work-items). À chaque élément de travail(work-item) est associé un cœur de calcul.

Espace global Work-group GX GY 0 1 2 3· · · 0 1 · · · NX 0 1 2 3 . . . 0 1 .. . NY · · · · · · · · · .. . .. . . .. 0 1 2 · · · 0 1 2 .. . WX WY

Figure 4.7. – Espace d’indices OpenCL. Espace 2D de tailleG

X

×G

Y

impliquantN

X

×N

Y

L’espace d’indices est un espace cartésien mono-, bi- ou tridimensionnel. Chaque élément

de travail (work-item) est identifié de manière unique par ses coordonnées dans l’espace

global ou par le couple des coordonnées du groupe(work-group) et d’une coordonnée locale

au groupe (work-groups), comme illustré par la figure 4.7. Les tailles de l’espace global

et des groupes de travail sont données en paramètres à chaque exécution d’un noyau. Le

parallélisme de données est obtenu en reliant l’espace d’indices et l’indexation des données.

Différents niveaux de synchronisation sont possibles. L’exécution des éléments de travail

(work-items)est concurrente au sein d’un groupe(work-group). Il est possible de

synchroni-ser les éléments au sein d’un même groupe à l’aide de barrières. Par contre il est impossible

de synchroniser les groupes entre eux, de même qu’il n’est pas possible de spécifier l’ordre

dans lequel ils seront exécutes ni de savoir lesquels seront exécutés simultanément. Du côté

de l’hôte, la synchronisation globale se fait par l’intermédiaire de la file d’attente et de l’état

de chaque noyau de calcul.

Le modèle de mémoire

Dans ce modèle, la mémoire de l’hôte est dissociée de celle des appareils. Cette dernière

est décomposée en quatre région distinctes :

Globale : niveau le plus haut, il est partagé en lecture et écriture par tous les éléments

de travail de tous les groupes (∼1 GByte).

Constante : mémoire accessible en lecture seule par les éléments de travail au cours de

l’exécution. De taille assez faible, elle permet de stocker des constantes numériques

(∼10 kByte).

Locale : niveau intermédiaire partagé au sein d’un groupe de travail. Ce niveau peut être

utilisé explicitement comme un cache (∼10 kByte).

Privée : niveau le plus bas, il est dédié à un élément de travail et inaccessible aux autres

(<1 kByte).

La mémoire globale ne peut contenir que des Buffers ou des Images. Les premiers sont

des zones mémoires contiguës destinées à un usage générique comme un tableau d’éléments.

Les seconds sont stockés dans la mémoire dédiée aux textures sous la forme d’une structure

de données complexe et dont les accès, en lecture seule ou écriture seule, sont gérés par des

fonctions OpenCL prédéfinies. Ce modèle hiérarchique est schématisé en figure 4.8. Comme

nous le verrons par la suite, une gestion précise des transferts de données entre ces différents

niveaux de mémoire est fondamentale pour l’amélioration les performances.

Le modèle de programmation

Afin d’exploiter tous les modèles définis précédemment, une application OpenCL se

décompose selon trois couches dont il est nécessaire de décrire tous les niveaux. Au niveau de

la plateforme, le programme hôte explore l’architecture disponible et un contexte OpenCL

doit être créé afin de lier le ou les appareils utilisés avec l’hôte et pour créer les files de tâches

associées à chaque appareil. Le compilateur OpenCL permet de compiler les sources des

noyaux de calcul spécifiquement pour un appareil ciblé. Au niveau des modèles de mémoire

et d’exécution, le programme est constitué de la gestion des files d’évènements ainsi que de

Mémoire globale du système host

Mémoire globale Constante

device work-group Mémoire locale P. w.i. P. w.i. P. w.i. P. w.i.

Figure 4.8. – Modèle hiérarchique OpenCL pour la mémoire

transferts de données entre les mémoires de l’hôte et des appareils. Un schéma d’exécution

est représenté en figure 4.9. Dans l’idéal, la conception des algorithmes doit permettre une

gestion asynchrone des évènements afin de maximiser l’utilisation des composants. Cette

dernière est maximale lorsque des calculs sont effectués simultanément sur les appareils et

sur l’hôte ainsi que pendant des transferts de données.

. . . Initialisation OpenCL

Compilation

Transferts

Exécution deskernels

Calculs

Host Device Création de la

file d’exécution

Figure 4.9. – Schéma d’exécution OpenCL

La figure 4.9 représente les durées d’exécution à titre d’illustration car les proportions

entre les différentes étapes ne reflètent pas nécessairement les temps observés dans une

application.

Documents relatifs