L’utilisation de logiciels de calcul scientifique permet aux acteurs industriels comme EDF de simuler des expériences qui seraient trop coûteuses, trop longues, trop compliquées voire impossibles à mettre en œuvre dans la pratique [1]. Dans le cas des problèmes trop spécifiques pour être traités par les logiciels disponibles sur le marché, l’industrie doit développer ses propres outils de simulation. La complexité algorithmique et la taille de ces logiciels peuvent entraver la maintenance et la mise à jour de leurs modèles physiques et mathématiques. Lors de la mise au point d’un nouveau logiciel de simulation, une grande attention est donc portée aux choix influençant sa maintenance future. Afin de réduire le coût de cette maintenance, les techniques de génie logiciel privilégient les stratégies minimisant le nombre de branches dans le code. Cela signifie généralement la mise au point de modules génériques dépendant le moins possible des spécificités des ordinateurs ou des modèles physiques et mathématiques. Ces modules peuvent alors être utilisés plusieurs fois dans une ou plusieurs applications, dans des contextes différents. Les modifications apportées à un module sont alors visibles dans toute les applications. Au contraire, la multiplication de branches spécialisées pour différents cas particuliers augmente le travail de maintenance et multiplie les possibilités d’introduction d’erreurs.
Les codes scientifiques : un compromis entre maintenabilité et performances
EDF R&D développe des logiciels de simulation pour de nombreux domaines scientifiques comme la mécanique des structures (Code-Aster [2]), la mécanique des fluides (Code-saturne [3, 4]), la thermique (Syrthes [5]) ou encore la neutronique (COCCINELLE [6] et COCAGNE [7]). Compte tenu de la complexité des problèmes à résoudre, les temps de résolution sont une très forte contrainte sur ces codes comme en témoigne le nombre de travaux effectués afin de réduire le temps de calcul des simulations . Cette contrainte conduit à vouloir spécialiser fortement ces codes pour les machines sur lesquelles ils doivent s’exécuter. La chaîne de calcul COCCINELLE est dédiée à la simulation du fonctionnement des cœurs de centrale nucléaire. Elle est utilisée aussi bien pour optimiser des paramètres d’exploitation que pour répondre aux exigences croissantes de l’Autorité de Sûreté Nucléaire (ASN). Pour l’exploitant EDF, COCCINELLE permet ainsi de déterminer des paramètres de pilotage, comme la concentration en bore nécessaire à l’équilibre de la réaction en chaîne, ou des paramètres d’optimisations comme la « longueur naturelle de campagne » qui correspond à la durée d’exploitation du combustible nucléaire avant qu’un rechargement du cœur ne soit nécessaire. COCCINELLE permet également à EDF de déterminer des éléments nécessaires aux dossiers de sûreté. Par exemple, lors d’un rechargement de combustible nucléaire, un dossier de sûreté doit être envoyé à l’ASN en vue d’obtenir l’autorisation de redémarrage de la centrale. Ce dossier nécessite entre autres la détermination du « point chaud », c’est-à-dire l’emplacement du réacteur qui atteint la température la plus élevée lors du fonctionnement de la centrale. Le code COCCINELLE est utilisé afin de calculer les températures maximales pouvant être obtenues dans les différentes parties du réacteur et permet donc l’identification de ce point chaud.
Afin de mieux prendre en compte certains phénomènes physiques, la chaîne de calcul COCAGNE a été mise au point. COCAGNE repose sur des modèles physiques plus complets que la chaîne COCCINELLE et permet donc d’effectuer des simulations plus proches de la réalité. Dans cette perspective, COCAGNE sert de code de référence afin d’estimer les erreurs liées au modèle physique de COCCINELLE [16]. COCAGNE a aussi pour vocation, à terme, de remplacer COCCINELLE. L’augmentation de la complexité des modèles induit une augmentation importante du nombre de calculs et donc, des contraintes sur les temps d’exécution. Par exemple, la validation par COCAGNE d’un calcul 3D COCCINELLE nécessite de traiter beaucoup plus d’inconnues. Un problème 3D COCCINELLE comportant 1 million d’inconnues sera validé par un calcul 3D COCAGNE sur un problème dit « crayon par crayon », correspondant à une discrétisation plus fine et comportant 100 millions d’inconnues [17]. Afin de pouvoir obtenir les résultats dans des délais raisonnables, il est important de réduire les temps de calcul de cette chaîne.
Le livre La physique des réacteurs nucléaires de Serge Marguet [18] introduit la notion de flux neutronique angulaire en détails et explique comment l’évolution du flux neutronique est régie par l’équation de Boltzmann. La résolution de cette équation représente une part importante du temps d’exécution de la chaîne COCAGNE [19, 20]. Trois solveurs s’appuyant sur différentes méthodes d’approximation sont disponibles dans la chaîne de calcul COCAGNE afin de résoudre cette équation. À chacune de ces approximations correspond un compromis particulier entre le temps de résolution et la précision des résultats.
– La méthode SPN [21, 22, 18] correspond à l’approximation la plus grossière disponible au sein de la chaîne de calcul COCAGNE. Elle permet l’obtention de résultats plus précis que la méthode de diffusion utilisée dans COCCINELLE tout en nécessitant relativement peu de temps de calcul. C’est la méthode utilisée pour valider les calculs de COCCINELLE [17, 16]. La consommation mémoire et les temps de résolution induits par cette méthode permettent d’effectuer des calculs directement sur station de travail. Il n’est donc pas envisagé d’utiliser les résultats des différents travaux de parallélisation de cette méthode sur machine à mémoire distribuée [23, 24].
– La méthode Sn [25, 22, 18] correspond à une approximation plus précise mais plus coûteuse en temps de calcul.
– La méthode des caractéristiques [26, 22, 18] est en cours de développement. Cette méthode permettra l’obtention de résultats plus fidèles aux modèles physiques et à la structure géométrique des réacteurs [26]. Si la consommation mémoire et les temps de résolution induits limitaient cette méthode aux seuls problèmes 2D [27, 28, 29], l’augmentation au cours des dernières années de la puissance de calcul des ordinateurs ainsi que de leur capacité mémoire permet depuis de concevoir des solveurs visant à résoudre des problèmes 3D .
Afin d’améliorer les performances de COCAGNE, le groupe Analyse et Modèles Numériques d’EDF R&D a réalisé différents travaux d’optimisations pour réduire la consommation mémoire et le temps d’exécution de ces solveurs . Si le temps d’exécution des codes de calcul industriels est une contrainte importante, ces derniers sont également soumis à un autre impératif : la longueur de leur cycle de vie. Le code de mécanique Code-Aster a par exemple fêté ses 20 ans en 2009 tandis que la première version de COCCINELLE a été lancée en 1983 [38]. Durant toute cette période, le code doit être maintenu. Ce travail de maintenance inclut trois types de travaux :
– la correction des erreurs,
– l’ajout de nouvelles fonctionnalités afin de répondre aux nouveaux besoins,
– et l’adaptation du code aux nouvelles architectures matérielles.
Recensement des solutions pour le domaine de l’algèbre linéaire
Limitation des bibliothèques procédurales
Dans un certain nombre de cas, mutualiser une partie du travail permet de faire des économies d’échelle. En informatique, la mutualisation de fonctions vers des bibliothèques permet de mettre en commun, entre plusieurs applications, les coûts de mise au point, de maintenance et d’optimisation de ces fonctions. Naturellement, pour que cela soit efficace, les fonctions de ces bibliothèques doivent être largement utilisées. Lorsque les fonctions d’une bibliothèque ont un champ d’utilisation suffisamment large, une interface finit généralement par devenir un standard de facto.
Au début des années 1970, les ordinateurs et les systèmes d’exploitation disponibles pour le calcul scientifique étaient très différents les uns des autres. Pour faciliter le développement d’applications scientifiques efficaces, chaque constructeur d’ordinateur fournissait une bibliothèque permettant d’effectuer les opérations les plus courantes. Chaque bibliothèque disposait alors de sa propre interface qui n’était pas compatible avec les bibliothèques des autres constructeurs. Pour pouvoir développer des codes portables entre les ordinateurs de différents constructeurs, la communauté scientifique a cherché à standardiser l’interface des principales opérations d’algèbre linéaire. Une étude menée sur différents codes de calcul scientifique a identifié les opérations mettant en œuvre des vecteurs comme les opérations les plus courantes [40]. Une proposition de standardisation de ces interfaces est faite en 1973 sous le nom de Basic Linear Algebra Subprograms (BLAS) .
L’architecture des ordinateurs évoluant, la décomposition des algorithmes en opérations vectorielles n’est plus suffisante pour permettre l’obtention de bonnes performances sur toutes les architectures [43]. Afin de combler ce manque, Jack Dongarra, en 1985, propose à la communauté scientifique une extension des BLAS pour prendre en compte les produits matrice-vecteur [44]. Cette extension est finalisée et publiée en 1988 [45]. À cette occasion, l’interface BLAS originale est rebaptisée BLAS de « niveau 1 » (Level 1 BLAS) ou BLAS1 en référence à la complexité algorithmique des opérations proposées par cette interface : les opérations vectorielles sur des vecteurs de taille N ont une complexité en O(N1). Pour des matrices denses de taille N × N, les opérations matrice-vecteur introduites par Jack Dongarra ont une complexité en O(N2) et sont donc dites de niveau 2 ou BLAS2. En 1987, Jack Dongarra propose d’étendre l’interface BLAS pour prendre en compte les opérations entre matrices comme les produits de matrices [46]. Ces opérations ont une complexité algorithmique en O(N3) et forment donc les BLAS3 ; elles sont publiées en 1990 [47]. Depuis, un forum technique dédié aux BLAS s’est mis en place afin de faire évoluer l’interface en fonction des besoins de la communauté .
Grâce à cette standardisation, les applications construites autour de l’interface BLAS deviennent portables sur les différentes plate-formes matérielles. Afin de gagner des parts de marché, les constructeurs d’ordinateurs et de processeurs cherchent à fournir à leurs clients les meilleures performances possibles. Pour y parvenir, ces derniers proposent donc leurs propres implémentations des BLAS. Actuellement, la majorité des constructeurs proposent leur implémentation des BLAS, comme par exemple :
– la Math Kernel Library (MKL) [50], fournie par INTEL ;
– la AMD Core Math Library (ACML) [51], fournie par AMD ;
– la Engineering and Scientific Subroutine Library (ESSL) [52], fournie par IBM.
Outre ces implémentations fournies par les constructeurs, différents travaux portés par la communauté du calcul intensif existent, comme par exemple les projets ouverts ATLAS et GOTO :
– ATLAS [53] (Automatically Tuned Linear Algebra Software) est une bibliothèque dont le processus d’installation effectue des mesures de performances afin de générer une implémentation optimisée pour l’ordinateur ;
– GOTO [54, 55] est une bibliothèque mise au point en assembleur par Kazushige Goto et qui est réputée pour être une des implémentations les plus performantes pour processeurs X86.
Des standards de facto existent également pour d’autres domaines scientifiques. Par exemple, les bibliothèques actuelles de transformées de Fourier implémentent la même interface que la version 3 de Fastest Fourier Transform in the West (FFTW) [56]. Depuis 2001, la GNU Scientific Library (GSL) [57] propose d’unifier les interfaces des bibliothèques de calcul utilisées dans de nombreux domaines scientifiques (algèbre linéaire, transformée de Fourier, interpolations, . . . ).
Une application dont la plus grande partie du temps d’exécution correspond à l’appel à de telles bibliothèques de calcul bénéficie automatiquement des performances apportées par les nouvelles architectures en changeant de version de bibliothèque. Le compromis entre maintenance et performance est alors trivial : le développeur de l’application scientifique prend en charge sa maintenance tandis que l’optimisation des performances est externalisée vers les bibliothèques scientifiques. Cependant, il n’est pas toujours possible d’utiliser efficacement les bibliothèques disponibles. En effet, la majorité des bibliothèques orientées performances fournissent un jeu de fonctions fixe et fini. Ce jeu de fonctions peut s’avérer être trop rigide pour répondre efficacement aux besoins des applications clientes. Ainsi, dans son analyse de l’optimisation des performances sur le CRAY I, Jack Dongarra montre que l’utilisation des BLAS1 conduit à deux limitations :
– BLAS1 ne permet pas d’exprimer des opérations présentant deux niveaux de parallélisme ;
– BLAS1 ne définit pas de matrices.
|
Table des matières
INTRODUCTION
Chapitre 1 Introduction
1.1 Les codes scientifiques : un compromis entre maintenabilité et performances
1.2 Recensement des solutions pour le domaine de l’algèbre linéaire
1.2.1 Limitation des bibliothèques procédurales
1.2.2 Une plus grande expressivité des opérations d’algèbre linéaire
1.2.3 Vers une description plus avancée de la structure des matrices
1.2.4 Notre objectif : la maintenabilité des langages dédiés et les performances des bibliothèques optimisées
1.3 Legolas++ : une bibliothèque dédiée aux problèmes d’algèbre linéaire
1.4 Objectif de la thèse : conception d’une version multicible de Legolas++
1.5 Plan de lecture
Chapitre 2 Programmation multicible : une structure de données par cible ?
2.1 Présentation des différentes architectures cibles
2.1.1 Les processeurs : des machines parallèles
2.1.2 Du processeur au processeur assisté : les accélérateurs de calcul
2.1.3 Introduction à l’architecture des processeurs X86_64 et à leur programmation
2.1.4 Introduction à l’optimisation pour GPUs NVIDIA
2.1.5 Comparaison des stratégies d’optimisation CPU et GPU
2.2 Optimisation pour CPU et pour GPU d’un exemple plus complexe
2.2.1 Présentation du problème
2.2.2 Implémentations optimisées
2.3 La plate-forme de tests : les configurations matérielles
2.4 Analyse des performances : à chaque architecture sa structure de données
2.5 Programmation multicible : un code source unique, différents exécutables optimisés
Chapitre 3 État de l’art des environnements de développement parallèle multicible
3.1 Vers un niveau d’abstraction plus élevé
3.2 Éléments de discrimination
3.2.1 Type de conception de l’environnement
3.2.2 Niveau d’abstraction du parallélisme
3.2.3 Support des accélérateurs de calcul
3.2.4 Adaptation du stockage à l’architecture matérielle
3.3 Différentes approches pour permettre le développement d’applications parallèles multicibles
3.3.1 Les approches basées sur la programmation événementielle
3.3.2 Les approches basées sur les patrons parallèles
3.3.3 Les approches basées sur la programmation par tableaux
3.3.4 Les autres approches
3.3.5 Synthèse
3.4 Choix stratégique : positionnement de MTPS
Chapitre 4 MTPS : MultiTarget Parallel Skeleton
CONCLUSION