Projet : ReMaP

previous up next contents
Précédent : Résultats nouveaux Remonter : Résultats nouveaux Suivant : Environnements multi-threads hautes performances et


Sous-sections


   
Compilateurs et bibliothèques



Participants : Vincent Boudet, Alain Darte, Frédéric Desprez, Stéphane Domas, Guillaume Huard, Emmanuel Jeannot, Cyril Randriamaro, Fabrice Rastello, Yves Robert, Georges-André Silber, Stéphane Ubéda.

Mots clés : calcul parallèle, parallélisation automatique, environnements de programmation .

Résumé :

Cette partie résume nos travaux récents concernant les compilateurs et les bibliothèques. Ceux-ci sont à la fois théoriques et pratiques : nous développons de nouvelles stratégies de transformation de codes (étude notamment de la fusion de boucles, du partitionnement de boucles, des algorithmes de détection de parallélisme), de distribution des données, de nouvelles stratégies algorithmiques (notamment en algèbre linéaire), et également des outils de programmation parallèle (à travers Scilab, TransTool, Nestor et PlusPyr).

Transformation de programmes

Algorithmes de parallélisation de boucles

Nous avons approfondi notre étude des algorithmes de parallélisation de boucles dans deux directions.

La première a consisté à développer des techniques de génération de code pour les algorithmes dits d'ordonnancement (comme ceux que nous avons développés dans les années précédentes). En effet, ces algorithmes de parallélisation ne sont à l'heure actuelle pas encore complètement implantés du fait justement de la complexité de la génération de code qu'ils impliquent. Nous avons proposé de nouvelles méthodes de génération de code, plus simples, qui indiquent que leur implantation sera faisable à l'avenir.

La seconde a consisté à implanter dans Nestor une variation de l'algorithme d'Allen et Kennedy. Nous avons étudié de façon théorique comment prendre en compte les dépendances de contrôle, tout en contrôlant la dimension des tableaux à introduire dans le code final pour garantir le calcul des bornes de boucles et des gardes des tests Fortran. Ces nouveaux résultats ont déjà été présentés au colloque CPC'98 (Compilers for Parallel Computing). Le nouvel algorithme de parallélisation qui découle de ces résultats a été complètement implanté dans Nestor.

Partitionnement de boucles

Nous avons approfondi le problème dit du partitionnement de boucles. Partant d'un nid de boucles (c'est-à-dire un ensemble de boucles imbriquées de type DO en Fortran), le but est de construire des tuiles élémentaires en partitionnant le domaine d'itération, de façon à augmenter la granularité des calculs. L'exécution d'une tuile par un processeur nécessite alors un certain nombre de données en lecture et en écriture, celles qui sont référencées au cours du calcul et qui vont être chargées dans le cache. Déterminer le nombre exact N de ces données n'est pas facile, car on ne veut compter qu'une fois les références multiples. On peut cependant obtenir de bonnes approximations de ce nombre N. Se pose alors la question de déterminer la taille et la forme des tuiles de manière à minimiser N. Ces travaux autour des techniques de loop partitioning s'inscrivent dans la lignée de nos résultats sur le partitionnement pour multiprocesseurs parallèles (tiling), mais s'appliquent également aux processeurs séquentiels dotés d'une mémoire organisée hiérarchiquement en plusieurs niveaux. Techniquement, nous partons de résultats récents de Agarwal, Kranz et Natarajan que nous avons améliorés dans de nombreuses directions (estimation de N, formulation générale du problème, heuristique plus puissante, etc.).

Fusion de boucles

La fusion de boucles est une transformation de programme qui combine plusieurs boucles en une seule. Elle est utilisée dans les compilateurs-paralléliseurs, principalement pour augmenter la granularité des boucles et pour améliorer la réutilisation des données. Nous avons étudié d'un point de vue théorique plusieurs variantes du problème de fusion de boucles - en identifiant les cas solubles en temps polynômial et les cas NP-complets - et établi le lien entre ces problèmes et quelques problèmes d'ordonnancement provenant de domaines complètement différents. Nous avons notamment étudié le problème de la fusion de boucles typées ainsi que le problème de la fusion de boucles avec décalage. Un des sous-problèmes ouverts depuis longtemps était le problème de la distribution partielle pour la parallélisation de boucles. Nous avons montré que ce problème est malheureusement NP-complet.

Pipeline logiciel et retiming

Nous avons étudié plus avant les techniques de retiming, utiles à la fois en synthèse d'architectures et en parallélisation automatique. Nous avons proposé deux nouveaux résultats d'optimisation sur cette technique : la minimisation et la maximisation du nombre d'arcs sans registres d'un circuit synchrone. Le problème de maximisation apparaît notamment dans le cadre de l'optimisation de la localité des données d'un programme. Il est NP-complet ce qui rejoint des résultats classiques concernant l'alignement de tableaux. En revanche, le problème de la minimisation peut être résolu efficacement par des techniques de minimisation de flot dans les graphes et fournit une application très intéressante pour le pipeline logiciel décomposé que nous avions étudié les années précédentes. Cet algorithme est en cours de développement à l'aide des bibliothèques de Nestor.

Alignement et distribution des données

Distribution des boucles parallèles et des tableaux aux processeurs

En 1990, Li et Chen ont montré que la recherche du meilleur alignement des dimensions des tableaux (pour minimiser le coût des communications) était un problème NP-complet par rapport au nombre de tableaux à aligner. Nous avons revisité leurs travaux, parce que la recherche d'un alignement ne doit pas être conduite sans tenir compte du parallélisme potentiel des nids de boucles. En d'autres termes, l'alignement optimal peut séquentialiser les calculs quelle que soit la distribution choisie ensuite. Nous présentons un algorithme efficace qui tient compte simultanément de l'alignement et de la distribution des données et des calculs. La bonne nouvelle est que plusieurs instances du problème d'alignement/distribution ont une complexité polynômiale.

Redistribution des tableaux

Nous nous sommes intéressés à la redistribution des tableaux mono-dimensionnels alloués de manière bloc-cyclique sur des grilles de processeurs. Nous avons montré l'an passé comment construire un ordonnancement optimal agencé en étapes de communication. Dans la suite de ces travaux, nous avons considéré un modèle plus réaliste dans lequel les étapes peuvent s'entrelacer. Nous avons alors montré comment obtenir un ordonnancement optimal dans la majeure partie des cas, à savoir passer d'une distribution CYCLIC(r) sur une grille de P processeurs à une distribution CYCLIC(s) sur une grille de Q processeurs, pour des valeurs arbitraires des paramètres P, Q, r, et s. Pour obtenir ces ordonnancements optimaux, nous utilisons des techniques issues de la théorie de graphes et de l'algèbre modulaire.

Algorithmique sur réseau hétérogène de processeurs

Pour distribuer les tableaux d'une application à paralléliser sur un réseau hétérogène de stations de travail, une solution bloc-cyclique n'est pas adaptée. Pour prendre en compte les différentes vitesses des processeurs, on peut penser à une distribution dynamique des données. Mais les stratégies dynamiques peuvent conduire à de mauvais résultats pour deux raisons : (i) le coût des communications liées à d'éventuelles redistributions rendues nécessaires par l'allocation des tâches; (ii) l'inactivité forcée des processeurs à cause des contraintes de dépendances. Nous proposons une approche statique par phases de calcul, en modifiant l'allocation après chacune des phases pour tenir compte d'éventuels changements de vitesse des processeurs. Au sein de chaque phase, nous optimisons la charge des processeurs en fonction de leurs vitesses (ou des estimations courantes de celles-ci). Nous montrons la validité de cette approche pour des problèmes d'algèbre linéaire fortement couplés comme les problèmes aux différences finies ou la décomposition LU. Ces résultats sont préliminaires : effectuer un gros calcul matriciel sur des ressources hétérogènes réparties sur un réseau n'est pas encore un problème résolu!

Insertion de redistributions et le logiciel ALaSca

Nous avons travaillé sur un outil de transformation de codes Fortran 77, contenant des appels aux bibliothèques BLAS et LAPACK, soit vers des codes HPF contenant des appels à l'interface HPF de ScaLAPACK, soit vers des codes Fortran 77 avec des appels à ScaLAPACK. Cette étape est une des premières étapes nécessaires à la parallélisation de tels codes numériques. Chaque routine de BLAS ou LAPACK parallèle possède une distribution qui maximise ses performances. Cette distribution dépend d'un certain nombre de facteurs dont la taille des données, le nombre de processeurs de la machine cible, les caractéristiques de ces processeurs et bien sûr l'algorithme parallèle. Nous calculons les distributions à partir d'exécutions des routines et d'une modélisation de l'algorithme parallèle utilisé. Puis, nous insérons dans le code toutes les redistributions nécessaires à une exécution optimale pour chaque routine. Nous disposons ensuite d'algorithmes et d'heuristiques permettant de supprimer certaines distributions pour une exécution parallèle à surcoût réduit. Le logiciel développé (ALaSca) a été intégré à TransTool.

Parallélisme de contrôle et le logiciel PlusPyr

PlusPyr permet d'analyser des programmes à contrôle statique et de générer le graphe de tâches associé. Nous avons mis au point un modèle intermédiaire, le graphe de tâches paramétré (GTP). Le GTP permet de décrire les dépendances inter-tâches quelle que soit la valeur des paramètres du programme.

Notre recherche a d'abord porté sur l'ordonnancement dynamique du GTP. Nous avons ensuite mis au point un algorithme d'ordonnancement statique et symbolique. Ce nouvel algorithme permet, lors de la compilation, de générer un programme parallèle qui exécute le programme séquentiel donné en entrée et de calculer le placement des tâches qui composent l'exécution parallèle. Le programme ainsi que le placement sont paramétrés. Le programme parallèle s'exécute alors en fonction des paramètres et de la machine cible. Le placement est calculé à l'aide des fonctions générées à la compilation. De plus, le calcul des fonctions paramétrées de placement se fait à l'aide du graphe de tâches paramétré (et donc ne dépend pas de la taille des données). Le programme parallèle obtenu ainsi est un programme générique.



previous up next contents
Précédent : Résultats nouveaux Remonter : Résultats nouveaux Suivant : Environnements multi-threads hautes performances et