• Aucun résultat trouvé

5.3 Implantation et optimisations sur DSP

5.3.1 G´ en´ eralit´ es sur les optimisations DSP

Les performances d’une application sur un processeur donn´e d´ependent de la com- plexit´e de calcul, mais aussi de l’implantation. Afin d’exploiter de mani`ere efficaces

5.3 implantation et optimisations sur dsp 113

Fig. 5.8 – Graphe d’architecture dans la m´ethodologie AAA : mod´elisation d’une plate-forme Sundance (2 DSP) reli´ee `a un PC via un bus PCI

les ressources de calcul, et d’augmenter ainsi les performances, l’implantation d’une application doit ˆetre optimis´ee. Pour cela, le code doit ˆetre modifi´e pour prendre en compte les sp´ecificit´es du processeur cible. Un code tr`es d´edi´e, ´ecrit en assembleur (langage machine) conduit aux meilleures performances, mais demande un temps de d´eveloppement long, est difficilement ´evolutif, et est sp´ecifique `a chaque processeur. Inversement un langage de haut niveau (ex : C) est ´evolutif et g´en´erique, mais ne prend pas en compte les sp´ecificit´es des processeurs. C’est alors au compilateur de r´ealiser les optimisations. Cependant, les compilateurs sont des programmes automa- tiques, et bien qu’ils puissent ˆetre performants, ils ne conduisent pas `a la meilleure implantation. Nous allons d´ecrire bri`evement des techniques de base pour optimiser une implantation avec un langage de haut niveau (le C). Nous utilisons l’environ- nement de compilation d´edi´e “Code Composer Studio” (CCS) de Texas Instruments pour programmer sur DSP, cependant les techniques utilis´ees sont g´en´eriques.

5.3.1.1 Optimisation des boucles

Les boucles sont le coeur de l’algorithme de calcul, c’est donc l`a que le temps de calcul est consomm´e. L’optimisation des boucles peut donc avoir un grand impact sur le temps d’ex´ecution global. Le compilateur utilis´e dispose d’un algorithme d’optimisa- tion de boucles grˆace `a la vectorisation et au pipeline logiciel.

Vectorisation Selon les op´erations `a effectuer et la multiplicit´e des boucles, plu- sieurs it´erations peuvent ˆetre d´eroul´ees, et les calculs ex´ecut´es en parall`ele sur les unit´es de calcul et avec des instructions SIMD (Single Instruction Multiple Data). Les op´erations doivent ˆetre assez simples pour permettre au compilateur de trouver l’ins- truction SIMD `a utiliser. De plus, la multiplicit´e doit ˆetre connue `a la compilation. Elle peut ˆetre fournie `a l’aide de macros de pre-traitement. L’int´erˆet est de charger au maximum les unit´es de calcul et les bus m´emoire afin d’approcher les performances

th´eoriques. Par exemple une unit´e de calcul 32 bits peut ex´ecuter simultan´ement la mˆeme op´eration sur quatre paires 8 bits ou deux paires 16 bits.

Pipeline logiciel Le DSP vis´e int`egre plusieurs unit´es de calcul d´edi´ees (arithm´etique, m´emoire, multiplication,...). Il est donc possible de parall´eliser plu- sieurs instructions si leur d´ependances le permettent. Afin de mieux ordonnancer les instructions, plusieurs it´erations de la boucle peuvent ˆetre pipelin´ees. C’est `a dire que les calculs d’une it´eration peuvent ˆetre ordonnanc´es alors que l’it´eration pr´ec´edente n’est pas termin´ee. Cela permet d’imbriquer les it´erations et de r´eduire la latence glo- bale d’une boucle. Celle-ci prend en compte l’initialisation du pipeline (prologue) et sa finalisation (´epilogue). La mise en pipeline d’une boucle avec peu d’it´erations doit donc veiller `a garder un prologue et un ´epilogue r´eduits pour ˆetre efficace.

Restrictions Pour que le compilateur puisse optimiser la mise en pipeline des boucles, certaines contraintes doivent ˆetre respect´ees :

– Pas de branchement : le nombre de cycle doit ˆetre constant et les instructions ex´ecut´ees doivent ˆetre toujours les mˆemes pour permettre au compilateur de les ordonnancer. Le conditionnement doit ˆetre limit´e pour ne pas g´en´erer de saut conditionnel (utilisation des op´erations conditionnelles seulement : l’ex´ecution d’une instruction peut ˆetre d´esactiv´ee en fonction de la valeur d’un registre). De mˆeme il ne doit pas y avoir d’appel de fonction.

– Le nombre d’it´eration doit ˆetre connu `a l’initialisation de la boucle : la condition de fin de boucle doit rester constante afin de pouvoir pipeliner les it´erations. – Le nombre d’instructions d’une boucle doit ˆetre limit´e (limites de l’outil).

Imbrication de boucles Comme nous venons de le voir, les boucles sont opti- mis´ees par le compilateur qui cr´ee un pipeline logiciel. Le temps d’ex´ecution d’une boucle comprend donc un prologue (initialisation du pipeline), le corps d’ex´ecution et un ´epilogue (vidage du pipeline). Lorsque des boucles sont imbriqu´ees, seul un niveau peut ˆetre optimis´e. Pour am´eliorer davantage les performances `a la fois en r´eduisant la latence due au prologue et `a l’´epilogue, et en optimisant l’ordonnancement sur un en- semble d’instructions plus grand, il convient de pouvoir r´ealiser les optimisations sur la boucle de plus haut niveau. Lorsque le nombre d’it´eration est connu `a la compilation, les courtes boucles int´erieures sont compl`etement d´eroul´ees pour permettre l’optimisa- tion des boucles imbriqu´ees. Ainsi, il est pr´ef´erable de d´efinir des fonctions sp´ecifiques (par exemple une par taille de bloc) qui peuvent ˆetre beaucoup plus performantes.

On peut noter que sur des processeurs du type Pentium, qui int`egrent un pr´edicteur de branchement et une unit´e d’ordonnancement pour r´eduire statistiquement le nombre de cycles perdus, la mise en pipeline est effectu´ee `a l’ex´ecution et que ce genre d’optimisation `a moins d’impact. A l’inverse, leur unit´es SIMD ´etant plus larges, la vectorisation a un impact important.

5.3.1.2 Utilisation du mot cl´e “restrict “

L’architecture m´emoire des processeurs cause une latence non n´egligeable lors de l’acc`es aux donn´ees. Cette latence peut ˆetre masqu´ee grˆace au pipeline, cependant,

5.3 implantation et optimisations sur dsp 115

le compilateur prend en compte par d´efaut le temps n´ecessaire `a la mise `a jour de la m´emoire entre une instruction d’´ecriture suivie d’une instruction de lecture, ce qui se traduit dans les boucles courtes `a des cycles vides. Pour ´eviter cela, il est possible de pr´eciser au compilateur que les donn´ees ´ecrites ne modifient pas les donn´ees lues, c’est `a dire que les buffers m´emoire en jeu ne se chevauchent pas. Le mot-cl´e “res- trict ” permet de pr´eciser le type d’un pointeur m´emoire en sp´ecifiant qu’il est le seul `

a acc´eder `a une espace donn´e. Le compilateur peut donc optimiser les acc`es m´emoire en ne prenant pas en compte les d´elais d’acc`es. L’op´eration type o`u l’impact est le plus important est la recopie m´emoire.

5.3.1.3 Les fonctions “inline”

Au lieu de g´en´erer un appel de fonction, le compilateur peut choisir d’int´egrer direc- tement le corps d’une fonction. Cela peut augmenter la taille du code car la fonction est recopi´ee autant de fois qu’il y a d’appel, mais les performances sont augment´ees en ´evitant le changement de contexte, les passages de param`etres et le branchement. De plus, la boucle contenant la fonction mise en ligne peut ˆetre optimis´ee par le com- pilateur, et le cache programme est mis `a profit, car les instructions sont proches en m´emoire. La fonction doit ˆetre d´efinie avec le mot-cl´e “inline”, ou bien dans certains cas le compilateur le fait automatiquement.

5.3.1.4 Utilisation des instructions sp´ecialis´ees

Lors de l’optimisation des boucles, le compilateur peut utiliser des instructions SIMD pour parall´eliser les traitements. Cependant lorsque la multiplicit´e de la boucle n’est pas bonne, en l’absence de boucle, ou si la vectorisation n’est pas triviale, les ins- tructions SIMD ne sont pas utilis´ees. Il est alors possible de forcer le compilateur `a utiliser des instructions SIMD en y faisant directement r´ef´erence par l’interm´ediaire de fonctions intrins`eques.

5.3.1.5 Acc`es m´emoire

Les processeurs sont compos´es de plusieurs niveaux de m´emoire. Les m´emoires L1 (ni- veau 1), proches du CPU (Central Processing Unit), sont rapides, elles fonctionnent `a la fr´equence du coeur de calcul, mais elles sont de taille r´eduite `a cause des contraintes physiques. La m´emoire L2 est une m´emoire interne interm´ediaire, et la m´emoire ex- terne peut ˆetre consid´er´ee sans limite de taille, mais a une bande passante r´eduite un temps d’acc`es long.

Dans le cas g´en´eral, une image haute d´efinition est contenue en m´emoire externe, car les m´emoires internes ne peuvent pas la contenir enti`erement. Pour ´eviter les pertes de performance dues `a l’acc`es aux donn´ees, les donn´ees utiles doivent ˆetre rapatri´ees en m´emoire interne (L2). Cela peut ˆetre fait manuellement en programmant un m´ecanisme d’acc`es aux donn´ees, ou automatiquement avec un contrˆoleur de cache. Dans les deux cas afin de r´eduire la fenˆetre utile d’acc`es aux donn´ees pour ´eviter les d´efauts de cache L2 (requˆete vers une donn´ees non mise en cache), et optimiser l’utilisation du cache L1 (de taille r´eduite), il convient de mettre `a profiter la localit´e des donn´ees.

Nous avons d´ecrit les techniques g´en´erales utilis´ees lors de l’implantation des al- gorithmes d’estimation de mouvement. L’ex´ecution d’un programme non optimis´e sur DSP conduit souvent `a des performances pouvant ˆetre de cinq `a dix fois inf´erieures aux performances attendues. L’´etape d’optimisation ne doit donc pas ˆetre n´eglig´ee. Dans le paragraphe suivant nous allons traiter des optimisations sp´ecifiques `a l’estimation de mouvement.