Projet : CAPS

previous up next contents
Précédent : Architectures de processeurs (cf. 2.2) Remonter : Résultats nouveaux Suivant : Communication dans les calculateurs parallèles


Sous-sections


   
Environnement pour architectures hautes performances(cf. 2.3)

Mots clés : Matlab, programmation parallèle, parallélisation automatique, portage d'applications, optimisation .



Participants : François Bodin, Stéphane Chauveau, Thierry Lafage, Yann Mével, Erven Rohou, André Seznec, Paul Van der Mark.

Résumé :

L'obtention de performances sur les architectures hautes performances nécessitent des outils logiciels adaptés qui cachent à l'utilisateur la complexité des matériels et des systèmes. Les actions de recherches que nous menons visent à fournir aux utilisateurs de calculateurs hautes performances des outils tels que compilateur, aide au portage, optimiseur pour permettre des développements et/ou portages d'applications hautes performances. Ainsi, nous développons Menhir, un compilateur Matlab pour machines parallèles, TSF, un outil d'aide au portage de codes Fortran sur architectures hautes performances et SALTO un environnement de manipulation de langage d'assemblage.

Menhir: un compilateur Matlab



Participants : François Bodin, Stéphane Chauveau.

Nous explorons une nouvelle direction de recherche qui consiste à étudier les techniques de production de codes parallèles à partir de langages plus proches d'un domaine d'application. Pour cela nous utilisons Matlab, un système spécialisé pour le calcul numérique et largement diffusé, pour la production automatique d'applications scientifiques séquentielles et parallèles en langage Fortran et C++. Notre approche permet de dériver directement l'application finale à partir du prototype écrit en Matlab. De plus la description des algorithmes en Matlab est de plus haut niveau qu'en Fortran (la gestion des structures de données n'est pas spécifiée dans le code) et laisse donc plus de liberté pour la génération et les transformations de code. Le prototype de compilateur paramétrable Menhir est disponible depuis cette année et est présenté dans la thèse de S. Chauveau [[10]]. Menhir est actuellement utilisé par la société LMS (http://www.lms.be, Louvain, Belgique) dans le cadre du développement d'une application de traitement du signal.

TSF : aide au portage sur les architectures hautes performances



Participants : François Bodin, Yann Mével.

Le portage (parallélisation et amélioration de performance) d'applications sur machines hautes performances est une activité techniquement difficile faisant appel à beaucoup de savoir-faire.

Le système TSF vise à accélérer cette activité grâce à l'utilisation conjointe de techniques issues de deux domaines : la parallélisation automatique et le raisonnement à partir de cas («Case-Based Reasoning»).

La parallélisation automatique fournit une bibliothèque de transformations de programmes à appliquer sous contrôle de l'utilisateur, dans le cas de TSF. Le raisonnement à partir de cas permet de recueillir les fruits des expériences de portage précédentes et fournit un accès au savoir-faire de l'expert. De plus pour aider l'utilisateur, le système permet d'instrumenter les codes afin d'analyser leurs performances. L'intégration des deux méthodes a pour objectif d'aider au choix des transformations adaptées en s'appuyant sur des expériences de portage similaires répertoriées dans la base de cas. Avec la technique de raisonnement à partir de cas, ces choix sont guidés par des calculs de similarité de contexte.

Cette étude est réalisée en collaboration avec la société Simulog qui fournit toute l'infrastructure de base à l'analyse de programmes Fortran grâce à son outil Foresys et le projet Irisa Repco (R. Quiniou).

Le système est actuellement en cours de test à NASA-AMES (USA).

Stratégie de compilation et interactions globales entre optimisations logicielles



Participants : François Bodin, Erven Rohou, André Seznec, Paul Van der Mark.

Au cours d'une chaîne de compilation classique, le type d'informations disponibles subit une profonde modification. Les premières phases ont une bonne connaissance de l'algorithme et des structures de données complexes utilisées par le langage de haut niveau. Les dernières phases ont une vision très précise de l'exploitation des ressources matérielles du processeur. Idéalement elles devraient connaître l'information que possédaient les premières transformations et disposer du maximum de connaissances pour appliquer efficacement des optimisations. Toutefois les compilateurs actuels ne propagent pas l'information et chaque étape doit régénérer une bonne partie des informations qu'elle utilise.

Il est important de conserver à chaque étape l'information facile à obtenir dans la mesure où celle-ci peut se révéler importante plus tard. Par exemple le générateur de code est souvent capable de déterminer si des accès à la mémoire sont dépendants par la connaissance qu'il a des variables locales et globales et des indices de tableaux. L'optimiseur bas-niveau a un besoin crucial de ce type d'information mais il ne peut que rarement l'obtenir sans faire appel à des mécanismes complexes comme la résolution d'équations diophantiennes.

Nous pensons aussi qu'il est important de briser la chaîne de compilation classique qui applique consciencieusement une liste de transformations dans un ordre immuable. L'information doit pouvoir remonter vers les optimisations de haut-niveau et celles-ci doivent être capables de défaire une partie de leur travail. Par exemple, il est parfois nécessaire de maîtriser les expansions de code résultant de nombreuses techniques de mise en \oeuvre du parallélisme à grain fin pour ne pas dégrader les performances du cache d'instructions [[33]].

Notre activité dans ce domaine se concentre sur l'interaction entre les optimisations au niveau du code source et celles effectuées au niveau du code machine.

Les réflexions sur la nécessité de faire communiquer les différentes phases d'un processus de compilation ainsi que de comparer les performances obtenues par différentes stratégies ont abouti au développement d'un premier prototype de compilateur. Les transformations de haut niveau et de bas niveau sont fortement couplées et s'échangent de l'information via un langage de communication simple appelé IL. Le principal objectif de ce langage est d'établir une carte qui mette en correspondance des portions de code haut-niveau et leur équivalent en assembleur. Ce nommage permet par exemple au générateur de code de décrire des propriétés visibles à haut-niveau qui pourront être exploitées à bas niveau.

Le compilateur dispose d'un certain nombre de transformations. Chacune est capable de modifier un fragment de programme, de quantifier son action, éventuellement de l'annuler et de transmettre de l'information à l'extérieur. Il est alors possible d'établir une véritable stratégie de compilation à partir d'un ensemble de transformations, la stratégie s'exprimant comme un algorithme. De nombreux autres critères, tels que l'allocation des registres, sont pris en compte.

Une partie importante de ces travaux est effectuée dans le cadre du projet Esprit LTR Oceans [[25]].

Collecte de traces d'exécution



Participants : François Bodin, Thierry Lafage, Erven Rohou, André Seznec.

Dans le cadre de la simulation dirigée par la trace, les outils logiciels d'intrumentation actuellement disponibles (Pixie, ATOM, ...) ont le défaut de ralentir de manière très significative l'exécution des applications (facteur 10-50), même si la trace générée n'est pas utilisée dans sa totalité. En effet, la trace d'une application est très volumineuse (plusieurs giga-octets pour de petites applications) et donc très difficile à utiliser en ce sens qu'une simulation sur une trace entière est très (trop) coûteuse en temps. Alors, des techniques telles que l'échantillonnage de trace sont utilisées pour réduire ce volume. D'autre part, tout programme comporte une phase d'initialisation qui n'est pas représentative de l'exécution totale. De ce fait, les premiers millards d'éléments de trace qui correspondent à cette phase d'initialisation sont, dans la plupart des cas, ignorés.

Le ralentissement induit par l'instrumentation est trop important et pour cela ne permet pas, actuellement, de collecter ne serait-ce que quelques échantillons de traces utilisables (i.e. après la phase d'initialisation) sur de réelles (grosses) applications exécutées dans leur totalité. Par réelles applications, nous entendons par exemple les applications de calcul intensif, les applications de type client-serveur (X, gestion de bases de données), mais aussi le système d'exploitation lui-même qui génère une activité dont on ne tient généralement pas compte.

Afin d'adresser ce problème, nous avons défini une nouvelle méthode de collecte de traces appelée «code cloning tracing» qui permet de ne pas trop ralentir les parties du programme testé dont la trace sera rejetée. Le code original est dupliqué. Les deux copies (clones) sont instrumentées de manière légère. Cette légère instrumentation permet, à l'exécution, de passer dynamiquement d'un clone à l'autre. Un des clones, appelé Pinst est ensuite instrumenté de manière lourde afin de collecter les traces (adresses des données par exemple), alors que l'autre clone, appelé Pexec sera exécuté tel quel: il correspond au mode d'exécution rapide de l'application instrumentée, ou mode «sans trace».

Un premier prototype appelé calvin a été implémenté à l'aide de SALTO [[34]]. En mode «sans trace», les applications que nous avons testées (l'ensemble des benchmarks SPEC95) subissent un ralentissement allant de 1.02 à 2.09. Ceci rend réaliste la collecte de traces sur de réelles applications telles que nous les avons définies.



previous up next contents
Précédent : Architectures de processeurs (cf. 2.2) Remonter : Résultats nouveaux Suivant : Communication dans les calculateurs parallèles