Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
1
Analyse et Optimisation de code
Principes généraux Processeur Alpha – Tru64 Unix
2
Optimisation séquentielle
Méthodologie proposée Principes généraux Optimisation du compilateur Timing and profiling Quelques méthodes d’optimisation “manuelle” Le but de cette présentation est est de présenter un certain nombre de règles et de techniques permettant d’optimiser un code sur les architectures actuelles. Certaines techniques valides pour une application vont au contraire detériorer les performances d’une autre application. Il est nécessaire d’acquérir une compréhension minimum de la facon dont un code est implémenté sur la machine, la facon dont on peut modifier cette implémentation pour améliorer les performances de ce code. D’autres techniques simples permettent d’améliorer considérablement les performances; Pour améliorer les performances d’une application, il est nécessaire de déterminer les parties du code qui ont une forte consommation CPU. A cette connaissance devra s’ajouter, l’analyse des causes de cette forte consommation (compteurs Hardware) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
3
Méthodologie conseillée
Validité du programme à optimiser Utiliser des codes déja optimisés ou s’y ramener Utiliser des algorithmes performants Analyser le code, et se concentrer sur les sections critiques Utiliser les capacités d’optimiser du compilateur Effectuer des modifications dans le code pour optimiser les sections critiques Si dans cette présentation, on applique les principes énoncés sur des stations Alpha, un grand nombre de ces principes sont applicables à la plupart des architectures utilisées pour le développement d’applications scientifiques. Les étapes d’optimisation d’un code sont succesivement: - détecter les parties consommatrices de temps CPU, - puis identifier les problèmes éventuels On suppose au préalable la validité du code Après avoir présente les principes généraux de fonctionnement de l’architecture d’un processeur et les techniques d’optimisation qui en découlent, je présenterai d’une part les outils permettant de faire une première analyse du code et de mettre en évidence des sections critiques, puis ceux qui fourniront des informations sur les causes. Nous verrons ensuite que le compilateur est l’outil par excellence pour l’adaptation performante d’une appication a une architecture particulière. Enfin nous verrons en conclusion quelques règles générales pour le développement performant d’une application. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
4
CIMENT – MIRAGE Laurence Viry
Principes Généraux Architecture des processeurs Augmenter le vitesse d’horloge des processeurs Techniques de micro-architecture permettant d’augmenter le nombre d’instructions par cycle Mémoire Mémoire hiérarchique (registre, cache,…) Mémoire virtuelle et Paging Optimisation des accès Quelques techniques d’optimisation 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
5
Architecture des processeurs Fréquence d’horloge
La fréquence de l’horloge détermine la durée d’un cycle Chaque opération utilise un certain nombre de cycles La fréquence d’horloge détermine les performances La fréquence d’horloge est fonction de : La technologie des semi-conducteurs Le packaging Les circuits … 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
6
Comment faire des processeurs plus rapides?
Augmenter la fréquence d’horloge (limites techniques, solution coûteuse) Permettre l’exécution simultanée de plusieurs instructions Exécution en parallèle (duplication de composants hardware, coûteux) Pipelining (pas de duplication de composants hardware) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
7
CIMENT – MIRAGE Laurence Viry
Architecture HPC Processeur RISC Instruction pipelining Branchement reporté Load/Store Architecture … Seconde génération de processeur RISC Processeur superscalaire (pipes en parallèle) Processeur « superpipelined » (profondeur des pipes) Processeur LIW (parallélisme d’instructions logiciel) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
8
CIMENT – MIRAGE Laurence Viry
Architecture Alpha 21264 Architecture RISC Software Pipelining Mémoire Hiérarchique (registre, caches,mémoire principale) Système de prédiction de branchement Prefetching Architecture Super-Scalaire Modification de l’ordre de l’exécution des instructions Exécution spéculative … Architecture RISC: Pipelining Mémoire Hierarchique Architecture Super-scalaire: Modification de l’ordre des instructions ce qui implique que ces instructions sont exécutées aussitôt que c’est possible. Utiliser plusieurs unités fonctionnelles en cachant la latence de la mémoire. Le compilateur ne peut pas tout prendre en charge. Exécution spéculative: spéculation sur le chargement. L’instruction est exécutée même si elle ne fait pas encore partie du flot des instructions à exécuter. On verra que dans le cas des prédictions de branchement, cela permettra d’effectuer du software pipelining la ou le traitement du branchement empêchait tout parallélisme. Prédiction sur les branchements: le système de branchement ainsi que l’exécution spéculative va permettre grâce aux techniques de pipelining une utilisation optimisée du parallélisme d’instructions. Optimisation du parallélisme d’instructions 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
9
Exécution spéculative
Exemple: LD R10,R2(R0) charger dans R10 à partir de la mémoire … instructions de type différents(pas de FDIV) FDIV R4,R5,R6 R4=R5/R6 R5 et R6 sont déjà dans les registres pour d’autres instructions et FDIV est inutilisée Le calcul par FDIV peut commencer, le résultat sera placé dans un espace temporaire Le calcul de R4 se fera sur un cycle, temps de récupération du résultat 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
10
CIMENT – MIRAGE Laurence Viry
Alpha Architecture Super-s 4 chargement d’instruction par cycle 6 instructions par cycle 4 instructions entières 2 instructions en virgule flottante 1 unité non bloquante “Load/Store” 4 unités fonctionnelles entières 64 bits 1 unité fonctionnelle addition virgule flottante 32/64 bits 1 unité fonctionnelle multiplication virgule flottante 32/64 bits unité fonctionnelle SQRT en virgule lottante (prefetch: charge les données dans le cache avant leur utilisation déplacement conditionnel remplace les branchements à l’intérieur des boucles 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
11
CIMENT – MIRAGE Laurence Viry
Software Pipelining Parallélisme d’instructions Une opération s’exécute en plusieurs étapes indépendantes par des éléments différents du processeur Le pipelining consiste à exécuter simultanément des étapes différentes d’ opérations différentes Exemple: opération s’effectuant en 5 opérations Charge l’instruction Décode Charge les opérandes Exécute Ecriture 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
12
Software Pipelining (suite)
3 instructions simultanées dans le pipe Charge l’instruction Décode Charge opérandes Exécute Ecriture Charge l’instruction Décode Charge opérandes Exécute Ecriture Charge l’instruction Décode Charge opérandes Exécute Ecriture 3 instructions en parallèle en 7 cycles (15 cycles en séquentiel 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
13
Software Pipelining (suite)
Sans pipelining résultat tous les deux cycles pour un processeur 195Mhz: 97Mflops Avec pipelining Après l’initialisation du pipe: 1 résultat par cycle pour un processeur 195Nhz: 195Mflops En général, l’unrolling des boucles améliore le parallélisme d’instructions do i=1, t(i)=t(i)*t(I) enddo do i=1, ,2 t(i)=t(i)*t(i) t(i+1)=t(i+1)*t(i+1) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
14
Pipelining: accès mémoire
L’accès mémoire est une fonction coûteuse en temps qui prend plusieurs cycles. Utiliser le procédé de pipelining pour le superposer à d’autres fonctions du processeur L’optimisation du compilateur peut réordonner les instructions pour favoriser ce procédé 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
15
CIMENT – MIRAGE Laurence Viry
Accès Mémoire Mémoire hiérarchique Registres Caches Mémoire Virtuelle Organisation des caches Optimisation des accès mémoire Outils d’analyse identifiant les problèmes de cache Quelques exemples Avoir un processeur rapide ne suffit pas, il faut que l’accès à la mémoire augmente en conséquence. Plus la mémoire est rapide d’accès plus elle est coûteuse => Mémoire hiérarchique (petite mémoire rapide près du processeur et mémoire de capacité plus grande à l’extéreur. Registres: La mémoire la plus rapide d’accès, la plus proche du processeur. Toute opération utilise le stockage de ses opérandes dans les registres. Il y a un nombre limité de registres. Si le processeur a besoin de plus de registres, il devra vider certains registres et stocker l’information ailleurs et charger les données utiles dans les registres disponibles. Les performances seront accrues si les données fréquemment utilisées sont dans les registres. Cache: C’est un stockage mémoire à accès rapide donc coûteuse et de petite taille situé entre les registres et la mémoire principale. Le but va être de réutiliser au maximum les données chargées dans un cache en utilisant les principes de localité spaciale et temporaire. Il faudra également tenir compte de l’organisation de ces caches. En général, on étend le principe du cache primaire à une deuxième zone mémoire moins rapide que le cache primaire mais plus rapide que la mémoire principale. Ce type de mémoire sera plus grande que le cache primaire(parce que moins coûteuse), elle se situe entre le cache primaire et la mémoire principale. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
16
Mémoire hiérarchique (DS20-EV6)
Registres Le processeur utilise uniquement les données dans les registres Temps d’accès: 2ns Deux niveaux de caches (sur certaines machines 3 niveaux) Cache primaire (L1) Accès par bloc (ligne de cache): 32 bytes Taille: 64KB Temps d’accès: 2 à 3 cycles Cache secondaire (L2) Accès par bloc : 128 bytes Taille: 4MB Temps d’accès : 10 à 15 cycles Mémoire principale (DS20: taille 2.5GB/proc, latence: 220ns ) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
17
Organisation des caches
Le cache est divisée en lignes de cache de n mots Direct-Mapped Cache Chaque adresse mémoire est associée à une ligne de cache Fully Associative Cache Chaque adresse correspond à n’importe quelle ligne de cache N-way set-associative Cache (2-way et 4-Way) Une adresse a une alternative de N lignes de cache Instruction Cache Organisation des caches: Un cache est divisé en ligne de cache, chacune de ces lignes contenant plusieurs mots. Lorsque le processeur a besoin d’une donnée, le cache regarde si il posséde cette donnée. Si non, le cache transmet la requête à la mémoire principale. Il ne récupère pas que la seule donnée demandée mais une ligne de cache entière. Donc si le processeur demande une donnée voisine, il a une forte probabilité que le cache puisse lui fournir. Direct-mapped cache stocke chaque adresse de la mémoire à une place précise dans le cache, ce qui génére dans certains cas des conflicts d’accès et des va et vient cache-mémoire. Full-associative cache peut stocker la ligne de cache dans n’importe quelle partie du cache, la ligne de cache la plus anciennement consultée sera éliminée du cache. Ce type de cache est très consommateur en taille sur le chip, coût et vitesse, ils ont tendance à être de petite taille. N-Set-assocaitive cache: N direct-mapped cache côte à côte pour un seul cache.Chaque adresse correspond à une ligne particulière de cache des N direct-mapped caches. En général N=2 ou 4 (DS20 N=2) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
18
CIMENT – MIRAGE Laurence Viry
Cache Localité temporaire et spatiale des données Cache Hit Fournit la donnée demandée à partir du cache Cache miss Récupère la donnée dans la mémoire principale La stocke dans le cache 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
19
CIMENT – MIRAGE Laurence Viry
Cache thrashing parameter (max=1024*1024) dimension a(max),b(max),c(max),d(max) …… do i=1,max a(i)=b(i) + c(i)*d(i) enndo Difficultés les vecteurs sont alloués de façon contigue Chaque vecteur à une taille de 4MB (taille du cache secondaire) Deux méthodes pour corriger ce problème redimensionner les vecteurs introduire des variables entre les tableaux pour décaler les adresses 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
20
CIMENT – MIRAGE Laurence Viry
Mémoire Virtuelle Dernière couche de la hiérarchie mémoire Registres Cache L1 … Cache LN Mémoire principale SWAP – disque Chaque programme utilise un espace d’adressage logique en correspondance avec l’adressage physique pour l’accès aux données Chaque programme découple les adresses utilisées par le programme (adresses virtuelles) avec les adresses physiques . Le programme voit l’espace des adresses qui commence à zéro ce qui ne correspond pas à l’espace d’adressage physique. Ceci apporte une certaine flexibilité et donne l’impression à chaque programme d’avoir l’intégralité de la mémoire à lui seul. La mémoire du programme est divisée en PAGES, la taille d’une page dépendant de la machine. Les pages allouées ne sont pas forcément contigues mais dépendent des besoins du programme=> optimisation des accès mémoire, minimisation des transferts disques. Page Tables: 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
21
Pourquoi la mémoire virtuelle
Allocation mémoire Espace mémoire divisé en pages pas forcément contigues Simplifie l’allocation mémoire associé à un process Code relocation Map des adresses logiques identiques à chaque run Pagination Transfert des pages de la mémoire principale au disque en fonction de l’utilisation Disque dernier niveau de la hiérarchie mémoire (swap) Espace de pagination sur le disque est la dernière partie et la moins performante de la hiérarchie mémoire à laquelle fera référence un programme. On peut considérer la relation entre mémoire principale et espace de pagination comme étant de même nature que la relation entre mémoire principale et cache. Le même type d’optimisation sera appliquée, basée sur le principe de localité. On peut exécuter des programmes qui ont besoin de plus de mémoire que la mémoire disponible sur la machine mais avec des chutes de performance dues aux accès mémoire (cache misses et TLB misses). 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
22
Mémoire Virtuelle : Page
Les transferts de la mémoire virtuelle à la mémoire physique se font par pages Process Region Table Virtual Translation Page Table Physical Address Page Tables: C'st la "page table" qui contient l'information qui permet de passer de l'adresse virtuelle connue par le programme à l'adresse physique. Chaque process a plusieurs page table associésà différentes régions comme le code objet, les données. Pour déterminer la localisation d'une variable, il fauda: Déterminer quelle "page table" est concernée Le programme connaît l'adresse virtuelle de la page table, il faut une translation supplémentaire adresse virtuelle-adresse physique. Ensuite, on récupére la donnée Virtual address Location 1000 données 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
23
TLB (Translation Lookaside Buffer)
TLB : Cache contenant les informations nécessaires aux translations adresse virtuelle – adresse physique Réduit le coût des références mémoire Taille du TLB limité TLB misses: L’adresse n’est pas dans le TLB Chercher l'information dans une page en mémoire La page contenant la donnée est sur disque, générer une nouvelle page en mémoire Le principe qui permet de récupérer une donnée nécessite deux translations adresse virtuelle-adresse physique, ce qui est beaucoup trop compliqué et peu performant. Le principe du cache est également appliqué aux "page table". Chaque machine moderne utilisant la mémoire virtuelle possédeun cache spécial appelé "translation lookaside buffer" (TLB). L'exploration du TLB se fait en même temps que l'exécution de l'instruction. Si l'adressec de la donnée est dans le cache, l'accèsra très rapide. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
24
CIMENT – MIRAGE Laurence Viry
Page Faults Scénario générant un page fault Il n'existe pas de table concernant la page La page a été restockée sur disque Chaque programme génére des "page fault" Beaucoup de "page fauts" Mémoire partagée par plusieurs process Mémoire requise supérieure à la mémoire réelle disponible 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
25
Techniques d’optimisation
Analyse interprocédurale Inlining Accès mémoire Réutilisation du cache Stride minimum Copie … Réduction des TLB misses Optimisation de boucles 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
26
Analyse Interprocédurale
Par défaut: analyse du compilateur sur une seule procédure à la fois. Inconvénients: manque d’information pour analyser les dépendances, pour mettre en évidence les constantes mettre en évidence les variables jamais utilisées traitement des variables à la frontière des procédures L’analyse interprocédurale(IPA) permet d’effectuer une optimisation du code en pré sence de l’intégralité de ce code. Certaines optimisations ne seront possibles qu’après une IPA. Note: Si vous utilisez la parallélisation automatique, l’appliquer après l’IPA.Car si on utilise la parallélisation automatique sur des parties séparées du code et qu’on applique l’inlining en utilisant l’IPA après, in “inline” du code parallélisé dans un programme principal qui n’est pas compilé pour initialiser une exécution parallèle. Aussi, il faut utiliser la parallélisation automatique après avoir compiler toutes les parties du code. OPTIMISATION CONSERVATIVE 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
27
Analyse Interprocédurale (IPA)
Analyse plusieurs procédures simultanément Renvoie la plupart des actions du compilateur juste avant l’édition de liens compilations: 2 phases phase sommaire : récupère les informations locales utilisées ultérieurement par l’IPA création de WHIRL objets dans “*.o” (fe) Edition de liens IPA: analyse et transforme les WHIRL objets back-end du compilateur: crée les “relocatables objects” édition de liens Facile à mettre en œuvre: -pipeline ou –O5 (compilation) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
28
... ... ... ... IPA et Optimisation inter procédurale Compilation:
édition de liens: ... source source fe fe ... .o (whirl) .o (whirl) IPA et Optimisation inter procédurale .l ... .l be be .o ... .o Edition de Liens 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry a.out
29
Analyse Interprocédurale(suite)
Intérets: permet des optimisations supplémentaires Software Pipelining, Optimisation des boucles imbriquées, Inlining, réduction des conflits de cache(padding,…) élimination des fonctions jamais utilisées détection des noms globaux … Inconvénients: augmente le temps global compilation/édition de liens augmente la taille de l’exécutable peut modifier sensiblement les résultats 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
30
CIMENT – MIRAGE Laurence Viry
Inlining Remplace l’appel d’une procédure par le code de cette procédure Intérets: élimine l’overhead dû à l’appel (sauvegarde des registres, appel, instructions de retour, …) fournit un contexte plus large pour l’optimisation scalaire et de boucles. Inconvénients: Augmente le temps de compilation Crée des problèmes d’allocation de registres plus complexes augmente la taille du code Critères d’Inlining: fréquence des appels taille de la procédure appelée L’heuristique d’inlining peut bénéficier de la connaissance de la fréquence d’appel, mais il n’est pas toujpours possible de connaître cette fréquence d’appel à la compilation. L’IPA permet le feedback nécessaire à la décision. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
31
Optimisation des accès mémoire
Stride Fortran: stockage par colonne Parcourt d’un tableau 2D par l’index le plus à gauche C : stockage par ligne Parcourt d’un tableau 2D par l’index le plus à droite Regroupement de données Optimisation par copie Optimisation des boucles 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
32
Réutilisation du cache: stride
Stride égal à 1 (Fortran) do i=1,n do j=1,n a(i,j)=b(i,j) enddo sera modifié 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
33
Réutilisation du cache (suite)
Regrouper les données utilisées dans une même section de code d=0 do i,1,n j=index(i) d=d+sqrt(x(j)*x(j) + y(j)*y(j) + z(j)*z(j) enddo d=d+sqrt(r(1,j)*r(1,j) + r(2,j)*r(2,j) + r(3,j)*r(3,j) x,y et z seront regroupés dans un même tableau r 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
34
Optimisation du cache par copie
Copie d ’une partie des données dans un tableau temporaire taille du tableau < 64*taille_page suffisamment petit: réutilisation des données du cache ne peut être pris en charge par le compilateur Performances: diminue les " TLB misses » " L1 et L2 misses " peuvent rester importants Overhead du à la copie Préférer le " Cache Blocking " lorque c ’est possible 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
35
Recouvrement des latences d’accès aux données
Par le système pour les faibles latences: caches primaires et secondaires data prefetch pas intégrée aux langages C et Fortran insérée automatiquement par le compilateur Manuellement par le programmeur à l’aide d’une directive pour certains compilateurs Les instructions de prefetching déplacent les données en avance de la mémoire principale vers le cache, ce qui permet de recouvrir la latence d ’accès aux données par un autre travail. LNO génére les instructions prefetch et effectue un unrolling pour éviter la redondances des instructions de prefetching. Le pseudo-prefetching permet de déplacer les données vers le cache primaire, à partir de la mémoire principale ou du cache secondaire. Controler le prefetching: Pour obtenir les meilleures performances, LNO suppose que les données ne tiennent pas dans le cache. Il génére des instructions de prefetching dans les boucles. Cette technique, souvent efficace, peut générer plus d ’overhead que de gain dans les cas ou les données sont suffisamment petites pour tenir dans le cache. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
36
Optimisationde boucles
Unrolling Boucles imbriquées Loop interchange Références mémoire Blocking Out-OF-Score Dans la majorité des applications, les boucles sont la partie de consommation CPU la plus importante. Quelquefois, le compilateur effectue des modifications judicieuse pour obtenir de bonne performance et parfois, il faudra modifier manuellement le code pour aider le compilateur. Certaines modifications vont améliorer l’optimisation du compilateur et réduire celle d’un autre compilateur. Pour optimiser des boucles, il faudra déja analyser ce qui est prédominant dans le traitement d’une itération. Les références mémoire ou les opérations flottantes, on saura allors sur quoi l’effort doit être porté, les références mémoire ou les calculs. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
37
CIMENT – MIRAGE Laurence Viry
Loop Unrolling Diminue l’overhead dû à la gestion des boucles Favorise le parallélisme du processeur Mais nécessite une boucle de préconditionnement Les boucles candidates à l’unrolling sont: Un nombre « raisonnable » d’instructions à chaque itération Petit: overhead de la boucle de préconditionnement, sauf si le nombre d’itérations est constant Nombre d’instructions par itération important: augmente la taille du code et des accès mémoire Pas d’appel de procédures Condition de branchement possible dans le cas de processeur superscalaire (exécution conditionnel) Boucle externe de boucles imbriquées dans certains cas 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
38
Boucles imbriquées Unrolling : Boucle interne et/ou boucle externe ?
stride => favoriser la réutilisation des caches Taille des boucles => favoriser les boucles à grand nombre d'itérations Traitement des boucles non récursives => augmente le taux de parallélisme: Lorsqu’o travaille avec des boucles imbriquées, on a souvent à faire à des problèmes de stride et donc d’accès mémoire. Optimisation des accès mémoire: 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
39
CIMENT – MIRAGE Laurence Viry
Loop Interchange Centrer l’activité sur les boucles les plus internes Minimiser le stride Nécessite une analyse de dépendance Par l’utilisateur Par le compilateur Parallélisation automatique Paralléliser sur la boucle externe Unrolling sur la boucle interne L’imbrication des boucles se fait souvent en fonction du model, il est parfois, utile en ce qui concerne les perforances et si c’est possible d’intervertir les boucles; Ce qi permet: De centrer l’activité des boucles imbriquées sur les boucles les plus internes et effectuer de l’unrolling Minimiser le stride d’accès au données en mémoire Ce procédé va dépendre de l’existence de dépendances entre les itérations successives. L’analyse de dépendance se fait rarement de façon automatique par le compilateur mono-processeur. Par contre sur les machines parallèles, le compilateur effectuera l’interchange si ca améliore les performances sans changer les résultats. Lorsque le compilateur effectue de la parallélisation automatique, il préférera paralléliser sur la boucle externe pour minimiser l’overhead et effectuer de l’unrolling sur les boucles les plus internes pour utiliser de façon optimale le processeur superscalaire ou vectoriel. Il lui faut donc parfois modifier l’ordre des boucles et donc faire une analyse de dépendance des itérations 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
40
CIMENT – MIRAGE Laurence Viry
Loop Interchange? DO I=1,N DO J=1,N A(J,I)=B(I,J) ENDDO DO J=1,N DO I=1,N A(J,I)=B(I,J) ENDDO L’inversion des boucles ne résoud pas les problèmes d’accès 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
41
CIMENT – MIRAGE Laurence Viry
Cache Blocking Principes: minimiser les transferts utiliser entièrement la ligne de cache réutiliser au maximun les données dans le cache minimiser le nombre de références différentes à des pages physiques (TLB misses) Méthode découper les données en blocs tenant dans le cache ajouter des boucles extérieures qui contrôlent la taille des blocs Cas de la multiplication de grandes matrices: 2 matrices découpées en blocs colonnes 1 matrice en bloc ligne Dans certains cas, le fait de modifier l’ordre des itérations va permettre de ramener les accès mémoire à des strides de 1. Mais ce n’est pas toujours le cas, pour d’autres cas, on va diminuer le stride de certains accès et augmenter le stride d’autres. On réduit les TLB misses et les secondary misses. En ce qui concerne les primary misses,, du fait de la faible latence de l ’accès à ce type de mémoire, il peut y avoir recouvrement par le système avec des taches de calcul. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
42
CIMENT – MIRAGE Laurence Viry
Cache Blocking Exemple: multiplication de deux matrices do j=1,n do i=1,m do k=1,p c(i,j)=c(i,j)+a(i,k)*b(k,j) enddo m n p lda ldb ldc Scs MFLOPS La raison pour laquelle, il y a baisse de performance est tres claire., ilsuffit d ’utiliser perfex et on constate une forte fr ’equence des événements « »TLB misses », « primary cache misses » et secondary cache misses ». Lorsque les structures de données sont trop grosses pour tenir dans le cache, une solution consiste à les découper en blocs suffisamment petits pour tenir dans le cache. La dégradation est plus rapide que l ’augmentation de la taille. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
43
Multiplication de matrices
B = Les blocs de a, b et c tiennent dans le cache simultnément. En divisant en blocs, on divise le nombre d ’accès par la taille des blocs, on minimise donc le transfert cache-mémoire. Il faudra faire attention, qu ’au sein des 3 blocs destinés à etre dans le cache, il n ’y ait pas de données associées à la meme ligne de cache. Un facteur influencant le choix de la taille des blocs et la taille du TLB. Plus grande est la taille es données, plus le nombre de pages virtuelles s référencées sont nécessaires, plus le nombre de TLB misses va augmenter. Accès: Bloc C : 1fois Bloc A : nb colonnes de C Bloc B : nb lignes de A C A 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
44
CIMENT – MIRAGE Laurence Viry
Fusionner les boucles dimension a(n), b(n) do i=1,n a(i)=a(i)+alpha*b(i) enddo dot=0. dot=dot+a(i)*a(i) dimension a(n), b(n) dot=0. do i=1,n a(i)=a(i)+alpha*b(i) dot=dot+a(i)*a(i) enddo 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
45
CIMENT – MIRAGE Laurence Viry
Les pointeurs Excellent outil pour construire et manipuler toute sorte de structure de données (listes, arbres,…) MAIS Inhibe certaines optimisations du compilateur par manque d’information. ==> Optimisation conservative POURTANT L’utilisation de structures de données appropriées peuvent améliorer les performances de certaines applications 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
46
Méthodologie conseillée
Validité du programme à optimiser Utiliser des codes déja optimisés ou s’y ramener Utiliser des algorithmes performants Analyser le code, et se concentrer sur les sections critiques Utiliser les capacités d’optimiser du compilateur Effectuer des modifications dans le code pour optimiser les sections critiques Si dans cette présentation, on applique les principes énoncés sur des stations Alpha, un grand nombre de ces principes sont applicables à la plupart des architectures utilisées pour le développement d’applications scientifiques. Les étapes d’optimisation d’un code sont succesivement: - détecter les parties consommatrices de temps CPU, - puis identifier les problèmes éventuels On suppose au préalable la validité du code Après avoir présente les principes généraux de fonctionnement de l’architecture d’un processeur et les techniques d’optimisation qui en découlent, je présenterai d’une part les outils permettant de faire une première analyse du code et de mettre en évidence des sections critiques, puis ceux qui fourniront des informations sur les causes. Nous verrons ensuite que le compilateur est l’outil par excellence pour l’adaptation performante d’une appication a une architecture particulière. Enfin nous verrons en conclusion quelques règles générales pour le développement performant d’une application. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
47
Utiliser des codes déja optimisés
Libfastm: CXML (Compaq Extended Math Library) et CXMLP (version parallèle SMP) versions optimisées des BLAS1, 2 et 3 (Basic Linear Algebra) FFT 1,2 et 3-D lapack (système linéaire et valeurs propres) solveurs de systèmes creux 2 versions: Une version séquentielle : libcxml.a Une version parallèle de type SMP : lincxmlp.a FFTW ATLAS 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
48
Algorithmes Performants
Les Mflops est un mauvais indice de performance d’un code Deux algorithmes de multiplications de matrices Même Mflops Temps CPU très différents En priorité à l’optimisation d’un code, s’assurer de la performance des algorithmes utilisés 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
49
Mesures de performance
Mesure globale du temps et autres statistiques commande UNIX "time" Mesure du temps d'une partie de code Fonctions explicites (C et Fortran) de mesure de temps Analyse complète de performance du code Outils de profiling: prof, gprof, pixie, … 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
50
Mesure globale du temps
Time (commande de base UNIX) : time <commande> Temps utilisateur, temps système, elapsed time CPU time = Temps utilisateur + temps système Propriétés Résolution de l'ordre de 10ms Un "system_time" disproportionné peut indiquer un disfonctionnement Nombre important de floatig-point exceptions Nombre important de "page faults" ou de "misaligned memory access" … CPU time < elapsed time Partage de la machine Grand nombre d'I/O Largeur de bande requise > largeur de bande de la machine Pagination et/ou swap important … Un system_time disproportionné peut indique un grand nombre de "page faults", misaligned memory access, floating_point exceptions, exceptions conditions… Le temps passé à explorer un disque, rembobiner une bande, attendre un caractère au terminal n'est pas compté dans le CPU time car il laisse libre le processeur d'exécuter d'autres opérations. Elapsed time st le temps passé devant le terminal du début à la fin de l'exécution du programme. L'elapsed time peut être plus grand que le CPU time dans le cas d'un partage de la machine, grand nombre d'I/O, l'application demande une largeur de bande plus importante que ce qui est disponible, le programme swap ou pagine. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
51
Fonction TIME (CSH ou TCSH)
%time program 14.9u 1.4s 0:19 83% K 27+86io 47pf+0w Nombre de swaps Fautes de pages Nommbre de blocs en sortie Nombre de blocs en entrée Quantité moyenne de mémoire réelle non-partagée utilisée Built-in csh time function: Pourcentage d'utilisation: rapport entre l'elapsed time et le CPU time Average real memory utilization:en Kb shared memory space: quantité moyenne de mémoire occupée par le code Unshared memory space:espace mémoire réel moyen occupé par les données ( variables locales, statiques, externes pour , common en fortran). Real: si on alloue un gros tableau et qu'on utilise qu'une petite partie de ce tableau, seule cette partie sera comptabilisée. Moyen: si une partie de programme utilise sur 1/10 ème de temps 100Mb et le reste du programme utilise 1Kb, time affichera une valeur moyenne de ~10Mb, ce qui n'est pas une image réelle des besoins mémoire. Bloc I/O: décrit l'usage des disques, des bandes ou d'autres périphériques. Les opérations d'I/O à l'écran ne sont pas comptabilisées. Un grand nombre d'I/O peut expliquer une utilisation CPU plus faible que prévue. Pages faults et swap: D'autres programmes peuvent partager le même espace. Même dans une situation optimale, on a des pages faults. Il y a des techniques pour minimiser ces pages faults. Quantité moyenne de mémoire partagée (Kb) Pourcentage d'utilisation Elapsed time Temps system pris par le process Temps utilisateur du process 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
52
Fonctions explicites de mesure de temps
Appel explicite de sous-programmes à l'intérieur du code Fonction system_clock() Procédures de la norme Fortran90/95 (~10ms) cpu_time() date_and_time() Fonction etime (non standard): temps système, utilisateur et total Hors standard : fonctions constructeurs Fonction etime: actual CPU_time for the process Real*4 etime, actual, tarray(2) External etime Actual=etime(tarray) Tarray(1): user_time Tarray(2) : system_time Etime, dtime : somme des deux, elapsed time Fonction dtime: CPU temps depuis le dernier appel de dtime 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
53
Fonctions explicites de mesure de temps
Procédure system_clock real :: time Integer :: debut, fin, vitesse call system_clock(count=debut,count_rate=rate) … call system_clock(count=fin) time=float(fin-debut)/rate Fonction etime real :: actual, etime, tarray(2) actual=etime(tarray) Avec tarray(1) : temps utilisateur tarray(2) : temps du system etime : temps total System_clock (count, rate, count-max) Count : nombre de cycles Rate : nombre de cycles par seconde Count_max : nombre maximum de cycles à partir duquel count est remis à zéro 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
54
Fonction dans la norme Fortran90/95
Procédure cpu_time real :: time_debut, time_fin call cpu_time(time_debut) … call cpu_time(time_fin) Print*, "temps = ", time_fin – time_debut, " secondes" Procédure date_and_time : integer :: date_time(8) character (len=12) :: real_clock(3) call date_and_time(real_clock(1), real_clock(2), real_clock(3),& date_time) Voir "Fortran Language Reference Manual" 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
55
CIMENT – MIRAGE Laurence Viry
Outils de profiling Deux types de profiling : PC Sampling : Prof : CPU-TIME Gprof : CPU-TIME associé à un graphe des appels Hiprof : CPU-TIME, graphe des appels, défaut de page,..; Basic-Bloc Counting : prof, pixie Utilisation des Compteur Hardware : uprofile et kprofile Profiling Mémoire Virtuelle Options de compilation de base pour le profiling: -g1 –O2 L'optimisation d'une application est liée à l'efficacité des algorithmes utilisés et des structures de données, réduire la complexité de N-squared à logN, éviter la copie de données, réduire les données traitées…On peut également adapter l'algorithme à l'architecture des données, pour les grands tableaux, decouper en bloc adaptés à la capacité des caches. Tru64 Unix fournit des outils de profiling qui vont permettre d'identifier les parties de code qui sont grosses consommatrices de ressources CPU, et d'intensifier les efforts sur ces parties. Deux types de profiling fournis par le compilateur: PC-Sampling: interruption du programme périodiquement et enregistrement des compteurs Prof : analyse du temps CPU et du nombre d'appels de chaque procédure GPROF et HIPROF: analyse du temps CPU de chaque procédure et des procédure appelées ainsi que la répartion du temps CPU sur les différentes procédures appelantes. Basic-bloc counting: le programme est divisé en blocs. L'outil compte le nombre de fois que chaque bloc est exécuté. Remarques: Pour tous ces outils, les options de compilation conseillées sont "-g1 et –O2" -g1:le minimum d'information de debug nécessaire, -g2 et plus fournit un code non optimal et des informations inutilespour le profiling -O2 : pour éliminer l'inlining qui éliminerait les informations sur les procédures "ilining" Utilisation de compteurs Hardware: uprofile et kprofile 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
56
Trois étapes pour le profiling
Instrumentation du programme Par le compilateur: -p, –pg Par le profiler : hiprof, pixie Exécution du programme instrumenté Fichier de données pour le profiler (mon.out,gmon.out,…) Utilisation du profiler pour l'extraction et la lecture des résultats: prof, gprof, hiprof, pixie 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
57
CIMENT – MIRAGE Laurence Viry
Hiprof (Tru64 Unix) Permet l'utilisation de fréquence d'échantillonnage plus petite et le profiling au niveau de la ligne. Les librairies partagées peuvent être analysées Profiling individuel des threads possible Indépendant des ressources hardware et de l'architecture Génére une perte de performance Ne se retrouve pas sur tous les systèmes UNIX 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
58
PC-Sampling ( prof, gprof,hiprof)
Cpu_time profiling : option –p et profiler prof % f90 –g1 –O2 –p –o prog prog.f % prog => création du fichier mon.out % prof prog mon.out > prof.list (sortie par défaut à l'écran) Cpu-time profiling + graphe des appels Compilateur : option –pg et profiler gprof % f90 –g1 –O2 -pg –o prog prog.f % prog => création du fichier gmon.out % prof prog gmon.out > prof.list (sortie par défaut à l'écran) profiler hiprof (pas d'option particulière): Compiler le programme : f90 –g1 –O2 –o prog prog.f Instrumentation du programme: hiprof prog => prog.hiprof Exécution : ./prog.hiprof ou hiprof –run <options> prog Affichage des résultats : hiprof –run –display <options> prog Prof (-p, prof): Prof échantillonne périodiquement les compteurs lorsque l'application s'exécute. Compiler avec l'option –p . Exécuter => création d'un fichier de profiling "mon.out". Utiliser l'outil prof pour lire les résultats de profiling obtenus. On obtient un tablau contenant les infos suivantes: %time : pourcentage CPU consommée par cette routine Seconds: CPU consommé par cette routine %Cumsec : pourcentage cummulé consommé par cette routine et les précédentes Cumsecs : CPU cummulé consommé par cette routine et les précédentes Calls : nombre d'appels Msec/call : estimation du temps moyen consommé par cette routine Name : nom de la routine Sur Tru64 UNIX : %time, seconds, %Cumsec, Cumsec, Name Gprof (-pg, gprof): instrumentation par le compilateur avec l'option –pg Il est important de savoir qui appel qui dans la liste des routines, obtenir le graph ou l'arbre des appels. Les outils de profiling qui permettent d'extraire ces informations sont gprof. Hiprof : Instrumentation par hiprof Fournit les mêmes informations que gprof mais il est possible d'effectuer l'instrumentation de bibliothèques partagées. Il est également possible de pousser l'analyse au niveau de la ligne de code, d'obtenir les défauts de page. En dehors des considérations de portage du travail de profiling, sur Tru64 Unix, on préferrera hiprof. Par défaut, hiprof utilise l'option –scaled de gprof qui permet une granularité du cycle machine et de la millisecondes lorsque les temps de procédures sont petits 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
59
CIMENT – MIRAGE Laurence Viry
Listing: PC-Sampling Each sample covers 8.00 byte(s) for 4% of seconds %time seconds cum % cum sec procedure (file) square_ (matpower.f) square_mult_ (matpower.f) %time : pourcentage de temps passé dans la routine seconds : temps en secondes passé dans la routine cum % : pourcentage de temps cumulé cum sec : temps cumulé en secondes 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
60
Basic-Bloc Counting (pixie,prof)
Compilation : f90 –g1 –O2 –o prog prog.f Instrumentation: pixie <options> prog Programme instrumenté: prog.pixie Fichier d'adresses des blocs: prog.Addrs Exécution: prog.pixie Crée le fichier compteurs de blocs: prog.Counts Extrait et affiche l'information de profiling prof –pixie prog >prog_pixie.list Réduire les informations fournies -exclude <procédure>, -only <procédure> -quit <n> : troncature du listing après n lignes 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
61
CIMENT – MIRAGE Laurence Viry
PC-SAMPLING + GRAPH 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
62
CIMENT – MIRAGE Laurence Viry
PC-SAMPLING + GRAPH 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
63
Optimisation par FEEDBACK
Optimisation en deux compilations successives Cinq Etapes: Compilation avec –gen_feedback (pas d'optimisation): f90 –gen_feedback –o prog prog.f Instrumentation: pixie prog => prog.pixie, prog.Addrs Exécution: prog.pixie => prog.Counts Affichage : prof –pixie –feedback prog.feedback prog Recompilation et optimisation du compilateur f90 –O5 –fast –arch host –feedback prog.feedback –o prog prog.f 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
64
CIMENT – MIRAGE Laurence Viry
Mémoire virtuelle Utilisation de la zone de swap Mémoire requise > mémoire physique de la machine Partage des ressources entre plusieurs programme Profiling Comparer la mémoire requise à la mémoire physique Commande size : text, data, bss Option du compilateur sur Tru64 Unix: -V Ne tient pas compte de la pile et du tas Page faults: vmstat ( Berkeley S) et sar (System 5) Condition de swap: La mémoire virtuelle peut, comme les caches misses, avoir un impact sur les performances d’un programme, soit: Parce que la taille mémoire requise par le programme est supérieur à la taille physique de la mémoire de la machine, Partage des ressources de la machine entre plusieurs programme Lorsqu’il n’y a plus suffisamment de mémoire disponible, le système sort les pages vers la zone de swap => accès disque pénalisant Pour analyser l’activité de swapping d’un système, on peut utiliser la commande : vmstat Pour estimer la mémoire requise d’un programme: size <programme> text: code exécutable après compilation et édition de liens data: données statiques initialisées bbs (block started by symbol): données statiques non initialisées en particulier les common La pile et le tas sont des zones d’allocations dynamiques dans le sens ou leur taille n’est pas connue à priori mais fixée à l’exécution. Les variables locales statiques sont allouées dans les zones data ou bss Page faults : vmstat 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
65
Page faults Global : vmstat 5 Virtual Memory Statistics: (pagesize = 8192) procs memory pages intr cpu r w u act free wire fault cow zero react pin pout in sy cs us sy id K 138K 14K 2M 193K 2M K K 138K 14K K 138K 14K K 138K 14K Par programme / procédure: Profiler hiprof hiprof –run –display –faults matpower 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
66
CIMENT – MIRAGE Laurence Viry
Compteurs Hardware Petits registres comptabilisant les occurrences d’événements associés à des fonctions du processeur Instructions load/store Opérations Floating Point Nombre de cycles d’attente d’accès mémoire Cache misses, TLB misses,… … Fournies des informations utiles à l’explication des manques de performance de certaines parties de codes Le suivi de ces événements permet d’affiner l’adaptation du code à l’architecture cible 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
67
Compteur Hardware sur EV67 et EV7
Deux registres de compteur de performances pour compter les événements hardware 1 à 16 événements hardware par compteur 2 événements: comptage exacte plus de 2 événements: multiplexage par l’OS sur les 2 compteurs, estimation statistique l’overflow d’un compteur provoque un “hardware trap” Dépend du type de processeur – inopérant sur EV6 Profiler uprofile 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
68
CIMENT – MIRAGE Laurence Viry
Pourquoi PAPI? Les compteurs Hardware existent sur la plupart des processeurs Les mesures de performances associées à ces compteurs varient suivant les processeurs Ily a très peu d’API permettant de les utiliser et elles sont souvent peu documentées instables et parfois inutilisables 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
69
CIMENT – MIRAGE Laurence Viry
But de PAPI Fournir une API portable, simple à utiliser pour accéder aux compteurs hardware sur la majorité des plate-formes HPC Définir des métriques de performances communes à un grand nombre de plate-formes fournissant des informations utiles à l’optimisation de codes Encourager les vendeurs à standardiser les interfaces et la sémantiques des compteurs hardware 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
70
Laisser faire le compilateur
Idéallement, le compilateur optimise automatiquement le code. Il n’a pas toujours assez d’informations (taille des données connue au run-time,…) excessive cache performance Optimisations principales Utilisation du parallélisme d’instructions (pipelining) Software pipelining Inlining Analyse Interprocédurale Optimisation de boucles Idéallement, c’est le compilateur qui effectue automatiquement les optimisations. Mais le compilateur n’a pas toujours les informations suffisantes. Par exemple, si le programme lit des données sur un fichier externe, la taille du fichier n’est pas connue a la compilation. La meilleure performance est optenuee lorsque l’utilistion du cache est optimisée, ce qui ne peut être fait par le compilateur. La plupart des compilateurs sont limités pour les optimisations du cache. Les transformations effectuées sont faites sur des petites parties de code., typiquement les boucles. Mais malhereusement, la plupart des jeux de données ne tiennent pas dans le cache. MIPSpro7.x effectue parfois des optimisations intempestives. Si on demaande le maximum doptimisation, il optimise l’utilisation du cache pour des données qui ne tiennent pas dans le cahe. On pourra observer des baisses de performances dans le cas de données qui tiennent dans le cache ou pour dans le cas d’une optimisation manuelle de l’utilisation de ce cahe. Trois types d’optimisation sont effectuées, elles ne sont pas réellement indépendantes les unes des autres. Loop optimization peut aider le software pipelining et l’analyse interprocédurale peut aide l’optimisation des boucles imbriquées. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
71
Options de base: On, n=0,…5 (Tru64 Unix)
Plus n grand: Plus l’optimisation est “sophistiquée” Plus le temps de compilation est important Plus la taille du code peut devenir grande Options de base On, n=1,…5 Optimisations locales: -O1 et plus Optimisation globale : -O2 et plus Optimisation globales supplémentaires: -O3 Analyse interprocédurale: -O4 (par défaut) Transformation de boucles et software pipelining: -O5 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
72
Autres options d’optimisation (Tru64 Unix)
Alignement des données dans les commons et les structure : -align <mot-clé> ou –fast Compromis précision rapidité: -math_library fast ou accurate Contrôler l’inlining : -inline <mot-clé> (speed, size,manual…) Contrôler l’unrolling : -unroll num ou –O3 et plus Indiquer au compilateur la machine cible : -arch host ou –arch ev6 , –fast => -arch host Contrôle du Software Pipelining : -O5 ou –pipeline –tune <cible> Permettre toutes les transformations mathématiques valides, ne respecte pas la sémantique (IEEE 754 binary floating point arithmetic) -fp_reorder ou -fast 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
73
Directives #pragma optimize (Tru64 Unix)
Permet de localiser l’optimisation du compilateur Avec le compilateur C Options de la directive #pragma optimize <setting> level= 0,…5 => #pragma optimize level =5 unroll=n => #pragma optimize unroll =5 .. #pragma optimize save #pragma optimize restore Voir Programmer’s Guide 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
74
Software Pipelining (Tru64 Unix)
Le compilateur ne fait pas de Software Pipelining par défaut = > augmente le temps de compilation -pipeline ou –O5 (-pipeline + -transform_loops) Performant sur les boucles vectorisables Moins performant sur les boucles: de grande taille contenant des récurrences N’est pas effectué sur les boucles: contenant des appels de fonction contenant des instructions goto 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
75
Automatique prefetching
Options du compilateur Tru64 Unix: Software pipelining -pipeline, -O5 => software pipelining Pas de directives #pragmas Niveaux de prefetching plus ou moins “agressif” ( IRIX – SGI) de façon conservative pour les grosses structures de données pour une taille des données inconnue Deux niveaux de prefetching (pas sur Tru64 Unix) niveau 2: mémoire principale vers le cache secondaire niveau 1: cache secondaire vers le cache primaire Les cas ou les données tiennent dans L1 sont rares. Plus souvent, elles tiennent dans L2, dans ce cas, il peut être utile de désactiver le “prefetch” à partir de la mémoire principale et d ’effectuer un pseudo-prefetching de L2 vers L1. Cela peut être effectuer par l ’option -LNO:prefetch_level2=off Par défaut LNO “prefetch” deux lignes de cache. Si ça n ’est pas suffisant pour recouvrir la latence de l ’accès aux données, on peut indiquer au compilateur un plus grand nombre de lignes de cache. A ces options, correspondent des directives qui ne seront apliquées que sur une partie du code et qui seront prioritaires. Pour désactiver les directives dans le code et appliquer les options, on peut utiliser l ’option -LNO:prefetch_manual=on-off 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
76
Contrôle de l’Inlining
Compilateur: -inline <mot-clé> -inline manual : uniquement les fonctions (-O2, -O3) -inline size : en fonction de la taille du code (-O1 et plus) -inline speed : quelque soit la taille et le nombre d’appels (-O4 et –O5) -inline all : toutes les fonctions et les routines si c’est possible -inline none: supprime l’inlining des sous-programmes (-O3 et moins) Compromis entre : La taille du code La fréquence des appels Directive #pragma inline (id,…) ou #pragma noinline(id,…) en C et C++ L’inlining d’une fonction permet de suppimer l’overhead du à l’appel et au compilateur d’effectuer des optimisations supplémentaires. La fonction inlinée devra être dans le même module que le code appelant sauf si vous utilisez l’option –ifo qui permet l’inlinig à travers les modules. Avec les options du compilateur –inline size, -inline speed, -noinline, -inline all, les fonctions sont “inlinées” en fonction de l’heuristique du compilateur. Avec la directive #pragmas, l’inlining est effectuée quelque soit la taille de la fonction ou de la routine et le nombre d’appels. Dans tous les cas, si une demande d’inlining est faite, des tests de faisabilité seront faits (cohérence des arguments effectifs et formels,…) -INLINE all : inlining de toutes les toutes les procédures lorsque c’est possible Manual : uniquement les fonctions (-O2 et –O3) None : supprime l’inlining des sous-programmes (-O3 et moins) Size : inlining avec un contrôle de la taille de l’exécutable (-O1 et plus) Speed : inlining si ca augmente les performances même si ca augmente la taille de l’exécutable. (-O4 et –O5) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
77
IEEE 754 binary floating point arithmetic
Exemple de transformation non conforme avec IEEE 754 do i=1,n tmp=1/c b(i)=a(i)/c par do i=1,n enddo b(i)=a(i)*tmp enddo L’ordre des opérations peut provoquer des résultats numériques différents (arrondis, overflows…) L’utilisation des ressources hardware impose parfois de modifier l’ordre des opérations (pipelining…) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
78
Rappel: Transformation de boucles
Les différents types de transformation de boucles loop unrolling Loop interchange Padding Loop Fusion or Fission Cache blocking Prefetching La connaissances des techniques permet d ’aider le travail du compilateur 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
79
Transformations de boucles (Tru64 Unix)
Effectuées par le compilateur avec les options : -transform_loops -O5 Optimisation de l’utilisation des caches, de la gestion des instructions Son action est suffisante pour la plupart des programmes Optimisation du compilateur inhibée par Boucles sans compteur Appel de sous-programmes ou de fonctions sans inlining Condition de sortie non standard Aliasing (pointeurs) Optimisation de l ’utilisation des caches, de la gestion des instructions par des transformations sur les boucles outer loop unrolling Loop interchange Padding Loop Fusion or Fission Cache blocking Prefetching Son action est suffisante pour la plupart des programmes La connaissances des techniques permet d ’aider le travail du compilateur Il peut être préjudiciable de laisser faire le compilateur -pipeline –O4 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
80
CIMENT – MIRAGE Laurence Viry
Optimisation du Cache Transformation de boucles: -O5 ou -transform_loops Concentrée sur les boucles imbriquées et peut bénéficier de l’analyse interprocédurale: -O3 et -transform_loops résoud de nombreux problèmes de cache, ne corrige pas une mauvaise conception du code désactive les transformations de boucles peut parfois augmenter les performances –notransform_loops 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
81
Obstacles à la performance
Ce qui contribue à l’overhead Appel à une routine Référence indirecte à la mémoire Tests à l’intérieur d’une boucle Conversion de type Variables non utilisées Tests trop verbeux Ce qui restreint la capacité d’optimiser du compilateur Référence indirecte à une procédure Pointeurs ambigus 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
82
Appels de sous-programmes
Réduit la capacité du compilateur à optimiser Pas de software pipelining Gestion des variables externes et des commons lourde Compromis entre: La taille de la routine Le nombre d’appels Éviter un nombre faible d’appels à une petite routine Modularité indispensable pour le développement de gros codes compactes et compréhensibles 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
83
Appel de procédures (suite)
Préférer DO I=1,N A(I)=A(I)+B(I)*C ENDDO À CALL MADD(A(I),B(I),C) SUBROUTINE MADD(A,B,C) A=A+B*C RETURN END Eviter COMMON /UTIL/K DO K=1,1000 IF (K .EQ. 1) CALL AUX ENDDO K variable de common: le compilateur stocke en mémoire et recharge K à chaque itération Conserver k comme variable locale 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
84
CIMENT – MIRAGE Laurence Viry
Macros Principalement utilisées en C: concerne surtout les petites fonctions #define average(x,y)((x+y)/2) main () { float q=100,p=500; float a; a=average(p,q); …} 2 étapes: Pré-compilation par cpp: remplace les macros par leur code Compilation C ou Fortran Le compilateur C effectue les deux étapes automatiqument, certains compilateurs fortran également. 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
85
CIMENT – MIRAGE Laurence Viry
INLINING Concernent les fonctions de taille plus importante que les macros Selon le compilateur, plusieurs méthodes Spécifier les procédures concernées à la compilation Mettre dans le code des directives Laisser le compilateur faire le travail automatiquement Compromis entre la taille du code et les performances (réutilisation optimale du cache instructions) 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
86
CIMENT – MIRAGE Laurence Viry
Branchement Méthode: Réduire les branchements si c’est possible Les sortir de certains blocs (boucles,…) Branchement à l’intérieur d’une boucle Invariant conditionnel dans la boucle Condition sur l’index de boucle=> restructuration du code Instruction conditionnelle indépendante => unrolling, exécution en parallèle Instructions conditionnelles dépendantes=> conservation de l’ordre Réductions => Laisser faire le compilateur Condition de transfert de contrôle 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
87
Branchement à l’intérieur d’une boucle
parameter (small=1.E-20) do i=1,n if (abs(a(i)) .ge. small) then b(i)=b(i)+a(i)*c endif enddo => Éliminer le test pour permettre le software pipelining 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
88
Invariant conditionnel dans la boucle
DO I=1,K IF (N .EQ. 0) THEN A(I)=A(I)+B(I)*C ELSE A(I)=0. ENDIF ENDDO Préférer: IF (N .EQ. 0) THEN DO I=1,K A(I)=A(I)+B(I)*C ENDDO ELSE A(I)=0. ENDIF 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
89
Expression conditionnelle indépendante
DO I=1,N DO J=1,N IF (B(J,I) .GT. 1.0) A(J,I)=A(J,I)+B(J,I)*C ENDDO Indépendance des itérations => Unrolling ou exécution en parallèle possible 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
90
Condition de transfert de contrôle
DO I=1,N DO J=1,N IF (B(I,J) .EQ. 0) THEN PRINT*,I,J STOP ENDIF A(I,J)=A(I,J)/B(I,J) ENDDO Utiliser les procédés de récupération d’erreur fournit par le standard IEEE – option à la compilation 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
91
CIMENT – MIRAGE Laurence Viry
Autres obstacles Conversion de type Eviter les expressions de type caractère dans les expressions conditionnelles Effectuer ses propres éliminations de sous-expressions Le compilateur ne les reconnaît pas toutes Ne gère pas celles qui contiennent des appels de fonctions Effectuer ses propres déplacements de code Partie invariante dans une boucle Références multiples à un même élément de tableau On a pas toujours intérêt à le remplacer par une variable scalaire 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
92
Elimination de sous-expressions
x=r*sin(a)*cos(b) y=r*sin(a)*sin(b) z=r*cos(a) devient temp=r*sin(a) x=temp*cos(b) y=temp*sin(b) Le compilateur ne fait pas l’élimination d’expression avec appel de fonction 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
93
CIMENT – MIRAGE Laurence Viry
Déplacement de code DO I=1,N A(I)=A(I)/SQRT(X*X+Y*Y) ENDDO Devient TEMP=1./SQRT(X*X+Y*Y) A(I)=A(I)*TEMP 14 Janvier 2002 CIMENT – MIRAGE Laurence Viry
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.