OpenACC 2.0 : Les nouvelles fonctions de gestion de données
By   |  January 06, 2014

Implémenter des tableaux multidimensionnels en tant que vecteurs de pointeurs

Sachant qu’implémenter des tableaux multidimensionnels avec des vecteurs de pointeurs est assez courant en C/C++, la pratique est maintenant directement supportée par OpenACC 2.0, au moins pour les tableaux réguliers. Avec une seule directive pour spécifier la forme du tableau multidimensionnel, le compilateur prendra en charge toute la mécanique de création d’un tableau de pointeurs équivalent sur l’accélérateur. Il existe toutefois une restriction importante : les pointeurs formant le tableau doivent tous être soit présents soit non présents. Autrement dit, modifier les pointeurs sur l’hôte ou sur l’accélérateur n’est pas autorisé.

Cette fonctionnalité peut être appliquée directement à notre premier exemple dans lequel le tableau de pointeurs data[n] sera traité par OpenACC 2.0 comme un tableau de structures bidimensionnel data[n][1]. C’est ce que montre le listing 4, où le gain en termes de productivité et de lisibilité par rapport au listing 2 apparaît évident.

La simplicité de cette syntaxe ne doit cependant pas faire oublier que la plupart des implémentations généreront un transfert de données par pointeur. Ainsi, les performances sur un tableau non contigu seront significativement moins élevées qu’avec un tableau contigu. Le code pourra cependant bénéficier d’un effet de bord intéressant pour la gestion du tableau en tant que tel : les boucles utilisées pour itérer sur les pointeurs pouvant maintenant être exécutées directement sur l’accélérateur, il en résultera quelquefois une meilleure mise à profit de son parallélisme matériel.

Le support d’autres types de données complexes tels que les listes chaînées, les arborescences ou les structures contenant des pointeurs est prévu dans les prochaines versions d’OpenACC. En attendant, il est déjà possible de gérer des données complexes en utilisant les nouveaux appels API présentés précédemment.

Les données globales

Enfin, l’un des apports les plus importants de cette nouvelle version est sans doute le support amélioré des variables globales par la directive declare. Avec OpenACC 1.0, il était déjà possible de créer une région de données globale en utilisant une des clauses standard (create, copy, copyin, par exemple), tandis que la clause device_resident servait à créer les variables sur l’accélérateur sans qu’elles existent sur le processeur hôte. Les variables globales ayant une durée de vie dynamique sur l’accélérateur étaient supposées être gérées comme toutes les autres variables, c’est-à-dire dans des régions de données explicites ou implicites bornant les directives de calcul. En version 2.0, OpenACC supporte officiellement les appels aux fonctions utilisateurs dans les directives de calcul. C’est d’ailleurs un problème car lorsque le compilateur traite ces directives, il peut ne pas être en mesure de déterminer quelles variables globales à durée de vie dynamique seront utilisées par la fonction appelée. Cette situation est illustrée au listing 5 où une fonction non locale, appelée depuis une région de calcul, utilise une variable globale dont la durée de vie est dynamique sur l’accélérateur.

En introduisant une nouvelle clause link dans la directive declare, OpenACC 2.0 apporte une solution simple à ce cas de figure. Une variable globale déclarée en tant que variable link sera toujours présente sur l’accélérateur sous la forme d’un lien global qui, initialement, ne pointe sur rien – un peu comme un pointeur initialisé à NULL. Ce lien sera mis à jour de façon dynamique pour pointer vers la bonne adresse ou vers NULL à chaque fois que le lien global sera utilisé par un constructeur data ou une directive enter data ou exit data.

Restriction importante sur les variables link globales, elles ne peuvent pas être utilisées avec certains appels API tels que acc_create() ou acc_copy(). Ces appels n’acceptant qu’une adresse hôte, ils ne peuvent pas connaître la nature link de la variable correspondante. De ce fait, logiquement, on ne peut pas mettre à jour l’adresse de la variable sur l’accélérateur.

Un des principaux inconvénients des variables link globales par rapport aux variables régulières est qu’il est possible, mais évidemment interdit, d’y accéder au niveau de l’accélérateur lorsqu’elles ne sont gérées par aucune région de données. De telles erreurs ne peuvent généralement pas être interceptées à la compilation et, dans la plupart des cas, elles aboutissent à une erreur d’exécution identique à ce qui surviendrait lors de l’utilisation d’un pointeur illégal sur l’accélérateur. Pour illustrer l’utilisation des clauses link, le listing 6 présente une bibliothèque I/O très simplifiée dans laquelle l’énorme buffer de sortie est géré de façon dynamique en tant qu’objet link.

Vous devriez maintenant être en mesure de tirer profit des nouvelles fonctions de gestion de données d’OpenACC 2.0 – et de les implémenter dans vos codes assez simplement. Le mois prochain, nous nous focaliserons sur d’intéressantes améliorations des constructeurs de calcul : constructeurs atomiques, clauses spécifiques à certains accélérateurs, parallélisme imbriqué, appels de routines, etc. Restez à l’écoute et, en attendant…

Bons développements !

Navigation

<12>

© HPC Today 2024 - All rights reserved.

Thank you for reading HPC Today.

Express poll

Do you use multi-screen
visualization technologies?

Industry news

Brands / Products index