Traduction binaire dynamique de l extension SIMD Néon de l ARMv7 dans Qemu



Documents pareils
Machines virtuelles. Brique ASC. Samuel Tardieu Samuel Tardieu (ENST) Machines virtuelles 1 / 40

Programmation assembleur : aperçu

Rappels d architecture

Architecture des ordinateurs

Cours 1 : La compilation

DU BINAIRE AU MICROPROCESSEUR - D ANGELIS CIRCUITS CONFIGURABLES NOTION DE PROGRAMMATION

IV- Comment fonctionne un ordinateur?

MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C

Conception de circuits numériques et architecture des ordinateurs

Arithmétique binaire. Chapitre. 5.1 Notions Bit Mot

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Compilation (INF 564)

1 Architecture du cœur ARM Cortex M3. Le cœur ARM Cortex M3 sera présenté en classe à partir des éléments suivants :

Exécution des instructions machine

Représentation des Nombres

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Représentation d un entier en base b

Programmation C. Apprendre à développer des programmes simples dans le langage C

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Département informatique de l université d Angers


Programmer en JAVA. par Tama

Assembleur. Faculté I&C, André Maurer, Claude Petitpierre

Thème 3 Conception et vérification d architectures de systèmes sur puce

ASR1 TD7 : Un microprocesseur RISC 16 bits

Microprocesseur + Logiciel

Introduction à la Programmation Parallèle: MPI

Chapitre VI- La validation de la composition.

Concept de machine virtuelle

Génération de code binaire pour application multimedia : une approche au vol

Partie 7 : Gestion de la mémoire

Traduction des Langages : Le Compilateur Micro Java

La mémoire. Un ordinateur. L'octet. Le bit

as Architecture des Systèmes d Information

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Projet d informatique M1BI : Compression et décompression de texte. 1 Généralités sur la compression/décompression de texte

Recompilation dynamique de codes binaires hostiles

Architecture matérielle des systèmes informatiques

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Jeu d instructions NIOS II

Cours Informatique 1. Monsieur SADOUNI Salheddine

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Comment reproduire les résultats de l article : POP-Java : Parallélisme et distribution orienté objet

UE Programmation Impérative Licence 2ème Année

Assembleur i8086. Philippe Preux IUT Informatique du Littoral. Année universitaire 95 96

Conventions d écriture et outils de mise au point

SSTIC Désobfuscation automatique de binaires. Alexandre Gazet. Yoann Guillot. Et autres idyles bucoliques...

Cours d initiation à la programmation en C++ Johann Cuenin

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Plan du cours. Historique du langage Nouveautés de Java 7

L utilisation d un réseau de neurones pour optimiser la gestion d un firewall

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

SRS DAY: Problématique liée à la virtualisation

Chapitre V : La gestion de la mémoire. Hiérarchie de mémoires Objectifs Méthodes d'allocation Simulation de mémoire virtuelle Le mapping

Ordinateurs, Structure et Applications

Linux embarqué: une alternative à Windows CE?

LA VIRTUALISATION. Etude de la virtualisation, ses concepts et ses apports dans les infrastructures informatiques. 18/01/2010.

Partie 1. Professeur : Haouati Abdelali. CPGE Lycée Omar Ibn Lkhattab - Meknès haouaticpge@gmail.com

Initiation à la sécurité

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

Algorithme. Table des matières

Cours 1 : Qu est-ce que la programmation?

Chapitre I Notions de base et outils de travail

INTERSYSTEMS CACHÉ COMME ALTERNATIVE AUX BASES DE DONNÉES RÉSIDENTES EN MÉMOIRE

Machines virtuelles Cours 1 : Introduction

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Ne laissez pas le stockage cloud pénaliser votre retour sur investissement

Langage C. Patrick Corde. 22 juin Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin / 289

Reproductibilité des expériences de l article "Analyse et réduction du chemin critique dans l exécution d une application"

Premiers Pas en Programmation Objet : les Classes et les Objets

Solution A La Gestion Des Objets Java Pour Des Systèmes Embarqués

Mesure de performances. [Architecture des ordinateurs, Hennessy & Patterson, 1996]

6 - Le système de gestion de fichiers F. Boyer, UJF-Laboratoire Lig, Fabienne.Boyer@imag.fr

Atelier C TIA Portal CTIA04 : Programmation des automates S7-300 Opérations numériques

Présentation d HyperV

Résumé Génération de code Le code intermédiaire

GenDbg : un débogueur générique. Didier Eymery Jean-Marie Borello Jean-Marie Fraygefond Odile Eymery Philippe Bion

Conversion d un entier. Méthode par soustraction

Architecture des ordinateurs TD1 - Portes logiques et premiers circuits

Informatique Générale

Tp 1 correction. Structures de données (IF2)

Grandes lignes ASTRÉE. Logiciels critiques. Outils de certification classiques. Inspection manuelle. Definition. Test

Architecture de l ordinateur

Logiciel de base. Première année ENSIMAG

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

Éléments de programmation et introduction à Java

Module : Virtualisation à l aide du rôle Hyper-V

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

machine cible machine hôte architecture cible différente de la machine hôte

Utilisation d objets : String et ArrayList

Jade. Projet Intelligence Artificielle «Devine à quoi je pense»

Introduction à l algorithmique et à la programmation M1102 CM n 3

Installation et prise en main

RTDS G3. Emmanuel Gaudin

Retrouver de vieux programmes et jouer sur VirtualBox

Introduction à l informatique temps réel Pierre-Yves Duval (cppm)

ISO/CEI Technologies de l information Gestion des actifs logiciels. Partie 1: Procédés et évaluation progressive de la conformité

Introduction au langage C

Transcription:

Travaux d études et de recherches Traduction binaire dynamique de l extension SIMD Néon de l ARMv7 dans Qemu Étudiant : Luc Michel Encadrants : Frédéric Pétrot Nicolas Fournel 23 mai 2010

TABLE DES MATIÈRES Table des matières Introduction 2 1 Fonctionnement interne de Qemu 3 1.1 La représentation intermédiaire de Qemu : la TCG................. 3 1.2 Méthode actuelle de traduction des instructions Neon............... 3 1.2.1 Présentation des helpers............................ 3 1.2.2 Surcoûts induits par les helpers........................ 4 2 Amélioration de la traduction des instructions Neon 4 2.1 Première méthode : conversion en micro-opérations TCG classiques........ 6 2.1.1 Présentation de la méthode.......................... 6 2.1.2 Exemple de la traduction du vadd.i16 à l aide de micro-opérations.... 6 2.1.3 Réflexions sur la méthode........................... 7 2.2 Deuxième méthode : ajout de micro-opérations SIMD au sein de la TCG..... 7 2.2.1 Présentation de la méthode.......................... 7 2.2.2 Exemple de traduction du vadd.i16 vers SSE................ 8 2.2.3 Réflexions sur la méthode........................... 11 3 Tests et résultats 11 Conclusion 12 Annexes 13 Références 14 1

TABLE DES MATIÈRES Introduction Contexte du TER Ce TER s est déroulé dans l équipe SLS (System Level Synthesis) du laboratoire TIMA, sous la direction de Frédéric Pétrot et Nicolas Fournel. Il s inscrit dans un travail de recherche autour de la simulation de systèmes. Avec l augmentation de la part de logiciel dans les systèmes embarqués récents et à venir, la légitimité de l utilisation de modèle de simulation au niveau transactionnel n est plus à démontrer. L apparition et le développement de systèmes embarqués multi-processeurs met en avant une des faiblesses de ce type de simulation, à savoir la lourdeur du ou des simulateurs d architectures utilisés pour la simulations des processeurs. En effet, la multiplication du nombre de processeurs alourdit d autant l utilisation de ces modèles de simulation. Les solutions proposées dans l équipe SLS utilisent principalement deux technologies distinctes pour améliorer ces performances. La première est appelée traduction binaire (binary translation) et consiste en la traduction des instructions de l architecture cible (ARM,...) en instructions de l architecture simulant (architecture dite hôte). Une fois cette traduction effectuée, on exécute la version traduite. Cette technologie est largement utilisées en virtualisation (ex : Qemu[1]) La seconde technique est nommée simulation native. Cette technique consiste en la compilation du logiciel embarqué pour l architecture hôte. Elle impose certains traitements pour permettre l interaction avec la simulation du reste de la plate-forme. Présentation de la problématique, introduction à Qemu Le but de ce TER était de travailler sur cette première méthode, la traduction binaire. La traduction binaire consiste à traduire le code binaire (le code exécutable par un processeur) d une architecture cible, vers celui d une autre architecture, dite h^ote. L architecture cible concernée par ce TER est l architecture ARM. En effet, il est question de travailler sur la manière dont Qemu traduit un sous-ensemble d instructions de cette architecture. Qemu est un logiciel open-source permettant d émuler ou de virtualiser une machine dite machine cible sur une autre machine dite machine hôte. Ces deux machines peuvent être d architectures différentes. Qemu utilise le principe de la traduction binaire dynamique, qui consiste à traduire, à la volée, le code binaire de la machine cible, vers celui de la machine hôte. Le sous-ensemble d instructions de l architecture ARM par lequel ce TER est concerné est celui des instructions Advanced SIMD, dont l implémentation est appelée NEON Technology TM. Dans la suite de ce document, nous ferons référence aux instructions Neon, pour les désigner. Les instructions Neon sont des instructions dites SIMD (Single Instruction, Multiple Data). Ce type d instructions, présent dans la majorité des architectures d aujourd hui, a la particularité de travailler non pas sur un ensemble de données mais sur un ensemble de vecteurs de données. Il est par exemple possible d effectuer l addition de deux vecteurs de quatre entiers chacun, en une opération. Ce type d instructions peut être très bénéfique en terme de performance dans certaines applications. L exemple le plus courant est celui des applications multimédia, par exemple lors de la compression ou décompression audio ou vidéo. Ce genre d instructions s adapte très bien aux algorithmes utilisés dans ces cas, de par la nature régulière de ceux-ci. Actuellement, les instructions Neon sont correctement traduites par Qemu, mais d une manière pénalisante en terme de performance. En effet, nous verrons par la suite qu une telle instruction se traduit sur la machine hôte par : Un appel de fonction, 2

1 FONCTIONNEMENT INTERNE DE QEMU Une traduction totalement SISD (Single Instruction Single Data), c est à dire une traduction à base d instructions assembleurs classiques. Le but de ce TER était donc de trouver une ou plusieurs solutions pour améliorer cette traduction, puis d en implémenter une partie afin de pouvoir constater ou non le gain de performance. 1 Fonctionnement interne de Qemu 1.1 La représentation intermédiaire de Qemu : la TCG Lorsque Qemu traduit le code binaire, il ne le fait pas directement de la machine cible vers la machine hôte. Il passe par une représentation intermédiaire appelée la TCG (Tiny Code Generator). Cette représentation intermédiaire est composée d instructions simples appelées micro-opérations, du type de celles des architectures classique (load, store, mov, add, sub, and, or,... ). La traduction, schématisée par la figure 1, se fait donc en deux temps : 1. Pour chaque instruction de l architecture cible, un décodage est effectué, et une première traduction est faite vers la représentation intermédiaire. 2. Une fois cette première traduction effectuée pour un sous-ensemble du code, une deuxième traduction est faite, cette fois-ci de la TCG vers l architecture hôte. Ce sous ensemble est appelé un basic block. Il est délimité par une instruction de type saut dans la TCG. Ainsi, lorsqu un saut vers une adresse ou un retour de fonction est effectué, Qemu considère la fin du basic block, et le début d un autre. Le code ainsi généré est placé dans un buffer, puis est executé par la machine hôte. Ce buffer contient non pas un mais plusieurs basic blocks, dont Qemu garde une trace. Ainsi, si le même basic block doit être exécuté plusieurs fois (plusieurs appels à la même fonction, itérations d une boucle,... ), le code présent dans le buffer est réutilisé, une seconde traduction n est donc pas nécessaire. Cependant, ce buffer est de taille limité. Ainsi, lorsqu il est plein, la politique de Qemu est de le vider complètement pour laisser place à de nouveaux basic blocks. Cette technique de représentation intermédiaire permet à Qemu de pouvoir rendre indépendant l émulation des machines cibles, et le support des machines hôtes. Ainsi, lors de l implémentation d une nouvelle architecture hôte, celle-ci peut directement bénéficier de toutes les architectures cibles déjà émulées, et inversement. De plus, grâce à ce buffer, les performances générales sont très bonnes puisque le code traduit à beaucoup de chances d être réutilisé. 1.2 Méthode actuelle de traduction des instructions Neon 1.2.1 Présentation des helpers Une autre technique utilisée dans la TCG pour traduire le code de l architecture cible est l utilisation des helpers. Cette technique consiste, non pas à traduire en représentation intermédiaire, mais à écrire une fonction en code C réalisant l opération voulue. Cette fonction sera compilée au même moment que Qemu. La TCG génère ensuite dans le code hôte un appel vers cette fonction pour exécuter l opération. C est de cette manière que sont traduites la plupart des instructions Neon. Cela est principalement dû à un héritage des anciennes versions de Qemu. La figure 2 montre l utilisation d un helper pour traduire l instruction vadd.i16 1. Cette instruction prend en paramètre trois registres q0, q1 et q2. Ceux sont des registres Neon 128 bits que l instruction considère comme étant des vecteurs de huit entiers de 16 bits. Cette instruction additionne les éléments des vecteurs q1 et q2, et place le résultat dans q0. 1. le fonctionnement de cette instruction est décrit figure 3 3

2 AMÉLIORATION DE LA TRADUCTION DES INSTRUCTIONS NEON 0x00000110: mov sp, r0 0x00000114: sub r0, r0, #32768 0x00000118: msr CPSR_c, #209 Code de la machine cible ARM movi_i32 tmp9,$0xdf movi_i32 tmp10,$cpsr_write call tmp10,$0x0,$0,tmp8,tmp9 movi_i32 pc,$0x11c exit_tb $0x0 Représentation intermédiaire TCG 0xb4f270ac: mov $0xd1,%ecx 0xb4f270b1: mov %ecx,(%esp) 0xb4f270b4: mov $0xdf,%ecx 0xb4f270b9: mov %ecx,0x4(%esp) 0xb4f270bd: mov %eax,0x34(%ebp) 0xb4f270c0: mov %edx,0x0(%ebp) 0xb4f270c3: call 0x821fa25 0xb4f270c8: mov $0x11c,%eax 0xb4f270cd: mov %eax,0x3c(%ebp) 0xb4f270d0: xor %eax,%eax 0xb4f270d2: jmp 0x84ed448 Code généré pour la machine hôte x86 Figure 1 Fonctionnement de la traduction dynamique 1.2.2 Surcoûts induits par les helpers Cette technique est coûteuse, car pour une unique instruction de la machine cible, un appel de fonction est effectué. Cela implique en plus de faire des arrangements autour de cet appel pour faire correspondre les paramètres et valeurs de retour. De plus, le helper prend en paramètre et renvoie des entiers sur 32 bits, et non sur 128 bits. En effet, cette traduction est totalement SISD, d où ces valeurs sur 32 bits. Pour traduire la totalité du vecteur, la fonction est appelée quatre fois, avec une partie différente du vecteur à chaque appel. De plus, des opérations supplémentaires sont nécessaires pour rendre indépendant l addition des différents entiers sur 16 bits. C est pourquoi le helper commence par isoler les bits de poids fort de ceux-ci avant de faire l addition, et les réinjecte ensuite si nécessaire. Toute cette mécanique induit un sur-coût non négligeable par rapport à l unique instruction vadd.i16 présente dans le code de la machine cible. 2 Amélioration de la traduction des instructions Neon Au court du TER, plusieurs réflexions ont été portées pour déterminer comment améliorer les performances de cette traduction. Principalement deux méthodes sont ressorties : Une première méthode consistant à remplacer la traduction à l aide d helpers par une traduction en représentation intermédiaire classique. Cette technique à pour effet de supprimer les appels de fonctions, ainsi que les passages et récupération de paramètres. En revanche, elle ne résout pas le problème du surcoût dû aux instructions supplémentaires pour la traduction (par exemple l isolation des bits de poids fort dans le cas du vadd.i16). Une deuxième méthode consistant à enrichir la TCG avec de nouvelles micro-opérations 4

2 AMÉLIORATION DE LA TRADUCTION DES INSTRUCTIONS NEON 0x00008584: vld1.32 {d0-d1, [r0] 0x00008588: vld1.32 {d2-d3, [r1] 0x0000858c: vadd.i16 q0, q1, q2 0x00008590: vst1.32 {d0-d1, [r0] Code de la machine cible ARM uint32_t HELPER(neon_add_u16) (uint32_t a, uint32_t b) { uint32_t mask; mask = (a ^ b) & 0x80008000u; a &= ~0x80008000u; b &= ~0x80008000u; return (a + b) ^ mask; Code du Helper ld_i32 tmp8,env,$0x2f8 ld_i32 tmp9,env,$0x308 movi_i32 tmp10,$neon_add_u16 call tmp10,$0x0,$1,tmp8,tmp8,tmp9 st_i32 tmp8,env,$0x2e8 Représentation intermédiaire TCG 0xb56c38b7: cmp 0xb56c38b9: mov 0xb56c38bb: je 0xb56c38bd: mov 0xb56c38c2: call 0xb56c38c7: jmp 0xb56c38c9: add (%edx),%eax %ecx,%eax 0xb56c38c9 $0x1,%edx 0x821ce38 0xb56c38ce 0xc(%edx),%eax Code généré pour la machine hôte x86 Figure 2 Exemple de traduction d une instruction Neon (vadd.i16) à l aide d un helper SIMD, afin de profiter pleinement des capacités de l architecture hôte. En effet, avec cette technique, le résultat de la traduction sur la machine hôte est à même de comporter des instructions SIMD si celle-ci les supporte. Afin de se limiter à un sous-ensemble d instructions Neon, ce TER se concentre sur une partie des sources du logiciel FFmpeg, logiciel libre de traitement audio et video. Celui-ci comporte une partie en assembleur propre à chaque plateforme sur lesquelles il est porté, qui optimise une partie des traitements. Pour l architecture ARM, certaines opérations sont optimisées à l aide d instructions Neon. Voici le sous-ensemble considéré : Instruction vadd vaddw vqmovun vrshr vshr vsub vswp vtrn Description Addition de vecteurs. Addition de vecteurs de tailles différentes. Déplace le contenu d un registre dans un autre de taille inférieur. Le résultat est converti en entier non signé. Effectue une rotation vers la droite sur les éléments d un vecteur. Effectue un décalage vers la droite sur les éléments d un vecteur. Soustraction de vecteurs. Échange le contenu de deux registres. Considère deux registres comme les lignes d une matrice 2 2 et en effectue la transposée. Certaines de ces instructions sont suivies d une information indiquant le type et la largeur des données utilisées. Par exemple, l instruction vadd.i16 travaille sur des vecteurs d entiers de 16 bits, elle ne tient pas compte du typage (signé ou non). vshr.u32 effectue le décalage logique 5

2 AMÉLIORATION DE LA TRADUCTION DES INSTRUCTIONS NEON 128bits 16bits 16bits 16bits 16bits 16bits 16bits 16bits q1 + + + + + + + q2 q0 Figure 3 Fonctionnement de l instruction vadd.i16 vers la droite d entiers sur 32 bits alors que vshr.s32 effectue un décalage arithmétique. La combinaison des instructions et des types de données offre donc beaucoup de possibilités, mais aussi beaucoup de cas à prendre en compte dans Qemu. 2.1 Première méthode : conversion en micro-opérations TCG classiques 2.1.1 Présentation de la méthode Cette première méthode se veut suffisamment simple puisqu il suffit de remplacer le helper par une suite de micro-opérations de la TCG, en gardant le même modèle. Il faut donc traduire le code du helper écrit en C, en micro-opérations TCG. 2.1.2 Exemple de la traduction du vadd.i16 à l aide de micro-opérations Voici un exemple avec l instruction Neon vadd.i16. Listing 1 Code du helper u i n t 3 2 t HELPER( neon add u16 ) ( u i n t 3 2 t a, u i n t 3 2 t b ) { u i n t 3 2 t mask ; mask = ( a ˆ b ) & 0 x80008000u ; a &= 0 x80008000u ; b &= 0 x80008000u ; return ( a + b ) ˆ mask ; 6

2 AMÉLIORATION DE LA TRADUCTION DES INSTRUCTIONS NEON Listing 2 Code générant les micro-opérations static inline int gen neon add u16 (TCGv t0, TCGv t1 ) { TCGv mask = new tmp ( ) ; t c g g e n x o r i 3 2 ( mask, t0, t1 ) ; t c g g e n a n d i i 3 2 ( mask, mask, 0 x80008000u ) ; t c g g e n a n d i i 3 2 ( t0, t0, 0 x80008000u ) ; t c g g e n a n d i i 3 2 ( t1, t1, 0 x80008000u ) ; t c g g e n a d d i 3 2 ( t0, t0, t1 ) ; t c g g e n x o r i 3 2 ( t0, t0, mask ) ; dead tmp ( mask ) ; return 0 ; Le type TCGv représente une valeur qui sera stockée dans un registre de la machine hôte. t0 et t1 sont les opérandes de l instruction vadd.i16, le résultat est stocké dans t0. Les microopérations générées sont similaires aux instruction présentes dans le helper, la même opération d isolation du bit de poids fort est effectuée. 2.1.3 Réflexions sur la méthode Durant les différentes réflexions portées pour construire cette solutions, il a été question de chercher à automatiser la génération du code de traduction, en partant par exemple de la documentation fournie par le constructeur ARM. Dans cette documentation, chaque instruction est décrite de manière formelle dans un pseudo-langage. Une extension possible, si cette méthode s avère performante, serait donc de développer un parser pour ce pseudo-code, qui générerait automatiquement la suite de micro-opération TCG pour chaque instruction. Cela éviterait ainsi un important travail de développement, et limiterait grandement les sources d erreurs. 2.2 Deuxième méthode : ajout de micro-opérations SIMD au sein de la TCG 2.2.1 Présentation de la méthode Cette deuxième approche semble être de meilleur qualité, puisqu elle permet de générer des instructions SIMD sur la machine hôte. En revanche, elle demande un plus gros effort de conception car pour chaque micro-opération SIMD ajoutée dans la TCG, il faut en théorie effectuer la traduction vers toutes les architectures hôtes déjà implémentées dans Qemu. Ce TER se limite néanmoins à la traduction vers l architecture x86, et son jeu d instructions SIMD MMX/SSE[3]. Il faut aussi adapter la TCG pour qu elle puisse travailler sur des données de 128 bits. Il faut enfin ajouter aux architectures hôtes, la liste des registres SIMD disponibles, afin d autoriser l allocateur de registres de la TCG à les utiliser. Dans la version 0.12.0 de Qemu, les micro-opérations de la TCG sont définies dans le fichier tcg/tcg-opc.h. En guise d exemple, voici la définition de la micro-opération add_i32, qui représente l addition classique sur 32 bits. DEF2( add i32, 1, 2, 0, 0) Le premier paramètre est le nom de la micro-opération, les second et troisième sont respectivement le nombre d opérandes out et in, le quatrième représente de nombre d opérandes 7

2 AMÉLIORATION DE LA TRADUCTION DES INSTRUCTIONS NEON immédiates et enfin, le dernier sert à positionner des flags donnant des informations supplémentaires à la TCG 2. Dans cet exemple, la micro-opération additionne deux opérandes in et stocke le résultat dans une opérande out. Environ 35 micro-opérations ont été ajoutées à la TCG de Qemu dans le cadre de ce TER. Afin de les différencier, elles sont toutes préfixer par simd_64_ ou simd_128_, suivant la taille des données qu elles manipulent. Elles sont entourées par des conditions préprocesseur ce qui permet de ne pas les inclure dans Qemu à la compilation si la machine hôte ne supporte pas le SIMD. Bien entendu et afin de rester cohérent, ces conditions apparaissent à d autres endroits dans le code. Notamment, si la compilation est effectuée sans le support du SIMD, la méthode actuelle de traduction du Neon est utilisée. Une fois ces micro-opérations définies, il est possible de rajouter des fonctions inline dans le fichier tcg/tcg-op.h. Ces fonctions sont celles utilisées lors de la traduction machine cible vers TCG. Elles sont préfixées par tcg_gen_ (cf. l exemple de la traduction du vadd.i16 avec la méthode 1). Ce sont elles qui vont effectivement émettre des micro-opérations. Elles peuvent soit directement en émettre une ou plusieurs, soit appeler une autre fonction inline similaire en adaptant les paramètres 3. 2.2.2 Exemple de traduction du vadd.i16 vers SSE Voici l exemple de l ajout de la micro-opération simd_128_add_i16 pour traduite l instruction Neon vadd.i16. Côté TCG Cette première partie décrit les ajouts réalisés dans la TCG. Listing 3 Ajout de la micro-opération dans tcg-opc.h DEF2( simd 128 add i16, 1, 2, 0, 0) Comme pour l addition classique, cette micro-opération prend en paramètre deux opérandes d entrées et une opérande de sortie. 2. Par exemple, le flag TCG_OPF_BB_END informe la TCG que la micro-opération marque la fin d un basic block. 3. Dans le cas d opération prenant en paramètre une opérande immédiate, la fonction inline charge d abord ce paramètre dans un registre avant d appeler la fonction similaire qui ne prend que des registres en paramètre. 8

2 AMÉLIORATION DE LA TRADUCTION DES INSTRUCTIONS NEON Listing 4 Ajout de fonctions inline dans tcg-op.h static inline void tcg gen simd 128 op3 ( int opc, TCGv i128 arg1, TCGv i128 arg2, TCGv i128 arg3 ) { gen opc ptr++ = opc ; gen opparam ptr++ = GET TCGV I128( arg1 ) ; gen opparam ptr++ = GET TCGV I128( arg2 ) ; gen opparam ptr++ = GET TCGV I128( arg3 ) ; static inline void tcg g en s imd 128 add i16 ( TCGv i128 ret, TCGv i128 arg1, TCGv i128 arg2 ) { tcg gen simd 128 op3 ( INDEX op simd 128 add i16, ret, arg1, arg2 ) ; La première fonction est la fonction utilisée dans le cas général d opérations SIMD à trois opérandes. Elle se contente de placer l opération et les paramètres dans leur buffer respectif, buffers que Qemu lira lors de la traduction de la TCG vers la machine hôte. La seconde fonction est celle qui sera appelée pour émettre une opération simd_128_add_i16. Elle appelle la fonction précédente avec les trois opérandes. Le type TCG_i128 a été ajouté à la TCG dans le cadre de ce TER afin que celle-ci supporte des opérandes sur 128 bits. Côté machine ARM cible Décrivons maintenant les ajouts dans la première étape de traduction : la traduction des instructions Neon en micro-opérations TCG. Listing 5 Traitement du vadd.i16 dans le décodage des instructions ARM (targetarm/translate.c) TCGv i128 ret, arg1, arg2 ; r e t = tcg temp new i128 ( ) ; arg1 = neon load simd reg128 ( rn ) ; arg2 = neon load simd reg128 (rm ) ; tcg g en s imd 1 2 8 add i16 ( ret, arg1, arg2 ) ; n e o n s t o r e s i m d r e g 1 2 8 ( rd, r e t ) ; t c g t e m p f r e e i 1 2 8 ( arg1 ) ; t c g t e m p f r e e i 1 2 8 ( arg2 ) ; Ce listing est exécuté lorsqu un vadd.i16 est rencontré dans le code ARM. Il charge les deux registres, appelle la fonction tcg_gen_simd_128_add_i16 créée dans la première étape, puis sauvegarde le résultat dans le registre de destination. Les variables rn, rm et rd sont définies lors du décodage de l instruction. Côté machine x86 hôte Il faut enfin effectuer la traduction de la micro-opération tcg_gen_simd_128_add_i16 sur la machine hôte. 9

2 AMÉLIORATION DE LA TRADUCTION DES INSTRUCTIONS NEON Listing 6 Déclaration de la micro-opération auprès de l architecture hôte (tcg/i386/tcgtarget.c) { INDEX op simd 128 add i16, { "X", "0", "X", Cette ligne est ajoutée dans un tableau contenant toutes les micro-opérations de la TCG. Ce tableau est propre à chaque architecture hôte, car il définit les contraintes liées aux opérandes de la micro-opération. En effet, lors de la traduction des micro-opérations, la TCG gère les registres de la machine hôte. Elle alloue et fournie des registres pour la traduction des micro-opérations. Ici, un "X" signifie que les registres qui vont être associés à la première opérande (opérande de sortie) et à la troisième opérande (deuxième opérande d entrée), seront des registres SIMD SSE de l architecture x86. Le "0" signifie que pour la deuxième opérande, l allocateur de registres doit fournir le même registre pour l opérande numéro 0, c est à dire la première. Cela s explique par le fait que l instruction analogue au vadd.i16 en SSE, comme la majorité des instructions x86, ne prend en paramètre que deux opérandes, la première étant à la fois une des deux opérandes d entrées et l opérande de sortie. Cette instruction analogue est l instruction paddw. Listing 7 Traduction de l opération en instruction SSE (tcg/i386/tcg-target.c) static inline void tcg out modrm simd simd ( TCGContext s, int opc, int r1, int r2 ) { tcg o ut8 ( s, ( opc & 0 x00ff0000u ) >> 1 6 ) ; tcg o ut8 ( s, ( opc & 0 x0000ff00u ) >> 8 ) ; tcg o ut8 ( s, opc & 0 x000000ffu ) ; tcg o ut8 ( s, 0 xc0 ( r1 << 3) r2 ) ; static inline void tcg o ut o p ( TCGContext s, int opc, const TCGArg args, const int c o n s t a r g s ) { switch ( opc ) { [... ] case INDEX op simd 128 add i16 : tcg out modrm simd simd ( s, 0 x00660ffdu, args [0] TCG REG XMM0, args [2] TCG REG XMM0) ; break ; [... ] Finalement, l opération est traduite. La fonction tcg_out_op est appelée par la TCG pour chaque micro-opération à traduire. Seul le cas qui nous intéresse est conservé ici. Le tableau args contient les numéros des registres alloués pour la traduction de l opération, en fonction des contraintes vues plus haut. La fonction tcg_out_modrm_simd_simd prend en paramètre l opcode x86 de l instruction (0x00660ffd). Cet opcode est celui de l instruction paddw[2]. Elle prend aussi en paramètre les deux registres concernés, et enfin, le contexte de la TCG. Cette fonction fait plusieurs appels à la méthode tcg_out_8, qui écrit un octet brut dans le buffer de traduction de l architecture cible. C est le contenu de ce buffer qui sera exécuté. 10

3 TESTS ET RÉSULTATS Voilà qui achève les différentes étapes pour traduire une instruction Neon avec cette deuxième méthode. Théoriquement, cette traduction effectuée pour l architecture hôte x86 devrait être faite pour toutes les autres architectures. 2.2.3 Réflexions sur la méthode Durant les différentes réflexions lors du développement de cette méthode, il a été question de chercher à déterminer l ensemble de micro-opérations SIMD optimal à rajouter à la TCG de Qemu, pour satisfaire au mieux toutes les architectures cibles et hôtes. En effet, la nature des instructions SIMD varient d une architecture à l autre. Par exemple, l instruction Neon vaddw permet l addition de deux vecteurs de tailles différentes. Une conversion est faite en interne pour effectuer l addition. Les instructions SIMD x86 en revanche ne proposent pas ce genre d opérations. Il faut d abord convertir l un des deux vecteurs avant de faire l addition classique. Il y a donc une réflexion à porter pour déterminer le juste milieu dans la TCG, c est à dire ne pas rajouter d instructions SIMD trop spécifiques à une architecture, mais en mettre suffisamment pour pouvoir s en sortir, quitte à faire la traduction d une instruction cible en plusieurs instructions hôte. Durant ce TER, les micro-opérations ajoutées sont celles dont le besoin était évident pour les traductions à effectuer : les opérations arithmétiques et logiques de base, les chargements mémoires,... De plus, il n a été question ici que de la traduction des instructions Neon vers les instructions MMX/SSE. Le fait de considérer un plus large panel d architecture (par exemple les instructions Altivec des PowerPC, ou les instructions VIS des SparcV9), que ce soit du côté de l architecture cible, ou hôte, rajoutera sans doute des contraintes à cette recherche de l ensemble optimal. 3 Tests et résultats L environnement de tests utilisé est une machine virtuelle exécutée par Qemu, et faisant tourner Linux. La machine virtuelle simulée est un dispositif de type système embarqué, appelé Beagle Board. Ce dispositif embarque entre autres, un processeur ARM Cortex-A8, qui nous intéresse puisqu il supporte les instructions Neon. Par manque de temps, il n a pas été possible de traduire toutes les instructions prévues à la base. Il n a pas non plus été possible de faire les tests avec FFmpeg, de part la trop grande complexité de la mise en place d un environnement de tests suffisamment évolué pour faire tourner celui-ci. Le principal problème rencontré fût la cross-compilation des binaires à partir de la machine hôte, pour la machine cible. Pour une raison inconnue, la majorité de ces binaires produisent une erreur de segmentation lors de leur exécution. Cependant, un programme suffisamment simple parvient à s exécuter (il semblerait que les erreurs de segmentations surviennent lors d appels à la libc). C est ainsi qu un benchmark composé d instructions Neon a pu être exécutés sur différentes version que Qemu. Ce benchmark exécute dix millions de fois une fonction contenant la majorité des instructions Neon traduites dans le cadre du TER. Le programme en question est fourni en annexe. Voici un tableau récapitulant les temps obtenus dans les différents cas. Version de Qemu Premier temps d exécution Temps moyen d exécution Version d origine 6.60s 6.21s Version méthode 1 6.22s 5.84s Version méthode 2 1.59s 1.16s La distinction entre le premier temps d exécution et les autres est dû au fait que lors de la première exécution du programme, Qemu effectue effectivement la traduction dynamique. 11

3 TESTS ET RÉSULTATS Pour les exécutions suivantes, il se contente de ré-exécuter les basic blocks déjà traduits, d où la différence de temps dans les trois cas. Les deux méthodes affichent des performances meilleures que celles du Qemu d origine, avec une très nette différence pour la méthode 2. Cela était prévisible puisque pour la première méthode, le gain est celui de l appel de fonction en moins alors que pour la deuxième méthode, des instructions SIMD sont utilisées sur l architecture hôte. Pour la première méthode, le gain est de quelques dixièmes de secondes, alors que pour la deuxième, le temps d exécution est divisé par un facteur 5.35. Qemu permet de dumper dans un fichier de log, les instructions générées pour la machine hôte. Pour chaque basic block, il donne leur taille et leur contenu. Voici les tailles en octets des basic blocks générés pour la fonction du benchmark : Version de Qemu Version d origine Version méthode 1 Version méthode 2 Taille du basic block 2087 octets 2199 octets 420 octets Le basic block de la méthode 1 est plus gros que celui de la version d origine. Cela est dû au fait que la version d origine ne contient que des appels de fonction, alors que la méthode 1 déroule l instruction dans le basic block lui même. Le basic block de la méthode 2 est lui quatre fois plus petit, ce qui correspond environ au gain de temps observé précédemment. Conclusion Ce TER a été l occasion de travailler sur un logiciel libre, pour chercher à optimiser une partie de celui-ci. Le but étant d optimiser la traduction des instructions Neon de l architecture ARMv7, deux méthodes sont ressorties. Une première méthode consistant à remplacer les helpers par des micro-opérations TCG déjà existantes, et la deuxième à enrichir la TCG avec des microopérations SIMD. La première méthode se veut plus simple à mettre en oeuvre puisqu il ne faut apporter des modifications qu à la partie traduction ARM vers TCG, alors que la deuxième oblige, non seulement à modifier cette partie, mais aussi la TCG en elle-même, ainsi que toutes les implémentations d architectures hôtes, pour supporter les nouvelles micro-opérations. Cependant, les gains en performance sont tels avec la deuxième solution que ce TER a démontré la viabilité de celle-ci. Il serait maintenant pertinent de faire une étude plus approfondie sur le jeu de micro-opérations SIMD à rajouter à la TCG, et ce, en prenant en compte un plus large panel d architectures, à la fois cibles, et hôtes. En étudiant les instructions SIMD de celles-ci, il faudrait en extraire le jeu de micro-opérations SIMD optimal pour la TCG. 12

3 TESTS ET RÉSULTATS Annexes Programme de benchmark Listing 8 Fonction assembleur du programme de benchmark. g l o b a l t e s t s i m d t e s t s i m d : vrshr. u8 q0, q0, #1 vrshr. u16 q0, q0, #2 vrshr. u32 q0, q0, #3 v s h l. u8 q0, q0, #1 v s h l. u16 q0, q0, #2 v s h l. u32 q0, q0, #3 vshr. u8 q0, q0, #1 vshr. u16 q0, q0, #2 vshr. u32 q0, q0, #3 v s h l. s8 q0, q0, #1 v s h l. s16 q0, q0, #2 v s h l. s32 q0, q0, #3 vshr. s8 q0, q0, #1 vshr. s16 q0, q0, #2 vshr. s32 q0, q0, #3 vadd. u8 q0, q1, q2 vadd. u16 q0, q1, q2 vadd. u32 q0, q1, q2 bx l r 13

RÉFÉRENCES Références [1] Fabrice Bellard. Qemu, a fast and portable dynamic translator. In USENIX, 2005. [2] Intel Corporation. Intel R 64 and IA-32 Architectures Software Developer s Manual, 2010. [3] Intel Corporation, Carole DuLong, Mickey Gutman, and Mike Julier. Complete Guide to Mmx Technology. McGraw-Hill Professional, 1997. 14