Parallelisme dans les architectures multi-cœurs pour applications mobiles

Les processeurs

                 L’adéquation entre les processeurs et les applications est indispensable afin d’offrir les meilleures performances possibles. Or la grande diversité d’applications dont les besoins sont très hétérogènes oblige les concepteurs à utiliser une multitude de processeurs qui vont être spécifiques à chaque type d’application. Par exmple, certains seront dédiés à la gestion des communications, d’autres seront utilisés pour le traimenent d’image. En utilisant des processeurs spécifiques, les concepteurs sont certains d’obtenir les performances requises tout en utilisant des processeurs dont la consommation énergétique reste limitée. Ainsi, l’accroissement des fonctionnalités des téléphones engendre une augmentation du nombre de processeurs afin de supporter les nouvelles fonctionnalités.
Le jeu d’instructions : Les processeurs sont classiquement différenciés par leur jeu d’instructions qui peut être de type Complex Instruction Set Computer (CISC) ou Reduced Instruction Set Computer (RISC) [8]. Les processeurs de type CISC ont un jeu d’instructions plus étendu et plus enrichi sémantiquement que les processeurs de type RISC. C’est par exemple le cas des processeurs Intel Core i7. Inversement, les processeurs RISC ont un jeu d’instructions davantage restreint, imposant le recours à plusieurs instructions de type RISC au lieu d’une seule avec une architecture de type CISC, ce qui impacte la taille du code généré par le compilateur. Architecturalement, les différences se situent au niveau de l’étage de décodage du processeur qui va être plus complexe pour les processeurs de type CISC. Ce type de processeur est très utilisé dans l’embarqué dans les processeurs ARM [9] ou MIPS [10] ainsi que dans certains processeurs haute performance comme les SPARC [11]. En fonction du domaine applicatif, un certain nombre d’extensions au jeu d’instructions peut être ajouté, comme par exemple les instructions de type MMX [12] ou SSE [13] sur les processeurs Intel ou encore l’extention vectorielle NEON [14] ou l’extention Jazelle [15] (accélération des applications Java) des processeurs ARM.
Le parallélisme d’opérations : Afin d’obtenir de meilleures performances, certains processeurs peuvent effectuer plusieurs opérations simultanément. L’extraction du parallélisme peut se faire au niveau microarchitectural grâce à un réordonnancement des opérations dans les processeurs de type outof-order, ce qui permet aux processeurs d’utiliser un parallélisme qui n’est visible qu’au moment de l’exécution. Cependant l’extraction du parallélisme va complexifier l’architecture globale du processeur. Afin de limiter la complexité du processeur, une autre approche consiste à extraire ce parallélisme au moment de la compilation. Ainsi le processeur n’a plus qu’a effectuer les opérations sur les unités d’exécution que le compilateur a déterminé. Ce type de processeur utilise une architecture de type Very Long Instruction Word (VLIW). C’est le cas des processeurs de la famille C64x de Texas Instruments [16]. Les processeurs de type Single Instruction Multiple Data (SIMD) permettent d’effectuer plusieurs opérations identiques simultanément sur des données différentes. Le processeur SPE intégré dans l’architecture Cell d’IBM ainsi que dans l’architecture Spurse Engine de Toshiba est un exemple de processeur SIMD. Que ce soit pour les architectures VLIW [17] ou SIMD, la complexité due à l’extraction du parallélisme est dans ces cas-ci reportée sur le compilateur, ce qui simplifie la microarchitecture du processeur, mais complexifie la tâche du compilateur qui ne peut extraire que le parallélisme visible au moment de la compilation. De manière générale, le parallélisme d’opérations ne pourra être efficace que dans le cas où suffisamment de parallélisme aura pu être extrait de l’application afin d’utiliser tous les opérateurs disponibles.
Le parallélisme de tâches : Le parallélisme de tâches peut aussi permettre d’augmenter les performances d’un processeur. En utilisant le parallélisme de tâches, celui-ci peut être capable d’avoir plusieurs tâches prêtes à être exécutées et ainsi utiliser au mieux ses ressources. La possibilité d’exécuter plusieurs tâches permet au processeur d’éviter les blocages dus aux tâches qui sont en attente d’une donnée en mémoire. Deux types d’ordonnancements existent :
— l’exécution bloquée, qui consiste à changer de tâche dès qu’elle est bloquée, par exemple lors d’un accès à une ressource partagée ou lors d’une dépendance de données ou d’instructions,
— l’exécution successive, qui consiste à changer de tâche après chaque cycle d’exécution ; les dépendances de contrôle et de données sont alors éliminées. Pour obtenir une occupation optimale du pipeline, il faut idéalement exécuter beaucoup de tâches en parallèle afin d’optimiser l’utilisation du processeur.
Certains processeurs peuvent exécuter plusieurs tâches simultanément, il s’agit des processeurs Chip MultiThreading (SMT). Plusieurs instructions provenant de différents threads peuvent ainsi être simultanéement présentes dans le pipeline du processeur. Ainsi, à chaque cycle, des opérations appartenant à des tâches différentes peuvent être exécutées, ce qui permet de réduire considérablement les pénalités d’exécution de chacune des tâches (lors du chargement d’une donnée en mémoire par exemple). Certains processeurs MIPS (MIPS MT) [18] permettent ce mode de fonctionnement (exécution bloquée), ainsi que l’UltraSPARC [19] (exécution successive) ou encore la technologie Hyper-Threading d’Intel [20] utilisée dans les processeurs Itanium, Core et Xeon.
Homogène vs hétérogène : Dans une architecture multi-cœurs, les ressources de calcul peuvent être identiques, on parle alors d’architecture homogène. Ceci facilite l’ordonnancement des tâches sur les processeurs puisque chaque tâche peut être allouée sur chaque processeur. A l’opposé, une architecture hétérogène est constituée de ressources différentes, comme par exemple des unités matérielles dédiées à certaines applications, ou encore des processeurs optimisés pour des applications spécifiques. Ceci permet d’obtenir des performances plus importantes pour un coût énergétique plus faible car l’adéquation entre les ressources de calcul et les applications est importante. Par contre, ces architectures rendent l’équilibrage de la charge entre les ressources complexe car les ressources hétérogènes utilisent généralement des jeux d’instructions différents. L’architecture big.LITTLE [21] de ARM est un exemple d’architecture hétérogène prévue pour limiter la consommation énergétique des appareils mobiles. Elle est constituée de deux processeurs ARM, le premier vise à limiter la consommation énergétique, le second est un processeur optimisé pour les performances. Le premier processeur prend en charge la majorité des tâches, en particulier celles qui fonctionnent en arrière plan. Si un besoin en performances important apparaît, le second processeur prend en charge les calculs, par exemple pour un jeu vidéo, ou pour le multimédia. Le premier processeur est celui qui est utilisé la majorité du temps, pour toutes les tâches peu consommatrices en puissance de calcul ; ainsi les gains en consommation énergétique sont importants, ceci sans sacrifier les performances globales de l’architecture puisque les tâches peuvent être migrées d’un processeur à l’autre. D’autres architectures allient des processeurs différents, comme par exemple l’architecture OMAP [22, 23] de Texas Instruments qui associe des processeurs ARM Cortex A9 avec des DSP TI C64x. De manière générale, les architectures hétérogènes sont utilisées dans les domaines où la consommation énergétique est un facteur très important et où les tâches ont des besoins qui varient dans le temps. Ainsi, les cœurs peu consommateurs pourront être utilisés la plupart du temps et les cœurs plus performants pourront être utilisés en cas d’un besoin en performances important.

Mémoire distribuée ou mémoire partagée

                Afin de supporter un maximum de modèles de programmation, le modèle de mémoire partagée permet de garder un espace d’adressage identique entre les différentes tâches. Les communications entre les tâches sont alors facilitées. Par contre, garantir la cohérence des différentes copies des données en mémoire se complexifie avec l’augmentation du nombre de processeurs. À l’inverse, dans un modèle distribué, chaque tâche possède un espace mémoire différent. Ainsi les communications doivent se faire explicitement par le logiciel, par passage de message ou en explicitant un espace mémoire commun à plusieurs tâches. D’un point de vue implémentation physique, les mémoires peuvent elles-aussi être centralisées dans plusieurs bancs mémoire qui sont utilisés par les processeurs. C’est le cas des architectures ARM MPCore [25] ou Intel KNC [26]. Elle peuvent aussi être distribuées entre les différents processeurs, chacun ayant un banc mémoire à proximité. C’est le modèle mémoire utilisé par l’architecture Tile Pro 64 de Tilera [27] par exemple. Cependant une architecture ayant des bancs mémoire distribués peut proposer un modèle de programmation utilisant une mémoire partagée. Par exemple, l’architecture Tile Pro 64 de Tilera propose d’unifier virtuellement toutes les mémoires afin de créer un espace mémoire globalement partagé et accessible par tous les processeurs. Ceci permet de faciliter le portage d’application sur ce type de processeurs.

Synthèse et comparaison des architectures multi-cœurs

Afin de comparer les différentes architectures, trois critères ont été choisis :
— la complexité d’un processeur élémentaire,
— l’uniformité de l’espace mémoire,
— la spécialisation du cotrôle.
La complexité d’un processeur élémentaire prend en compte le type du processeur utilisé dans l’architecture. Un processeur ne possédant qu’une seule unité d’exécution et quelques étages de pipeline sera considéré comme plus simple qu’un processeur capable d’exécuter des instructions dans le désordre et multi-tâches. L’uniformité de l’espace mémoire permet de montrer quel est l’espace mémoire vu de l’application. Une architecture de type GPU a un espace qui est très hétérogène. A l’opposé, une architecture telle que Intel KNC [26] propose un espace totalement uniforme. La spécialisation du contrôle montre les spécificités de l’architecture en termes de contôle des tâches. Un GPU possède un contrôle très spécifique qui gère les tâches, les transferts de données, alors qu’une architecture de type ARM MPCore ne possède pas de contrôle spécifique. On distingue trois groupes d’architectures :
— Les architectures généralistes (triangles oranges), qui sont dotées de processeurs complexes, qui proposent un espace mémoire uniforme et qui n’imposent pas de contrôle spécifique des applications. Les processeurs sont souvent très performants et peu nombreux. Il sont généralement connectés au travers d’un bus (Figure 2.4) et sont quelques fois aidés d’accélérateurs dédiés, en fonction du type d’applications visées. Le faible nombre de cœurs permet de préserver une cohérence des mémoires caches sans fortement impacter les performances. La mémoire partagée permet de supporter un grand nombre de modèles de programmations. Parmi ces architectures, on peut citer l’ARM MPCore, TI Omap, TI TCI6487 [36] et Freescale 8156 [36]. Certaines architectures gardent le même modèle mais utilisent des interconnexions de type tores, comme par exemple le Cell d’IBM [30], le Spurse Engine [37] de Toshiba ainsi que l’architecture KNC d’Intel [26].
— Les architectures massivement parallèles hiérarchiques (triangles bleus Figure 2.3) qui proposent un grand nombre de processeurs et qui sont beaucoup moins complexes. Elles proposent un espace mémoire qui n’est pas uniforme (mémoires locales, mémoires partagées avec les voisins et mémoire globale), par ailleurs des ressources sont dédiées au contrôle des applications. Cette approche permet d’augmenter le nombre de processeurs tout en limitant les latences de communication entre les cœurs (Figure 2.5). C’est l’approche hiérarchique qui consiste à regrouper les processeurs en clusters et à interconnecter les clusters via un réseau sur puce. Le nombre de cœurs étant limité dans un cluster, ils peuvent être interconnectés via un bus ce qui permet des latences faibles ainsi qu’un débit élevé. Une cohérence entre les mémoires caches au sein d’un cluster est aussi possible. Par contre, le portage des applications sur ce type d’architecture est beaucoup plus complexe que pour une multi-coeurs car les parties communicantes de l’application doivent de préférence être effectuées au sein d’un même cluster, les communications entre cluster étant beaucoup moins rapides. Les parties relativement indépendantes peuvent par contre s’effectuer sur des clusters différents. C’est le cas des architectures MPPA de Kalray [33], P2012 de ST/CEA [32] ainsi que l’Ambric AM2045 [38].
— Les architectures massivement parallèles (triangles verts sur la Figure 2.3), qui proposent aussi un grand nombre de processeurs. Cependant, ceux-ci sont organisés en grille, la mémoire peut être vue comme uniforme depuis les processeurs bien qu’elle soit distribuée sur l’architecture. La gestion des tâches est ici laissée au choix de l’utilisateur (Figure 2.6). Ces architectures sont composées d’un nombre très important de processeurs plus simples. Ces processeurs sont interconnectés par des réseaux sur puces en grille, les bus devenant inefficaces quand le nombre de cœurs est important. Afin de diminuer les latences d’accès à une mémoire centralisée, qui augmente avec le nombre de cœurs à cause de la distance ainsi que du nombre d’accès simultanés, la mémoire est distribuée au sein de l’architecture. Une mémoire distribuée implique de gérer spécifiquement les transferts de données ainsi que de protéger les accès aux données partagées. C’est le cas des architectures SODA [39] et ASAP [31]. La suite de cette section détaille quelques architectures de l’état de l’art appartenant aux différents modèles présentés.

Présentation du ARM Mali 200, un processeur graphique à architecture programmable

                  Le processeur ARM Mali 200 [50, 51] vise le marché de l’embarqué et plus particulièrement les smartphones. Ce processeur supporte l’API OpenGL ES 2.0 faite spécialement pour les systèmes mobiles. Cette API permet l’utilisation des ressources programmables, contrairement à OpenGL ES 1.1 qui est dédié aux architectures paramétrables. Cette architecture n’est pas unifiée : un processeur est dédié aux opérations sur les sommets, un deuxième se consacre aux opérations sur les fragments. Une des particularités de cette architecture est qu’elle est basée sur un rendu par tuile. Toutes les opérations liées à la géométrie de la scène sont effectuées, ainsi toutes les primitives sont placées dans l’image. Ensuite, une liste des primitives se situant dans chaque tuile ainsi que des primitives se situant à cheval sur les bords de la tuile est sauvegardée en mémoire. Enfin, toutes les opérations de rendu sont effectuées sur chaque tuile en une fois seulement. Le principal avantage d’une architecture utilisant un rendu par tuile est que toutes les informations, en particulier les données stockées dans le framebuffer, peuvent être stockées dans la puce pour la tuile en cours. Les accès aux données de la tuile en cours sont très rapides puisqu’il n’y a pas besoin d’accéder à la mémoire extérieure. Une fois le rendu de la tuile fini, les données sont alors écrites dans le framebuffer en une seule fois. Le processeur Mali possède deux mémoires de tuiles ; ainsi, quand le calcul d’une tuile est fini, il peut utiliser instantanément la deuxième mémoire pendant que les données sont écrites dans la première mémoire. Afin de limiter l’impact des pénalités induites par les accès mémoire pour les données des textures, jusqu’à 128 opérations peuvent être en cours d’exécution en même temps. Ceci permet au processeur de passer au calcul d’un nouveau fragment le temps nécessaire pour accéder à une texture lors du calcul du fragment 0. Les 127 autres opérations peuvent pendant ce temps faire des requêtes en mémoire. Quand la donnée sera prête, le calcul du fragment 0 peut continuer. Afin de limiter la bande passante liée aux accès aux textures, un cache matériel permet de stocker la texture. Il utilise des unités de compression et de décompression afin de diminuer encore la bande passante nécessaire. De plus, les textures peuvent être stockées en cache de manière compressée, ce qui participe à réduire la surface silicium. Lors d’un accès, le pixel de la texture est décompressé au vol. L’architecture du Mali 200 n’est pas une architecture unifiée, principalement afin de diminuer la surface nécessaire, car le processeur de géométrie n’utilise que 30 % de la surface totale puisqu’il est spécialisé pour la partie géométrie. Un processeur effectuant les deux étages serait beaucoup plus complexe. Afin d’augmenter les performances, plusieurs unités de fragment peuvent être ajoutées. Elles pourront ainsi s’occuper de plusieurs tuiles en parallèle. Par contre, toutes les opérations liées à la géométrie de la scène étant effectuées en une seule passe, les données résultantes de ces opérations doivent être stockées en mémoire pour pouvoir être utilisées pour les opérations de rendu. Ceci peut utiliser beaucoup d’espace mémoire et limite la complexité de la scène pouvant être rendue.

Synthèse des architectures des accélérateurs graphiques

                   Les processeurs graphiques sont passés d’un modèle paramétrable (Figure 2.10.a), où seuls quelques paramètres pouvaient être modifiés, à un modèle presque totalement programmable où presque toutes les étapes du rendu graphique peuvent être modifiées grâce à des programmes appelés shaders (Figure 2.10.c). Cette évolution est arrivée sur les processeurs hautes performances équipant nos ordinateurs, mais aussi dans le monde de l’embarqué où les processeurs graphiques, qui à l’origine n’occupaient que la fonction d’accélérateur graphique, sont maintenant en passe de devenir des accélérateurs généralistes au même titre que les architectures multi-cœurs. Cependant, le premier objectif des accélérateurs graphiques est justement d’accélérer le rendu graphique et ceci avec de très bonnes performances, que ce soit en termes de performances pures, de consommation énergétique ou encore de surface silicium. Pour cela, ces architectures offrent un haut niveau de parallélisme permettant de traiter un grand nombre de données en parallèle. L’ordonnancement des calculs sur les processeurs permet d’utiliser au maximum leurs ressources tout en masquant les latences mémoires. Il est de plus optimisé pour les traitements réguliers qui suivent les mêmes branchements. L’accélération des applications généralistes est alors contrainte par l’architecture qui est optimisée pour le graphique mais pas pour l’accélération d’applications généralistes, à cause des contraintes dûes aux communications entre threads, de la hiéarchie mémoire et de l’ordonnancement des threads.

Le rapport de stage ou le pfe est un document d’analyse, de synthèse et d’évaluation de votre apprentissage, c’est pour cela chatpfe.com propose le téléchargement des modèles complet de projet de fin d’étude, rapport de stage, mémoire, pfe, thèse, pour connaître la méthodologie à avoir et savoir comment construire les parties d’un projet de fin d’étude.

Table des matières

1 Introduction 
2 État de l’art 
2.1 Introduction 
2.2 Architectures multi-cœurs embarquées 
2.2.1 Choix architecturaux
2.2.1.1 Les processeurs
2.2.1.2 Modèles d’exécution
2.2.1.3 Modèle mémoire
2.2.1.4 Réseau d’interconnexion
2.2.1.5 Modèles de programmation
2.2.1.6 Architectures symétriques et asymétriques
2.2.2 Synthèse et comparaison des architectures multi-cœurs
2.2.3 Architecture multi-cœurs OMAP de Texas Intruments
2.2.4 Architecture many-cœurs hiérarchique P2012
2.2.5 Architecture many-cœurs Tilera TilePro 64
2.2.6 Syntèse des architectures multi-cœurs embarquées
2.3 Processeurs graphiques
2.3.1 Évolution des processeurs graphiques
2.3.1.1 Les premiers accélérateurs
2.3.1.2 L’arrivée de l’accélération 3D
2.3.1.3 Les premiers GPU programmables
2.3.1.4 Les architectures unifiées
2.3.1.5 Comparaison des architectures graphiques
2.3.2 Présentation du PowerVR MBX, un processeur graphique à architecture paramétrable
2.3.3 Présentation du ARM Mali 200, un processeur graphique à architecture programmable
2.3.4 Présentation de quelques processeurs graphiques à architecture unifiée 3
2.3.4.1 Imagination Technologies PowerVR SGX
2.3.4.2 Nvidia Geforce GTX680
2.3.4.3 AMD Radeon 7970
2.3.5 Synthèse des architectures des accélérateurs graphiques
2.4 Conclusions 
3 Etude d’un pipeline graphique 
3.1 Introduction
3.2 Description du rendu graphique 
3.2.1 Partie sommets (Vertex)
3.2.2 Partie primitives (Triangle)
3.2.3 Partie fragments (Fragment)
3.2.4 Partie liée à la mémoire vidéo (Frame Buffer)
3.3 Implémentation séquentielle
3.3.1 Étude de l’implémentation séquentielle
3.3.2 Profilage du pipeline graphique
3.4 Implémentation parallèle 
3.4.1 Découpage de l’application
3.4.2 Environnement de simulation
3.4.3 Parallélisation du rendu graphique
3.4.4 Résultats de profilage
3.4.5 Mesures par image
3.4.6 Parallélisation au niveau des données
3.5 Analyse des besoins d’un pipeline graphique 
3.6 Vers une adaptation dynamique du pipeline graphique
4 Support de la dynamicité 
4.1 Introduction
4.2 État de l’art des méthodes d’équilibrage de charge 
4.2.1 Méthodes d’équilibrage de charge dans la littérature
4.2.1.1 Équilibrage de charge dans les grilles de calcul
4.2.1.2 Équilibrage de charge dans les architectures embarquées
4.2.1.3 Équilibrage de charge dans les processeurs graphiques
4.2.2 Comparaison des méthodes
4.2.2.1 Méthodes statiques
4.2.2.2 Méthodes dynamiques
4.2.2.3 Fonctionnement centralisé ou distribué
4.2.2.4 Concentration de la charge
4.2.3 Conclusions
4.3 Approche proposée pour l’équilibrage de charge
4.3.1 Modèle applicatif
4.3.2 Méthode de Load Balancing proposée
4.3.2.1 Surveillance de l’application
4.3.2.2 Calcul de charge
4.3.2.3 Prédiction de l’évolution de la charge
4.3.2.4 Adaptation du parallélisme
4.4 Conclusion 
5 Architecture multi-cœurs supportant le rendu graphique 
5.1 Introduction 
5.2 Les ressources de calcul 
5.2.1 Jeu d’instructions
5.2.1.1 Besoins applicatifs
5.2.2 Profondeur du pipeline
5.2.3 Support du Multi-Threading
5.2.3.1 Besoins applicatifs et contraintes
5.3 Les modèles d’exécution et de programmation 
5.4 La hiérarchie mémoire
5.5 Dimensionnement des éléments de l’architecture 
5.6 Le contrôle de l’architecture 
5.6.1 Gestion des synchronisations
5.6.2 Fonctions du module de synchronisation
5.6.2.1 Mapping mémoire
5.6.2.2 Modes de fonctionnement (saturation)
5.6.2.3 API bas niveau
5.6.2.4 Accès simplifié aux compteurs
5.6.2.5 API des fonctions de synchronisation
5.6.2.6 Gestion des FIFO
5.6.3 Surveillance de l’application
5.6.3.1 Approche
5.6.3.2 Structure interne
5.6.3.3 Les compteurs
5.6.3.4 La détection
5.6.3.5 Gestion des étages
5.6.3.6 Dimensionnement
5.6.3.7 Caractérisation en surface et en consommation
5.6.3.8 Passage à l’échelle
5.6.4 Contrôle du parallélisme
5.7 Mise à jour du parallélisme
5.8 Architecture proposée
5.8.1 Transfert des données
5.8.2 Exécution
5.9 Optimisations possibles
5.9.1 Chargement des textures
5.9.2 Rasterizer matériel
5.10 Conclusions
6 Validation et benchmarking 
6.1 Environnement de simulation 
6.1.1 Module de surveillance
6.1.2 Module de synchronisation
6.1.3 Le module d’équilibrage de charge
6.1.4 Système de trace
6.2 Portage de l’application 
6.2.1 L’interface de programmation
6.2.2 Choix du scenario applicatif
6.2.3 Support de la parallélisation dynamique
6.2.4 Adaptation de l’application
6.2.5 Vers un benchmark plus complexe
6.2.5.1 Évaluation du benchmark
6.2.5.2 Extraction des composantes des frames
6.2.5.3 Extrapolation
6.3 Étude des performances de l’équilibrage de charge
6.3.1 Comparaison de l’équilibrage de charge avec un parallélisme fixe
6.3.2 Comparaison de l’équilibrage de charge avec des parallélismes calculés hors-ligne
6.3.3 Scalabilité de l’équilibrage de charge
6.3.4 Évolution du temps de blocage
6.3.5 Impact des paramètres de mesure sur les performances
6.4 Conclusion
7 Conclusions et perspectives 
Bibliographie

Télécharger le rapport complet

Télécharger aussi :

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *