• Nenhum resultado encontrado

Le code déclenchant la soumission des tâches (réalisée par les méthodesstartet run) est généré à partir d’informations issues de l’analyse sémantique de la section S en suivant l’algorithme 1 (l’algorithme présente uniquement le cas synchrone mis en place par la méthode run; dans le cas asynchrone, l’ensemble du code jusqu’à la synchronisation implicite est encapsulé dans une tâche OpenMP). L’algorithme se décompose en cinq grandes parties. Il commence par récupérer des données per- manentes depuis les ports de données d’entrées/sorties et allouer des données tem- poraires. Ensuite, il déclenche la préparation des partitionnements et repartitionne- ments. Après, il exécute la séquence d’opérations calculée lors de l’analyse séman- tique (dont le fonctionnement est décrit par la figure4.3) en alternant des opérations de partitionnement, de soumission de tâches de métatâche, de départitionnement et de repartitionnement. L’exécution de ces opérations fait appel à des services fournis par les greffons présentés dans les sections 4.3 et 4.4 ainsi qu’à des services fournis par des composants générés depuis des métatâches dont le fonctionnement est décrit en section 4.5. Enfin, l’algorithme demande le nettoyage des structures de données issues des opérations relatives aux partitionnements avant de déclencher la libération des données.

Transformation des composants utilisateurs

Les sources des composants utilisateurs sont composées de deux parties dis- tinctes : le code contenant l’implémentation du composant qui prend la forme de classes C++ et la définition des interfaces d’un composants, exprimé en utilisant des macros C++. La transformation de composants Halleyen composants L2C se fait automatiquement lors de la compilation : les macros de Halley génèrent au- tomatiquement à la compilation les macros L2C responsables de la description des interfaces d’un composant. Cela a pour effet de transformer les ports de données en portsuse dont le type est décrit par la figure4.5. La transformation des composants utilisateur n’a donc aucun impact sur l’implémentation même d’un composant et s’effectue de manière totalement transparente.

4.3. SUPPORT DES TYPES DE DONNÉES 83

interface ExtDataPort<DataType>

{

void acquire(DataType* ptr);

void release();

void allocate();

void free();

void wait();

};

Figure 4.7 – Type de port data des greffons de données (interface publique).

Étant donné que Halley est un prototype, il est important de noter que les interfaces des greffons ne couvrent pas le cas général, mais ces interfaces sont suffi- samment généralistes pour traiter les cas d’utilisations traités dans les chapitres 5 et6. Des travaux supplémentaires sont nécessaires afin d’améliorer la généricité des interfaces ainsi que pour évaluer leur applicabilité sur d’autres cas d’utilisations plus variés. Cette remarque s’applique aussi aux autres sortes de greffons présentés dans les sections 4.4 et 4.5.

4.3.1 Interfaces des greffons

Les greffons de données doivent disposer d’au moins deux portsprovide : un port de gestion des données data et un port part relatif au partitionnement du buffer de données comme cela a été précédemment illustré sur la figure 4.4. Détaillons le contenu de ces deux interfaces.

Port d’accès et de manipulation des données Le port data d’un greffon de données vise à permettre la manipulation d’un buffer de données par la section. Le type de cette interface est décrit par la figure4.7.

Les méthodes acquire et release sont utilisées pour gérer des buffers de don- nées permanents (c.-à-d. obtenus depuis des composants utilisateurs). La méthode acquire permet au composant de récupérer le descripteur d’un buffer de données (p. ex. pointeur). Cette méthode rend le greffon responsable du buffer de données.

Les métadonnées relatives au buffer de données (p. ex. taille du buffer) ne sont pas passées en paramètres et sont définies par des attributs du composant. La méthode releaserelâche la responsabilité du buffer de données.

Les méthodes allocateet freesont utilisées pour gérer des buffers de données temporaires (c.-à-d. visibles uniquement dans les sections et n’existant que lors de leurs exécutions). Dans le cas des buffers de données temporaires, les greffons de données sont toujours responsables de leur buffer. La méthode allocate crée un buffer de données temporaire non initialisé à partir des métadonnées fournies par les attributs du composant. La méthode freedétruit le buffer temporaire en mémoire.

interface ExtDataPartPort<DataType, MetaInformations>

{

void* getDependency();

DataType* data();

MetaInformations infos();

// Autres méthodes supplémentaires requises // par les greffons de partitionnement }

Figure4.8 – Type de port part des greffons de données (interface privée).

La méthode wait est une fonction bloquant le fils d’exécution de l’appelant jusqu’à ce que toutes les tâches qui opèrent sur le buffer de données soient terminées.

Port de partitionnement Le portpartd’un greffon de données vise à fournir des informations aux greffons de partitionnement. Les greffons de données sont libres de fixer leurs propres types d’interface pour ce port, en accord avec les experts fournissant des types de données partitionnées associés. En effet, le type de l’interface part ne dépend que des greffons de données et des greffons de partitionnement associés et non des composants glus de Halley. Halley propose néanmoins un patron de type d’interface qui permet aux greffons de partitionnement de fonctionner (indépendamment du type de données traité). Ce type est décrit par la figure 4.8.

La méthodegetDependency fournit un pointeur opaque utilisé pour définir des dépendances entre un buffer de données et les fragments issus de son partitionne- ment, assurant ainsi la cohérence des calculs effectués par le graphe de tâche généré à l’exécution, notamment en cas de repartitionnement. La méthode datafournit un descripteur référençant le buffer de données géré par le greffon. La méthode infos fournit les métadonnées du buffer de données, gérées par le greffon, qui sont néces- saires au partitionnement (p. ex. taille de la donnée). Plus d’informations sur l’usage de cette interface par les greffons de partitionnement sont fournies en section 4.4.

Spécification des interfaces La figure4.9montre un exemple de définition de type de données (tableau bidimensionnel) utilisé pour déduire les interfaces du greffon associé. elemSize est utilisé pour définir la taille des éléments du tableau (p. ex.

float, double, int, etc.). Il est important de noter que le type DataType est aussi utilisé pour décrire le type des ports de données, permettant à Halley de déduire automatiquement les ports use/provide issue des ports de données.

4.3.2 Enregistrement de greffons et paramétrage

Afin qu’une application puisse accéder à un greffon, celui-ci doit être associé à un type de données et répertorié dans des fichiers de description de greffons four- nis au compilateur Halley. La figure 4.10 montre un exemple de fichier (défini