sommaire - foad.ensicaen.fr

86
DIGITAL SIGNAL PROCESSOR Travaux Pratiques SOMMAIRE SEQUENCEMENT PREAMBULE 1. ALGORITHME DE FILTRAGE 1.1. Algorithme de référence 1.2. Test de performance 1.3. Intégration en C canonique 2. AUTOMATISATION DES TESTS 2.1. Test de conformité 2.2. Test de performance 2.3. Temps de compilation et empreinte mémoire 2.4. Temps de programmation 3. PROGRAMMATION VECTORIELLE 3.1. Assembleur canonique C6600 3.2. Assembleur VLIW C6600 3.3. Pipelining logiciel assembleur C6600 3.4. Assembleur vectoriel C6600 3.5. Déroulement de boucle en C 3.6. Vectorisation de code en C 3.7. C canonique sur architecture IA-64 3.8. Vectorisation SSE4.1 sur architecture IA-64 4. HIERARCHIE MEMOIRE 4.1. Mémoire locale adressable 4.2. Préchargement des données de DDR SRAM vers L2 SRAM 4.3. Préchargement des données de L2 SRAM vers L1D SRAM 5. PERIPHERIQUES D'ACCELERATION 5.1. Transferts par IDMA 5.2. Stratégie Ping Pong 5.3. Transferts par EDMA BILAN BENCHMARKING 1

Upload: others

Post on 19-Jun-2022

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

SOMMAIRE

SEQUENCEMENT

PREAMBULE

1. ALGORITHME DE FILTRAGE

1.1. Algorithme de référence1.2. Test de performance1.3. Intégration en C canonique

2. AUTOMATISATION DES TESTS

2.1. Test de conformité2.2. Test de performance2.3. Temps de compilation et empreinte mémoire2.4. Temps de programmation

3. PROGRAMMATION VECTORIELLE

3.1. Assembleur canonique C66003.2. Assembleur VLIW C66003.3. Pipelining logiciel assembleur C66003.4. Assembleur vectoriel C66003.5. Déroulement de boucle en C3.6. Vectorisation de code en C3.7. C canonique sur architecture IA-643.8. Vectorisation SSE4.1 sur architecture IA-64

4. HIERARCHIE MEMOIRE

4.1. Mémoire locale adressable4.2. Préchargement des données de DDR SRAM vers L2 SRAM4.3. Préchargement des données de L2 SRAM vers L1D SRAM

5. PERIPHERIQUES D'ACCELERATION

5.1. Transferts par IDMA5.2. Stratégie Ping Pong5.3. Transferts par EDMA

BILAN

BENCHMARKING

1

Page 2: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

SEQUENCEMENT

• Travaux préparatoires à réaliser avant chaque séance. Suivre les exercices préparatoires du polycopié ou les directives de l'enseignant d'une semaine sur l'autre. Correction faite par un étudiant en début de TP selon les séances.

• Séance n°1 : exercices 1 et 2

• Séance n°2 : exercices 3.1 et 3.2

• Séance n°3 : exercices 3.3 et 3.4

• Séance n°4 : exercices 3.5, 3.6 et 3,7

• Séance n°5 : exercices 3.8 et 4.1

• Séance n°6 : exercices 4.2 et 4.3

• Séance n°7 : exercices 5.1 et 5.2

• Rapport de Synthèse : compte-rendu de synthèse de 7 pages à réaliser hors séance

2

Page 3: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

PREAMBULE

3

Page 4: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

PREAMBULE

Durant cette trame de travaux pratiques, nous allons nous intéresser au workflow typiquement rencontré en milieu industriel dans le cadre d'optimisation logicielle d'algorithme pour une cible matérielle spécialisée. Ce processus de développement peut par exemple être rencontré chez les acteurs des grands domaines du traitement du signal (traitement d'antenne, traitement d'image, traitement du son …). Nous travaillons d'ailleurs à l'ENSICAEN avec plusieurs partenaires industriels utilisant ce type de méthodologie.

Durant la séquence qui suit, nous nous intéresserons à l'implémentation d'un algorithme simple et standard du domaine du traitement du signal, un filtre FIR ou produit scalaire. Nous nous attarderons bien entendu aux stratégies d'optimisation sur une architecture matérielle spécialisée. Tous nos développements seront guidés par le test, étape pouvant tenir une place très importante dans le temps de développement global d'une application et le benchmarking (analyse comparative). Nous constaterons que si cette étape n'est pas délaissée, il nous ait alors possible de gagner des jours de développement sur une tâche courante. Observons le workflow de la trame de travaux pratiques :

• Analyse mathématique théorique de l'algorithme

• Modélisation et validation sur outil de prototypage. L'outil logiciel de prototypage rapide le plus rencontré en milieu industriel à notre époque dans le domaine de l'embarqué appliqué au traitement du signal est Matlab/Simulink. Cette étape est essentielle afin de valider la structure en pseudo code des algorithmes ainsi que les vecteurs d'entrée et de sortie pour les procédures de test à venir

• Intégration sur cible d'un algorithme de référence

• Intégration sur cible des procédures de test. Dans le cadre de nos développements, nous nous intéresserons essentiellement aux tests de conformité et de performance dans une optique de benchmarking

• Intégrations et validations successives sur cible des stratégies d'optimisation sur architecture processeur spécialisée (vectorisation monocœur, parallélisation multicœur, gestion optimale de la hiérarchie mémoire et périphériques d'accélération)

4

Page 5: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Dans une optique pédagogique et professionnalisante, notre choix s'est porté sur l'architecture C6600 proposée par Texas Instruments. Pour information, en 2015 la famille C6000 de TI est l'architecture leader sur le marché des processeurs DSP (Digital Signal Processor). Le processeurC6678 étudié en TP étant l'un des composant haut de gamme de la famille avec ses 8 cœurs vectorielsVLIW. Cette architecture propose quelques atouts assurant une grande flexibilité et permettant une bonne compréhension des architectures processeurs actuelles. Observons là plus en détails :

Le processeur DSP TMS320C6678 offre 8 cœurs vectoriels VLIW (Very Long Instruction Word) possédant chacun 32Ko caches L1 program et L1 data, ainsi que 512Ko de cache L2. Chaque cœur peut-être cadencé jusqu'à 1,4GHz. Le niveau mémoire L3 de 4Mo nommé MSM (Multi-core Shared Memory) est partagé entre cœurs. Chaque niveau mémoire peut être configurable en cache ou en mémoire adressable SRAM permettant une architecture matérielle configurable en modèle mémoire uniforme ou non-uniforme. Chose impossible sur processeur généraliste GPP Intel par exemple. De la mémoire RAM DDR3 externe peut également être ajoutée sur circuit imprimé et est alors interconnectée via le périphérique d'interface EMIF (External Memory Interface).

En première année, nous avons découvert les bases du développement sur processeur numérique. Afin de faciliter cette approche nous avons développé sur MCU (Micro Controller Unit) oumicrocontrôleur. Ces processeurs étant généralistes et non spécialisés pour du calcul numérique massif, nous nous sommes donc assez longuement attardés sur les périphériques et interfaces de communication :

5

Page 6: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

L'enseignement de cette année est différent et doit être perçu comme une extension des compétences de première année. Cette année nous allons travailler sur machine fortement parallèle et nous nous efforcerons de comprendre puis d'exploiter au mieux les ressources matérielles proposées par notre processeur. Les périphériques d'interface ne seront donc pas vus, seule la partie processing nous intéressera. Nous nous focaliserons donc sur l'architecture vectorielle, parallèle et le pipeline de chaque cœur, les hiérarchies mémoires ainsi que les périphériques d'accélération :

Même si l'exemple qui suit n'a que peu de sens, afin de bien comprendre les différences majeures entre les architectures de première année et de deuxième année, comparons les performances théoriques maximales des deux processeurs. Un MCU 8bits PIC18 de Microchip peut exécuter jusqu'à 12MIPS (soit 12 millions instructions entières 8bits par seconde). Un DSP 32bits TMS320C6678 de Texas Instruments peut exécuter jusqu'à 22,4GFLOP/core (soit 22,4 Giga instructions flottantes 32bits en simple précision par seconde par cœur). Soit jusqu'à 179,2GFLOP pour le processeur complet grâce à ses 8 cœurs, le tout avec une horloge à 1,4GHz. Avec ces quelqueschiffres, nous pouvons commencer à pressentir le potentiel pour du calcul numérique flottant de cette famille de processeur.

La trame de travaux pratiques sera réalisée sur la plateforme de développement TMDXEVM6678L EVM (EValuation Module) proposé par la société Advantec. Cette maquette d'évaluation embarque notamment une sonde d'émulation USB XDS100 assurant la programmation et le débogage des applicatifs :

6

Page 7: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Les outils de développement et bibliothèques sont librement téléchargeables et installables depuis internet du moment que nous n'utilisons que la sonde de programmation XDS100 présente sur la maquette ou le mode simulation. Les outils deviennent alors payants si nous souhaitons travailler avec des sondes d'émulation évoluées, telle que la sonde XDS560 également présente à l'école. Voici ci-dessous des liens vers les outils logiciels (IDE, SDK) utilisés afin de réaliser la trame de travaux pratiques. Bien entendu, nous vous conseillons vivement d'installer ces outils sur vos machines (IDE et bibliothèques spécifiées ci-dessous) :

• Wiki Processeurs TI. Point d'entrée des différentes ressources en ligne proposées par Texas afin de développer sur la totalité de leurs gammes de processeurs :

http://processors.wiki.ti.com/index.php/Main_Page

• IDE Code Composer Studio v6.0 basé sur Eclipse et ABI associées (Application Binary Interface). Nous vous conseillons une installation hors ligne. De plus, le téléchargement des outils depuis le site officiel de Texas Instruments requiert une inscription à leur site. La validation par TI de cette étape peut prendre quelques jours, ne pas être surpris :

http://processors.wiki.ti.com/index.php/Category:Code_Composer_Studio_v6

• Bibliothèques de fonctions C CSL (Chip Support Library) proposées par TI pour la gestion des périphériques internes de leurs familles de processeurs. Bien choisir la bibliothèque associée au processeur C6678 : http://processors.wiki.ti.com/index.php/Chip_support_library

Après installation, CSL est accessible depuis le répertoire suivant : C:\ti\pdk_C6678_version\packages\ti\csl\

• Bibliothèque DSPLIB (Digital Signal Processing Library) développée par TI et proposant des fonctions C pour le domaine du traitement numérique du signal et optimisée pour leurs architectures processeurs. Dans notre cas, seules les bibliothèques pour la famille C6600 nous intéressent :

http://www.ti.com/tool/SPRC265

Après installation, la DSPLIB est accessible depuis le répertoire suivant : C:\ti\dsplib_c66x_version\packages\ti\dsplib\

7

Page 8: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

A partir de maintenant, le travail qui nous attend consiste à implémenter un algorithme de filtrage FIR (ou produit scalaire) sur une architecture spécialisée pour du calcul numérique. Effectuonsquelques rappels sur cet algorithme. Une implémentation courante de ce filtre consiste à appeler périodiquement (période d'échantillonnage) l'algorithme dans une optique de calcul en temps réel. A chaque appel, seul un échantillon de sortie est calculé puis traité :

x() = vecteur d'échantillons d'entrée (taille égale à N)a() = vecteur de coefficientsy(k) = échantillon courant de sortiek = indice courantN = ordre du filtreN+1 = nombre de coefficients

L'implémentation vue en travaux pratiques se fera en temps différé. Nous calculerons un vecteur de sortie complet en traitant l'information depuis un vecteur d'entrée pouvant être très long et dans tous les cas de figure de taille supérieure ou égale au nombre de coefficients :

x() = vecteur d'échantillons d'entrée (taille supérieure ou égale à N)a() = vecteur de coefficientsy() = vecteur d'échantillons de sortiek = indice courantN = ordre du filtreN+1 = nombre de coefficientsY = taille du vecteur de sortieY+N-1 = taille du vecteur d'entrée

La phase de prototypage rapide sous environnement Matlab/Simulink ne sera pas à faire et vous est donnée (répertoire de projet /disco/matlab/). Elle est entièrement recouverte par le programme de 1ière année en Traitement Numérique du Signal. Nous nous attarderons uniquement sur les problématiques liées à l'intégration sur DSP TMS320C6678. Observons l'implémentation en pseudo code Matlab au format flottant simple précision IEEE754 de l'algorithme de filtrage en temps différé précédemment présenté :

function yk = fir_sp(xk, coeff, coeffLength, ykLength) yk = single(zeros(1,ykLength)); % output array preallocation % output array loop for i=1:ykLength yk(i) = single(0); for j=1:coeffLength yk(i) = single(yk(i)) + single(coeff(j)) * single(xk(i+j-1)); end endend

8

Page 9: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Voici enfin quelques compléments d'information concernant le filtre à intégrer sur cible ainsi que sur les vecteurs d'entrée et de sortie. La synthèse et la génération du filtre a été réalisée sous Matlab/Simulink via l'outil FDATool. Il s'agit d'un filtre passe bas coupant à 200Hz pour une fréquence d'échantillonnage à 10KHz, d'ordre 63 (comprenant donc 64 coefficients de symétrie paire en flottant simple précision IEEE754), offrant un gain unitaire dans la bande passante et une atténuation de -40dB dans la bande coupée. La bande d'atténuation est comprise entre 200Hz et 600Hz. Ce filtre ne vise aucune application ou domaine spécifique et ne nous servira qu'à illustrer les concepts et stratégies d'optimisation sur processeur spécialisé.

Le vecteur de test d'entrée est une simple somme de deux sinusoïdes à 100Hz et 1KHz. Après filtrage, seule l'harmonique à 100Hz est clairement identifiable. Génération du vecteur sous Matlab :

Fs = 10000; % sample frequency Ts = 1/Fs; % period frequencyF1 = 100; % harmonic n°1 of input vectorF2 = 1000; % harmonic n°2 of input vectorXK_LENGTH = 2048; % 2K/8Kb samples : length of input vectort=0 : Ts : (XK_LENGTH-1)*Ts; % time vector %*** INPUT VECTOR GENERATIONxk = single(sin(2*pi*F1*t) + sin(2*pi*F2*t));

9

Page 10: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Radar de défense aérienne GM 400 développé par THALES AIR SYSTEMS

Enfin pour conclure, afin de bien prendre conscience de l’intérêt de tel développement et phases d'optimisation, prenons l'exemple d'une application radar. Nous pouvons observer, ci-dessous,l'architecture matérielle typique d'un radar. Observons l'emplacement du processeur de traitement numérique du signal, dans le cas présent un DSP. Il faut savoir que d'autres familles de processeurs peuvent également remplir cette tâche (GPP, GPU ou FPGA/SoC), chaque famille offrant son lot d'avantages et d'inconvénients.

Une chaîne numérique de traitement radar implémente également un produit scalaire commecelui étudié dans cette trame de travaux pratiques (algorithme FIR). A titre indicatif, à lui seul cet algorithme pèse près de 40% de la charge CPU d'une chaîne complète. Compte-tenu des contraintes temps réel excessivement lourdes imposées par ce type d'application (qqMo de données à traiter en qqms), nous pouvons pressentir tout l'intérêt de développer des bibliothèques de fonctions spécialisées pour l'architecture cible. Ce sera l'objectif premier de cet enseignement tout en respectant des méthodologies assurant un développement le plus optimal possible.

10

Page 11: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

11

Page 12: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

ALGORITHME DE FILTRAGE

12

Page 13: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

1. ALGORITHME DE FILTRAGETravail préparatoire

Culture Générale

• 1. (1pt) Question de traitement Numérique du Signal (cf. programme de première année). Il existe deux grandes familles de filtres numériques, les filtres FIR (Finite Impulse Response) et IIR (Infinite Impulse Response). Quels sont les avantages et inconvénients des filtres FIR et citer des exemples d'application dans lesquels nous pouvons les rencontrer ?

• 2. (0,5pt) Question traitant du préambule. Combien, le DSP étudié cette année, possède-t-il de cœurs ?

• 3. (0,5pt) Question traitant du préambule. Quel est l'ordre du filtre numérique implémenté en TP ? A titre indicatif, il s'agit du même ordre de grandeur que celui rencontré dans une chaîne radar pour la réalisation de convolution

• 4. (0,5pt) Question traitant du préambule. Rappeler la méthodologie de développement (workflow) déployez durant cet trame de TP et également rencontrée en milieu industriel

• 5. (1,5pt) Question traitant du préambule. Que signifie, développement guidé par le test ? S'aider d'internet

• 6. (0,5pt) Rappeler le rôle et l'utilité du qualificateur de type const. Bien entendu, ne pas répondre ''définir une constante''

• 7. (0,5pt) Quel est le rôle des directives pré-processeur #if en #endif ? Donner des exemples d'utilisation de ces directives

• 8. (0,5pt) En vous aidant d'internet, donner également le rôle du qualificateur de type restrict.Expliquer dans quels cas nous pouvons le manipuler ainsi que son utilité dans le cadre de cette trame d'enseignement

• 9. (0,5pt) Rappeler ce qu'est un Timer (cf. programme de première année) pour un processeurnumérique (MCU, DSP, GPP …)

13

Page 14: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Analyse d'un projet logiciel

• 10. (1,5pt) Récupérer et extraire l'archive dsp-tp.tar depuis la plateforme pédagogique moodle. Expliquer exhaustivement le contenu de l'arborescence de fichiers

• 11. (0,5pt) En vous aidant de la réponse à la question précédente, expliquer pourquoi le projetde test reste physiquement dissocié des projet bibliothèques

• 12. (0,5pt) Chez Texas Instruments, qu'est-ce que CSL (Chip Support Library) ? Télécharger CSL pour notre architecture processeur

• 13. (1pt) Chaque cœur de notre DSP possède un timer 64 bits mis à zéro au reset, extrêmement simple d'utilisation et travaillant à la fréquence de travail du cœur (soit 1,4Ghz dans notre cas). Ces timers se nomment TSC (Time Stamp Counter) et servent typiquement à de la mesure de performance. Pour information, tout processeur GPP Intel actuel possède également un timer nommé TSC dans chaque cœur. En vous aidant de la documentation technique de CSL présente dans le répertoire de projet (/disco/c6678/doc/csl/docs/doxygen /html/index.html) ou sur internet, détailler l'API (Application Programming Interface) de programmation proposée par TI afin d'utiliser ces timers

• 14. (0,5pt) Proposer un code C permettant la mesure du temps écoulé en nombre de cycles CPU concernant l'exécution d'une zone de code ainsi que l'affichage de celui-ci via la fonction standard printf

14

Page 15: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

1. ALGORITHME DE FILTRAGETravail en séance

Pour des raisons pédagogiques et un gain de temps certain, les deux premiers

exercices sont dédiés à l'analyse de l'ossature du programme, sa

compréhension et la prise en main des outils de développement.

Les sources des deux premiers exercices vous sont donc fournis. Nous vous

demandons de réaliser la trame de Travaux Pratiques initiale en remplaçant

les phases de développement par des phases de copie successives de code.

L'objectif étant de vous concentrer sur l'analyse et une compréhension fine de

l'ensemble du projet logiciel. Nous nous focaliserons par la suite sur le

processus d'optimisation sur architecture processeur spécialisée.

Récupérer et extraire dès maintenant l'archive dsp-tp.tar sur la plateforme

d'enseignement moodle

1.1. Algorithme de référence

Durant toute la trame de travaux pratiques, ne pas oublier de parcourir voire lire les annexes proposant notamment un tutoriel d'utilisation de l'IDE Code Composer Studio de Texas Instruments, un exemple de création de projet sous ce même IDE, un exemple de création de bibliothèque statique… De même, durant la totalité de la trame, Nous vous demanderons de respecter impérativement lesrègles de codage (coding style) imposées en annexe.

• La totalité des fichiers sources avec solutions pour les deux premiers exercices se trouvent dans le répertoire /teacher/

• Créer un projet nommé firtest dans le répertoire /disco/c6678/test/pjct/ incluant le source/disco/c6678/test/src/firtest_example.c. S'assurer de la bonne compilation et exécution du projet.

15

Page 16: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Sans pour autant créer un nouveau projet, retirer le fichier source /disco/c6678/test/src/firtest_example.c puis ajouter le fichier source /disco/c6678/test/src/firtest_main.c. S'assurer de la bonne compilation et exécution du projet. Bien penser à lire attentivement le contenu des fichiers d'en-tête.

Les fichiers d'en-tête servent souvent de documentation pour une libraire ou un projet logiciel. Ils précisent notamment les services logiciel proposés par une bibliothèque ou un applicatif et donc ce que nous pouvons faire et ne pas faire avec le projet courant.

• Nous allons maintenant intégrer puis exécuter un algorithme de filtrage développé par Texas Instruments et optimisé pour l'architecture DSP C6600. Celui-ci jouera le rôle d'algorithme de référence, nous permettra de valider nos futurs vecteurs de sortie et nous servira de mesure étalon pour nos benchmarks à venir (analyses comparatives).

En vous aidant de la documentation technique de la bibliothèque DSPLIB de TI présente sous /disco/c6678/doc/dsplib/DSPLIB_Users_Manual.chm ou C:\ti\dsplib_c66x_version\docs\ DSPLIB_Users_Manual.chm, appeler depuis la fonction main la procédure DSPF_sp_fir_gen en respectant le prototype imposé et en passant comme arguments les variables et macros définies dans les fichiers sources et d'en-tête actuellement présent dans notre projet (a_sp.h, xk_sp_8Kb.h et firtest.h). Le vecteur de sortie sera sauvé dans le tableau yk_sp_ti.

• Visualiser les vecteurs d'entrée et de sortie après exécution du programme en utilisant l'utilitaire graphique Graph proposé par CCS depuis l'espace de débogage. Après quelques utilisations de cet utilitaire fort peu utile et performant, nous comprendrons l'utilité d'automatiser les procédures de tests afin de gagner un temps considérable dans nos développement.

◦ S'assurer que le projet soit bien configuré en mode Debug

◦ Après compilation, programmation et exécution, basculer dans l’environnement de travail CCS Debug, puis mettre le programme en pause sans pour autant stopper la session de debug.

◦ Ajouter les variables xk_sp et yk_sp_ti dans la fenêtre Expressions

◦ Clic droit sur chaque variable puis cliquer sur Graph

◦ Paramétrer l'outil comme vous pouvez. Cet utilitaire étant fortement bogué, lent et peu flexible, nous nous efforcerons par la suite à l'utiliser le moins souvent possible.

16

Page 17: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

◦ Valider graphiquement les vecteurs d'entrée et surtout celui de sortie (limiter le nombre d'échantillons affichés à 200). Celui-ci nous servira de vecteur étalon pour tousnos futurs développement :

vecteur d'entrée (200 échantillons) vecteur de sortie (200 échantillons)

17

Page 18: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

1.2. Test de performance

• En vous aidant du travail préparatoire, valider l'utilisation du timer TSC puis effectuer une mesure de performance de l'algorithme développé par TI en vous aidant de la fonction standard printf. Rappelons, qu'une API d'utilisation du timer TSC est proposée par CSL.

• Temps écoulé en nombre de cycles CPU pour l'algorithme de référence développé par TI :

CPU cycles

Dans le projet actuellement en cours de développement, l'utilisation de la fonction C standard printfne pose que peu de soucis car seules certaines zones de code bien spécifiques sont en cours de test et de validation. En effet, il ne s'agit pas d'un système logiciel complet. Néanmoins, dans les années à venir, bien garder en tête que cette fonction standard est rarement optimisé pour s'exécuter sur un processeur de type MCU ou DSP et est à bannir durant vos phases de développement. Son tempsd'exécution est souvent excessivement long. Par exemple, ne jamais appeler un printf depuis une ISR (Interrupt Software/Service Routine). Pour résumer, dans le domaine de l'embarqué, bannir dès que possible la fonction printf de vos développements sauf si vous développez sur processeur généraliste (GPP, SoC) sous un système d'exploitation évolué (GNU\Linux, Android …). En général, des fonctions optimisées non standards sont fournies par l'ABI, par exemple la fonction LOG_printf chez TI.

18

Page 19: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

1.3. Intégration en C canonique

Jusqu'à présent, nous n'avons fait que créer un projet et appeler des fonctions développées par d'autres, en l’occurrence des ingénieurs d'application de chez Texas Instruments. Nous allons attaquer nos premières phases de développement pour à terme essayer de faire mieux que Texas. L'avenir nous dira si nous réussirons.

• Sans créer de nouveau projet ni toucher au code précédemment écrit, rajouter un test de performance pour l'algorithme de filtrage fir_sp. Inclure le fichier /disco/c6678/firlib/src/fir_sp.c au projet puis le modifier. Cet algorithme est une implémentation standard C99 canonique (sans optimisation) d'un produit scalaire. Il nous servira quant à lui de référence dans nos futures phases d'optimisation.

Ajouter le source au projet puis compléter la définition de la fonction en vous aidant du travailpréparatoire. S'assurer de la bonne compilation et exécution du projet. Valider également avecl'outil Graph le vecteur de Sortie. Le vecteur de sortie sera sauvé dans le tableau yk_sp.

• L'outil d'analyse graphique Graph permet-il une validation rigoureuse du vecteur de sortie ? Justifier votre réponse.

• Instrumenter le code afin de réaliser un mesure de performance. En vous aidant des annexes, configurer le projet en mode Release puis effectuer le test (debug retiré et options d'optimisation levées). Noter le temps écoulé en nombre de cycles CPU pour l'algorithme de référence FIR en C canonique :

CPU cycles

• Modifier maintenant votre projet de façon à respecter l'affichage suivant :

19

Page 20: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

20

Page 21: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

AUTOMATISATION DES TESTS

21

Page 22: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

2. AUTOMATISATION DES TESTSTravail en séance

Cette partie est essentielle et va nous permettre de gagner un temps non négligeable durant nos futures phases de développement. Nous avons pu constater dans la partie précédente que la validation des données de sortie d'algorithmes n'est pas forcément triviale, surtout dans le cas de larges vecteurs de données. Une validation manuelle terme à terme faite par le développeur n'est pasconcevable dans un contexte industriel. Le temps ingénieur étant probablement la ressource la plus précieuse dans une optique de conduite et de suivi de projet. Les exercices qui vont suivre seront donc découpés en trois grandes parties dans une optique d'optimiser notre temps de développementdurant nos travaux futurs :

• Écriture d'un test de conformité

• Écriture d'un test de performance

• Optimisation du temps ingénieur durant les phases de test

22

Page 23: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

2.1. Test de conformité

Nous allons débuter par le développement d'un test de conformité assurant la validation de nos futurs vecteurs de sortie. Nous utiliserons toujours pour référence le vecteur de sortie de l'algorithme de Texas Instruments (algorithme DSPF_sp_fir_gen et vecteur de sortie yk_sp_ti). Ce testest très générique et peut très bien être réutilisé dans un cadre plus large pour d'autres algorithmes àtester.

• Dans le fichier d'en-tête firtest.h présent dans le répertoire /disco/c6678/test/h/ nous pouvons observer la déclaration d'un type structure TestSystem_obj spécifique à notre projet. Pour notre projet, il s'agit d'un objet logiciel mis à jour notamment par la fonction firtest_sys et sauvegardant temporairement les sorties de nos différents tests de conformité. Observer son contenu et le commenter exhaustivement ci-dessous. Ne pas hésiter à interroger l'enseignant encadrant si vous avez un doute :

typedef struct {char error_status[4]; // string to specify validity of test (''OK'' or ''NOK'')uint64_t error_samples; // number of false samplesfloat error_percent; // maximum percentage errorfloat error_margin; // maximum tolerated margin. Have to be initialized

} TestSystem_obj; // conformity test object

• Ajouter au projet le fichier source firtest_sys.c et s'assurer de sa bonne compilation.

• Sachant que le champ error_margin est à initialiser au début du lancement du programme (erreur tolérée pour notre procédure de test) et en vous aidant du travail préparatoire, écrire et valider le code implémentant la fonction firtest_sys. Cette fonction est découpée en trois parties :

◦ initialisation de la boucle de test

◦ boucle de test assurant une comparaison terme à terme des différents éléments des vecteurs d'entrée, capturant le pourcentage d'erreur maximale mesurée durant la totalité du test et comptant le nombre d'échantillons ayant une erreur supérieure à la marge fixée dans le cahier des charges du projet. Dans notre cas, nous tolérerons une erreur strictement inférieure à 1%.

◦ Mise à jour de l'objet logiciel capturant les informations de sortie du test de conformité. Nous pourrons enfin quitter la procédure en retournant un booléen indiquant la validité du test.

23

Page 24: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Modifier maintenant votre projet de façon à respecter l'affichage suivant. L'affichage des performances de l'algorithme en cours de test ne devra se faire que si la validité du vecteur desortie associé est actée.

Comme dans beaucoup de développement logiciel dans l'embarqué, il est courant d'utiliser la valeurde retour d'une fonction comme indicateur de sa bonne exécution (valeur booléenne). De même, comme pour une approche orientée objet, notre procédure de test n'a pour rôle que d'appliquer untraitement à l'objet d'entrée. Aucun affichage ne doit être fait dans cette fonction. Tous les affichages et interfaces développeur seront gérées depuis la fonction main. De plus, si votre implémentation respecte des standards du C (exemple C99), ceci permet d'assurer une portabilité pour d'éventuelles réutilisations dans d'autres projets.

24

Page 25: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

2.2. Test de performance

Nous allons maintenant nous attaquer à l'écriture d'un test de performance générique, pouvant être appliqué à la totalité des algorithmes de filtrage FIR sous tests mais également aux futurs modèles mémoires déployés dans la suite de la trame de travaux pratiques.

• Dans le fichier d'en-tête firtest.h présent dans le répertoire /disco/c6678/test/h/ nous pouvons observer la déclaration d'un type structure TestPerf_obj spécifique à notre projet. Pour notre projet, il s'agit d'un objet logiciel mis à jour notamment par la fonction firtest_perf et sauvegardant temporairement les sorties de nos différents tests de performance. Observer son contenu et le commenter exhaustivement ci-dessous. Ne pas hésiter à interroger l'enseignant encadrant si vous avez un doute :

typedef struct {uint32_t perf_rep; // number of test repetitionsCSL_Uint64 perf_nbcycles; // duration in number of CPU cyclesfloat32_t perf_usertime_ms; // duration in msfloat32_t perf_macs; // algorithm performance in MAC per CPU cycle

} TestPerf_obj; // performance test object

• Que vaut la complexité en MACS de notre algorithme implémentant un produit scalaire (filtre FIR) ?

• Pourquoi, dans une optique de benchmarking, est-il intéressant de répéter plusieurs fois l'exécution de l'algorithme sous test puis de moyenner les résultats de sortie (uniquement sur architecture déterministe) ? Nous constaterons qu'il sera plus rigoureux de prendre la valeur maximale sur architecture non déterministe (GPP, AP à CPU superscalaires ou sur GPU).

Pour information, dans le domaine l'embarqué appliqué au traitement numérique du signal, l'un desprincipaux indicateurs de performance d'un algorithme est donné par son nombre de MAC's par cycle CPU (ou GMACS, Giga Multiply Accumulate per Second). Cet indicateur étant lié à la complexité mathématique de l'algorithme (cf. enseignement d'algorithmique). Dans le cas de notre architecture, un DSP de la famille C6600 peut offrir jusqu'à 8 MAC/cy par cœur (soit un maximum de11,2 GMACS avec une horloge à 1,4GHz par cœur et 89,6 GMACS pour le processeur).

25

Page 26: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Ajouter au projet le fichier source firtest_perf.c et s'assurer de sa bonne compilation.

• En vous aidant du travail préparatoire, écrire et valider le code implémentant la fonction firtest_perf. Dans un premier temps, nous ne tiendrons pas compte du paramètre memoryModel qui sera abordé par la suite. Le paramètre output permet quant à lui d'écraser le vecteur précédemment sous test par le vecteur de sortie en cours de validation. Cette fonction peut être découpée dans deux parties :

◦ Boucle fixant le nombre d'appels de l'algorithme en cours de test. La mesure et l'accumulation des temps d'exécution se feront dans la boucle.

◦ Mise à jour de l'objet logiciel capturant les informations de sortie du test de performance.

/** * @brief performance test for FIR algorithms library * @param benchmark statistics about current algorithm performance * @param memoryModel memory model architecture. Accepted values : * @li UMA_L2CACHE_L1DCACHE * @li UMA_L2SRAM_L1DCACHE * @li UMA_L2SRAM_L1DSRAM * @param output output vector to overwrite * @param fir_fct pointer to function under test */void firtest_perf( TestPerf_obj *benchmark,

uint8_t memoryModel,float * restrict output,void (*fir_fct) ( const float * restrict,

const float * restrict,float * restrict,int,int) );

• Modifier maintenant votre projet de façon à respecter l'affichage suivant.

26

Page 27: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

2.3. Temps de compilation et empreinte mémoire

Afin d'optimiser le temps de compilation de notre projet ainsi que l'empreinte mémoire du code une fois chargé en mémoire interne du processeur, nous allons appliquer une astuce excessivement simple. Cette étape peut jouer un léger rôle dans les phases de benchmarking. En effet, en minimisant l'empreinte mémoire du code, nous pouvons améliorer l'usage du cache L1P (Level 1 Cache Program), limité à 32Ko sur notre architecture. Cette partie reste non critique dans le cadre de la trame de travaux pratiques compte-tenu de l'empreinte mémoire globale du projet.

• En vous aidant du travail préparatoire, encapsuler la procédure de test de l'algorithme fir_sp entre deux directives de pré-compilation #if et #endif (printf's, test de performance et test de conformité). Nous pourrons ainsi ajouter ou retirer du code à la compilation en utilisant les macros ci-dessous présentes dans le fichier firtest.h. Dans un premier temps, nous n'utiliserons que la macro TEST_FIR_SP :

/* algorithms and memory model under test */#define TEST_FIR_SP 1#define TEST_FIR_SP_R4 0#define TEST_FIR_SP_OPT_R4 0#define TEST_FIR_ASM 0#define TEST_FIR_ASM_MANUAL 0#define TEST_FIR_ASM_PIPE 0#define TEST_FIR_ASM_R4 0#define TEST_FIR_L2SRAM_L1DCACHE 0#define TEST_FIR_L2SRAM_L1DSRAM 0#define TEST_FIR_L2SRAM_L1DIDMA 0#define TEST_FIR_L2EDMA_L1DIDMA 0

Cette technique est très couramment utilisée dans le monde de l'embarqué dès que nous avons à manipuler des bibliothèques ou outils logiciel de taille importante (bibliothèques réseau, graphique, USB, systèmes de fichiers … ou également des systèmes d'exploitation temps réel ...). En effet, par exemple nous pouvons très bien utiliser une librairie réseau offrant un très grand nombre de services (IP, ICMP, UDP, TCP, HTTP, SMTP, FTP, DNS ...) pour n'en exploiter qu'une poignée (par exemple ICMP, IP, TCP). Auquel cas, inutile d'embarquer sur le processeur tous les autres services. La bibliothèque est alors fournie avec un header incluant des macros de configuration des services strictement nécessaires. Nous pouvons ainsi, après compilation, minimiser l'empreinte mémoire globale de notre projet dans une optique de réduction des coûts liés à la technologie processeur déployée. N'oublions pas que le domaine des systèmes embarqués, contrairement au monde des ordinateurs, nous travaillons le plus souvent en milieu contraint (ressources CPU et ressources mémoire).

27

Page 28: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

2.4. Temps de programmation

Cette étape, quant à elle, est relativement importante. Nous allons effectuer un test simple afin de bien en comprendre l'importance. L'objectif premier étant de minimiser notre temps de développement global en jouant sur le temps de chargement du programme via la sonde de programmation. Rappelons également que nous utilisons la sonde de programmation XDS100, modèle bas de gamme porté directement sur la plateforme de développement. A titre indicatif, le coût moyen d'une sonde XDS560 (haut de gamme) en fonction du distributeur peut varier entre 1000€ et 2500€. De plus, si nous souhaitons l'interfacer avec l'IDE, nous devons alors payer la licence de celui-ci (1000-3000€).

• Modifier l'inclusion du fichier d'en-tête xk_sp_8Kb.h (vecteur de 8Ko soit 2048 échantillons d'entrée au format flottant simple précision IEEE754) afin d'appeler le header xk_sp_256Kb.h(vecteur de 256Ko soit 64K échantillons d'entrée au format flottant simple précision IEEE754) également présent dans le répertoire /disco/c6678/test/h/. Ce fichier a également été créé depuis l'environnement de prototypage Matlab/Simulink. Compiler puis expliquer le temps passé à attendre la fin de la programmation du processeur.

• Ajouter au projet le fichier source firtest_init.c et s'assurer de sa bonne compilation.

• Intégrer les initialisations actuellement faites au début du main dans la fonction firtest_init (TSC timer, erreur tolérée pour le test de conformité et nombre d'exécution de l'algorithme sous test) puis s'assurer de la bonne compilation et du bon fonctionnement du projet.

• Maintenant, nous n'utiliserons le vecteur d'entrée sous forme d'une allocation statique pré-initialisée, mais sous forme d'un vecteur vide initialisé au démarrage de l'application par le processeur lui-même.

En vous aidant du travail préparatoire, retirer les appels des fichiers d'en-têtes xk_sp_XXb.h du projet, déclarer une variable globale de type tableau nommée xk_sp puis assurer son initialisation depuis la fonction firtest_init. Compiler et valider graphiquement (outil Graph) la forme d'onde et échantillons du vecteur d'entrée.

#include <firtest.h>#include <a_sp.h>

/* input and ouputs vectors */float32_t xk_sp[XK_LENGTH];

Pour information, il faut savoir que dans le domaine des applications radar, les vecteurs d'entrée ontle plus souvent une taille de plusieurs Mo. Il en est de même pour le domaine du traitement d'imagepour lequel ce processeur est également spécialisé.

28

Page 29: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Voilà, à ce stade là de la trame de travaux pratiques, nous venons de terminer les phases de développement les moins intéressantes mais qui restent néanmoins nécessaires. Nous commençons à maîtriser l'environnement de développement, les procédures de test sont écrites, automatisées et intégrées au projet. Nous sommes maintenant prêt à attaquer le vif du sujet, l'optimisation d'algorithme architecture dépendante.

• Valider une dernière fois l'interface offerte par notre projet de test en respectant l'affichage ci-dessous ainsi que les règles de codage imposées :

29

Page 30: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

30

Page 31: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

PROGRAMMATION

VECTORIELLE

31

Page 32: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3. PROGRAMMATION VECTORIELLE Travail préparatoire

Les phases de développement en assembleur attaquant avant le début du

cours, vous allez devoir vous former en avance de phase afin de profiter au

mieux des séquences de cours et de travaux pratiques. Nous allons utiliser dans

un premier temps une formation industrielle proposée par Texas Instruments.

Pour ce faire, utilisez les cours en lignes en suivant le lien ci-dessous et en

respectant le séquencement suivant :

https://training.ti.com/c6000-embedded-design-workshop

Séance 2 :

Introduction to C6000 Architecture (1 of 15) - entier

C6000 Architecture (2 of 15) – début - 1h12

Séance 3 :

C6000 Architecture (2 of 15) –1h12 - fin

C6000 Optimizations - Part 1 (4 of 15) - entier

C6000 Optimizations - Part 2 (5 of 15) - entier

Bien entendu, nous vous invitons à toutes les regarder !

32

Page 33: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Travail préparatoire

Séance 2

• 1. (4,5pt) Sachant que les paramètres d'entrée de toute fonction assembleur appelée depuis un fichier source C sont respectivement passés par les registres A4, B4, A6, B6, A8 … etc sous notre chaîne de compilation et architecture, écrire en assembleur canonique C6600 (sans optimisation) le code équivalent à la fonction C canonique de filtrage fir_sp.

.global fir_sp_asm

; C prototype : match registers :;; void fir_sp_asm ( const float * restrict xk, -> A4; const float * restrict a, -> B4; float * restrict yk, -> A6; int na, -> B6; int nyk); -> A8fir_sp_asm:

; user code

B B3NOP 5

Dans un premier temps, une solution manipulant des données au format entier sur 16bits (cf. prototype donné ci-dessous et vidéos Texas Instruments, C6000 Architecture (2 of 15)) serait une bonne aide. S'aider ensuite de la documentation technique datasheet - instruction set and cpu – sprugh7 présente dans l'archive de travaux pratiques afin de réaliser la transposition au format flottant. Paradoxalement, c'est plus simple en flottant, vous le constaterez.

.global fir_q15_asm

; C prototype : match registers :;; void fir_q15_asm ( const short * restrict xk, -> A4; const short * restrict a, -> B4; short* restrict yk, -> A6; short na, -> B6; short nyk); -> A8fir_q15_asm:

; user code

B B3NOP 5

En résumant, pour ce travail préparatoire, se mettre en condition première semaine de stage 2A ou 3A. Il s'agit effectivement d'un exercice de mise en condition.

33

Page 34: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• 2. (5pt) Proposer une implémentation C pour la fonction de filtrage fir_sp_r4 effectuant un déroulement de boucle d'un facteur 4 sur les deux boucles internes de l'algorithme de filtragefir_sp. Attention, ce travail est légèrement plus complexe qu'il n'y parait !

void fir_sp_r4 ( const float * restrict xk, \const float * restrict a, \float * restrict yk, \int na, \int nyk){

int i, j;float acc1, acc2, acc3, acc4;float a0, a1, a2, a3;float xk0, xk1, xk2, xk3, xk4, xk5, xk6;

/* input array loop */for (i=0; i<nyk; i+=4) {

/* user code *//* FIR filter algorithm - dot product */for (j=0; j<na; j+=4){

/* user code */}/* user code */

}}

• 3. (0,5pt) Nous constaterons dans la suite de la trame de travaux pratiques que l'implémentation précédemment écrite est bien plus performante qu'une implémentation en C canonique standard sans déroulement de boucle. Néanmoins, quels inconvénients et limitations amènent cette implémentation ?

34

Page 35: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Travail préparatoire

Séance 3

• En s'aidant de la présentation de l'exercice 3.3. Pipeling Software Assembleur C6600, proposer une implémentation de la fonction fir_sp_asm_softPipeline

• Proposer une implémentation en assembleur C6678 de la fonction ci-dessous. La solution proposée devra utiliser les instructions vectorielles suivantes LDDW, LDNDW, DMPYSP et DADDSP.

void fir_sp_r14 ( const float * restrict xk, \const float * restrict a, \float * restrict yk, \int na, \int nyk){

int i, j;float xk0, xk1, xk2, xk3;float a0, a1, a2, a3;float acc0, acc1, acc2, acc3;

/* input array loop */for (i=0; i<nyk; i++) {

acc0 = 0.0;acc1 = 0.0;acc2 = 0.0;acc3 = 0.0;

/* FIR filter algorithm - dot product */for (j=0; j<na; j+=4){

a0 = a[j];a1 = a[j+1];a2 = a[j+2];a3 = a[j+3];

xk0 = xk[j+i];xk1 = xk[j+i+1];xk2 = xk[j+i+2];xk3 = xk[j+i+3];

acc0 += a0*xk0;acc1 += a1*xk1;acc2 += a2*xk2;acc3 += a3*xk3;

}yk[i] = acc0 + acc1 + acc2 + acc3;

}}

• En s'aidant de la documentation technique datasheet - instruction set and cpu – sprugh7 (instruction descriptions), quelles instructions vectorielles auraient pu être intéressantes dans le cadre de notre implémentation ?

35

Page 36: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3. PROGRAMMATION VECTORIELLE Travail en séance

Nous allons maintenant attaquer les premières phases d'optimisation mono-cœur architecture dépendante de notre projet (DSP C6600 de Texas Instruments). Les exercices qui suivent peuvent être découpés en trois grande parties :

• Optimisations assembleur C6600

• Optimisations en langage C

• Comparatif architectures IA-64 extensions SSE4.1

• Ajouter au répertoire logique src du projet un sous répertoire firlib puis y ajouter les sources élèves des algorithmes de filtrage à développer présents dans /disco/c6678/firlib/src/. S'assurer de la bonne compilation du projet.

36

Page 37: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3.1. Assembleur canonique C6600

• Sélectionner puis copier à la suite du main le code encapsulé entre les directives pré-processeur #if ( TEST_FIR_SP !=0 ) et #endif comprises. Modifier la section de code copiée ainsi que les commentaires afin d'assurer les tests de la fonction assembleur canonique fir_sp_asm. S'assurer de la bonne compilation du projet.

Cette étape sera à répéter durant nos développements futurs pour chaque implémentation avec optimisation. Nous pourrons ainsi nous focaliser sur les stratégies et problématiques d'optimisation et non plus sur les procédures de test et de benchmarking.

• En vous aidant du travail préparatoire, implémenter le code de la fonction fir_sp_asm puis valider son fonctionnement.

Voici ci-dessous quelques conseils afin de faciliter votre développement. Dans tous les cas, il vous faudra impérativement travailler en mode Debug. Depuis l'espace de travail CCS Debug, utiliser la fenêtre Registers afin d'observer en temps réel le contenu des registres CPU. Placer des points d'arrêts (double clic dans la fenêtre d'édition sur le numéro de la ligne souhaitée) judicieusement dans votre code puis exécuter pas à pas le programme (CCS Debug > Run > Assembly Step). Maintenant, voici comment écrire ou tester efficacement la procédure :

◦ étape n°1 : s'assurer que l'appel et le retour de la procédure se déroulent bien puis vérifier les valeurs des paramètres d'entrée de la fonction.

◦ étape n°2 : implémenter la boucle vide avec la condition de sortie associée. S'assurer du bon nombre d'itérations et du fait de quitter celle-ci.

◦ étape n°3 : dans la boucle, vérifier les premiers chargements de données de la mémoire vers le cœur ainsi que la validité des données pré-chargées.

◦ étape n°4 : écrire le code correspondant au produit scalaire dans le cœur de la boucle. Cette partie est plus complexe à tester et à valider.

◦ remarque : de façon générale, toujours tester les valeurs limites : condition de sortie de boucle, débordement de tableau, valeurs de pointeurs mémoire …

• Après validation, lancer une exécution en mode Release (mode Debug coupé et options d'optimisations levées), puis reporter les résultats des tests dans le tableau d'analyse comparative à la fin de ce support de travaux pratiques.

• Valider l'affichage de votre mesure dans la console de sortie de l'IDE

37

Page 38: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3.2. Assembleur VLIW C6600

Contrairement aux processeurs superscalaires, les architectures VLIW (Very Long Instruction Word) et EPIC (Explicitly Parallel Instruction Computing) ont pour point commun d'avoir un code out-of-order en mémoire (OOO ou dans le désordre) mais offrant une exécution in-order (exécution et sortie du pipeline dans l'ordre). Dans cet exercice, nous allons jouer sur ce point sans pour autant utiliser d'instructions vectorielles ni tenter d'avoir une utilisation optimale du pipeline. En effet, nous n'utiliserons que des instructions scalaires.

Rappelons le principe de ce type d'optimisation, uniquement applicable sur architecture CPU VLIW et EPIC. L'exemple qui suit présente un avancement de branche d'exécution sur architecture C6600. Le code est alors dans le désordre en mémoire et pourtant les deux files d'instructions ci-dessous réalisent le même traitement :

Canonical C6600 assembly instructions in-order in memory(processing time : 14 CPU cycles)

MPYSP A3,B9,A17NOP 3FADDSP A17,A5,A5

NOP 2 [A1] SUB A1,1,A1 [A1] B L2

NOP 5

VLIW C6600 assemblyinstructions out-of-order in memory

(processing time : 7 CPU cycles)

MPYSP A3,B9,A17 ; instructions bundle|| [A1] SUB A1,1,A1 [A1] B L2

NOP 2FADDSP A17,A5,A5NOP 2

• Comme pour l'algorithme fir_sp_asm, copier un bloc de code assurant les tests de conformité et de performance d'un algorithme puis le modifier de façon à obtenir une section de test pour l'algorithme fir_sp_asm_vliw.

• Implémenter le code de la fonction fir_sp_asm_vliw, effectuant une optimisation manuelle par avancement de branches d'exécution de l'algorithme fir_sp_asm puis valider son fonctionnement. Comme pour chaque phase de développement, bien travailler en mode Debug.

• Après validation, lancer une exécution en mode Release (mode Debug coupé et options d'optimisations levées), puis reporter les résultats des tests dans le tableau d'analyse comparative à la fin de ce support de travaux pratiques.

38

Page 39: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3.3. Pipelining logiciel assembleur C6600

Dans cet exercice, nous allons nous efforcer d'obtenir une utilisation optimale du pipeline logiciel pour l'algorithme écrit en assembleur canonique. Cet exercice consiste à jouer sur le nombre d'unités d'exécution du cœur en essayant d'utiliser le CPU au maximum de son potentiel théorique. Dans notre cas, chaque cœur possédant 8 unités d'exécution, toutes capables de travailler en parallèle, nous chercherons à obtenir un maximum de 8 instructions exécutées par cycle CPU. Nous allons donc nous intéresser au parallélisme d'instructions.

Pour notre algorithme, sans déroulement de boucle (vectorisation des données), le facteur optimal d'optimisation en terme d'accélération sera obtenu à travers cet exercice. Observons de façon graphique dans un tableau l'architecture du code à implémenter. Dans la table de programmation ci-dessous, vous trouverez une implémentation de la boucle interne, la boucle externe restant inchangée. Le prolog est exécuté une seule fois, la boucle kernel autant de fois qu'il y a d'itérations de boucles en retranchant la profondeur du prolog et l'epilog sera également exécuté qu'une seule fois. L'allocation des registres reste libre dans le cadre de cet exercice.

Unités d'Exécution(occupation des pipelines hardware et software)

.D1 .M1 .S1 .L1 .L2 .S2 .M2 .D2

PROLOG

LDW LDW

NOP NOP

NOP NOP

NOP NOP

NOP NOP

LDW MPYSP LDW

NOP NOP NOP

NOP NOP NOP

NOP NOP NOP

NOP NOP NOP

KERNEL

LDW MPYSP BDEC FADDSP LDW

NOP NOP NOP NOP NOP

NOP NOP NOP NOP NOP

NOP NOP NOP NOP NOP

NOP NOP NOP NOP NOP

NOP NOP NOP NOP NOP

EPILOG

MPYSP FADDSP

NOP NOP

NOP NOP

NOP NOP

FADDSP

NOP

NOP

39

Page 40: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Comme pour les algorithmes précédents, copier un bloc de code assurant les tests de conformité et de performance d'un algorithme puis le modifier de façon à obtenir une section de test pour l'algorithme fir_sp_asm_softPipeline.

• Implémenter le code de la fonction fir_sp_asm_softPipeline, effectuant la technique de pilpelining logiciel vu en cours sur l'algorithme fir_sp_asm puis valider son fonctionnement. Comme pour chaque phase de développement, bien travailler en mode Debug.

Voici ci-dessous quelques conseils afin de faciliter votre développement :

◦ étape n°1 : la profondeur de la boucle kernel interne doit posséder une taille supérieure ou égale au nombre de cycles CPU nécessaires à l'exécution de l'instruction B (branch).

◦ étape n°2 : tester la condition de sortie de la boucle ainsi que le bon nombre d'itérations.

◦ étape n°3 : vérifier les données préchargées depuis la mémoire par les instructions de chargement sur plusieurs itérations.

• Après validation, lancer une exécution en mode Release (mode Debug coupé et options d'optimisations levées), puis reporter les résultats des tests dans le tableau d'analyse comparative à la fin de ce support de travaux pratiques.

• Les NOP's (delay slot) peuvent être vus comme des espaces libres dans lesquels peuvent être insérer des instructions à exécuter en parallèle. Dans une optique de déroulement de boucle (vu dans les parties qui suivent), nous pourrons alors être amenés à charger de façon conséquente la boucle kernel actuellement sous exploitée.

• Sans nous en rendre compte, au fil des exercices en assembleur précédents et actuel nous nous efforçons d'entrer dans la tête de notre compilateur C. En effet, lorsque les options d'optimisation sont levées, il tente d'appliquer un maximum des techniques d'accélération que nous sommes en train de découvrir. Sans pour autant obtenir une implémentation optimale. Nous constaterons par la suite que si nous souhaitons obtenir des facteurs d'accélération optimaux en restant à l'étage du langage C, il nous faudra effectuer du refactoring de code ainsi qu'aiguiller au maximum la chaîne de compilation. Nous perdrons alors en portabilité de code.

40

Page 41: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3.4. Assembleur vectoriel C6600

Durant cet exercice, nous allons nous intéresser au parallélisme des données en utilisant un maximum d'instructions vectorielles SIMD (Single Instruction Multiple Data) permettant un traitement des opérandes à l'étage assembleur par vecteur de données (2, 4, 8 …) et non plus par données scalaires (une à une). De plus, ceci nous permettra de minimiser l'usage du pipeline logiciel d'instructions et donc le nombre d'unités d'exécution utilisées. Laissant ainsi la place potentielle à d'autres instructions.Prenons l'exemple d'une même section de code avec des instructions scalaires et vectorielles. Dans les deux cas, le traitement réalisé est le même :

C6600 scalars assembly instructions(processing time : 18 CPU cycles, 4 instructions)

LDW *A19++, A25NOP 4

LDW *A19++, A24NOP 4MPYSP A25, B23, B5NOP 3MPYSP A24, B22, B4NOP 3

C6600 vectorials assembly instructions(processing time : 9 CPU cycles, 2 instructions)

LDDW *A19++, A25:A24NOP 4DMPYSP A25:A24, B23:B22, B5:B4 NOP 3

• Comme pour les algorithmes précédents, copier un bloc de code assurant les tests de conformité et de performance d'un algorithme puis le modifier de façon à obtenir une section de test pour l'algorithme fir_sp_asm_r14.

41

Page 42: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Nous allons maintenant effectuer un déroulement d'un facteur 4 de la boucle interne de l'algorithme (boucle externe inchangée). Voici ci-dessous une implémentation C du code assembleur à implémenter :

void fir_sp_r14 ( const float * restrict xk, \const float * restrict a, \float * restrict yk, \int na, \int nyk){

int i, j;float xk0, xk1, xk2, xk3;float a0, a1, a2, a3;float acc0, acc1, acc2, acc3;

/* input array loop */for (i=0; i<nyk; i++) {

acc0 = 0.0;acc1 = 0.0;acc2 = 0.0;acc3 = 0.0;

/* FIR filter algorithm - dot product */for (j=0; j<na; j+=4){

a0 = a[j];a1 = a[j+1];a2 = a[j+2];a3 = a[j+3];

xk0 = xk[j+i];xk1 = xk[j+i+1];xk2 = xk[j+i+2];xk3 = xk[j+i+3];

acc0 += a0*xk0;acc1 += a1*xk1;acc2 += a2*xk2;acc3 += a3*xk3;

}yk[i] = acc0 + acc1 + acc2 + acc3;

}}

Afin d'implémenter de façon optimale cet algorithme, nous allons utiliser des instructions vectorielles. En s'aidant des annexes ou de la documentation technique SPRUGH7, se documenter surles instructions suivantes :

• LDDW• LDNDW• DMPYSP• DADDSP

42

Page 43: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• En quoi diffère l'instruction LDDW de l'instruction LDNDW ?

Il faut savoir que notre chaîne de compilation réalise par défaut, notamment sur la pile, des alignements mémoire sur les données (adresses des données multiples de N octets, 8o dans notre cas). Observons ci-dessous un exemple de défaut d'alignement mémoire et essayons de comprendre la nécessite d'aligner nos données en mémoire dans le cas d'utilisation de fonctions intrinsèques. Un alignement mémoire garanti une utilisation optimale des accès aux ressources mais ajoute néanmoins de nombreux espaces/slots vide en mémoire cache et en RAM. Dans le cas présent, cette technique accélère donc l'exécution du code mais néanmoins dégrade l'occupation des ressources mémoire. Rappelons également que le taille des chemins/paths d'un CPU vers la mémoire L1 donnée vaut 64 bits soit 8 octets sur notre architecture. Prenons ci-dessus un exemple de jeu de données, les premières non-alignées et les secondes alignées modulo 8 octets :

short foo ;float bar[3] ;

43

Page 44: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Implémenter le code de la fonction fir_sp_asm_r14, effectuant un déroulement de boucle d'un facteur 4 sur la boucle interne de l'algorithme puis valider son fonctionnement. Comme pour chaque phase de développement, bien travailler en mode Debug.

En observant le code élève fourni, nous pouvons constater un traitement étrange à l'entrée et à la sortie de la procédure (cf. ci-dessous). En vous aidant de la documentation technique SPRU187V – Optimizing Compiler, Chapter 7.3 Register Conventions, Table 7-2. Register Usage dédiée aux mécanismes d'optimisation sur architectures C6000, comprendre et expliquer le rôle des sections de code rajoutées.

save_context .macro rsp; save core working registers context on the top of stackMV B15,rsp ; save Stack PointerSTDW B15:B14,*rsp--[1]STDW B13:B12,*rsp--[1]STDW B11:B10,*rsp--[1]STDW A15:A14,*rsp--[1]STDW A13:A12,*rsp--[1]STDW A11:A10,*rsp--[1]MVC ILC,B15MVC RILC,B14STDW B15:B14,*rsp--[1]; don't use rsp register in current assembly procedure .endm

restore_context .macro rsp; restore core working registers context from the top of stackLDDW *++rsp[1],B15:B14MVC B14,RILCMVC B15,ILCLDDW *++rsp[1],A11:A10LDDW *++rsp[1],A13:A12LDDW *++rsp[1],A15:A14LDDW *++rsp[1],B11:B10LDDW *++rsp[1],B13:B12LDDW *++rsp[1],B15:B14MV rsp,B15 ; restore Stack PointerNOP 3.endm

fir_sp_asm_r14: ; save core registers contextsave_context A3

; user code

; restore core registers context and leave procedurerestore_context A3B B3NOP 5

44

Page 45: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

La directive préprocesseur assembleur .macro s'utilise comme une macro fonction en langage C (macro avec paramètres). Par exemple :

#define mul(x, y) x * y // mul(1,4) équivalent à 1*4 avant compilation

• Quelle limitation amène l'implémentation de notre algorithme de filtrage ?

• Durant l'implémentation de notre algorithme assembleur en base 4 (radix 4), quels sont les deux registres de travail du CPU que nous ne devons en aucun cas utiliser durant la totalité du traitement de la fonction ?

• Après validation, lancer une exécution en mode Release (mode Debug coupé et options d'optimisations levées), puis reporter les résultats des tests dans le tableau d'analyse comparative à la fin de ce support de travaux pratiques.

Voilà, à ce stade là de la formation en systèmes embarqués, vous devez être apte à porter un esprit critique sur les performances annoncées d'un processeur et ne plus regarder que sa seule fréquence de travail. Un processeur, même mono-cœur, cadencé à 500MHz peut très bien offrir des performances supérieures à un processeur multi-coeurs cadencé à 2GHz. Pour une architecture mono-cœur, il vous faut notamment tenir compte :

• de sa faculté à traiter des instructions en parallèle (nombre d'unités d'exécution pouvant travailler simultanément)

• de sa faculté à traiter les données par paquet (largeur des paths CPU, largeur des registres de travail et jeu d'instructions vectorielles)

• de la technologie de son pipeline matériel (superscalaire, VLIW ou EPIC), voire pour les plus curieux, des stratégies d'accélération interne au pipeline (le plus souvent aux étages de décodage et d'exécution)

45

Page 46: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3.5. Déroulement de boucle en C

A partir de maintenant et jusqu'à la fin de votre cursus, j'ai fini de vous torturer avec du développement en assembleur (en TP en tous cas). Même si ces exercices vous ont pour certains semblé inutiles, ils sont nécessaires à la compréhension fine d'une architecture matérielle donnée et des mécanismes d'accélération pouvant être utilisés. Mais se rassurer, notamment pour ceux ayant bien assimilé, en se disant que vous êtes en train de développer sur l'une des architectures de cœur pouvant être les plus complexes et performantes au monde. Tout dépend de notre degré de compréhension de l'architecture et de notre capacité à l'exploiter.

A partir de maintenant, la totalité de nos développements se feront en langage C. Nous découvrirons dans un premier temps des stratégies simples d'optimisation portables et applicables à beaucoup de processeurs vectoriels. Nous conclurons par une stratégie d'accélération optimale pour notre architecture mais amenant son lot d'inconvénients.

Le principe du déroulement de boucle consiste, sans mécanisme d'optimisation particulier, de ré-implémenter en C canonique notre algorithme en doublant/quadruplant/etc le nombre de chargement mémoire, d'opérations arithmétiques, etc dans nos boucles. Prenons un exemple de déroulement de boucle d'un facteur 2, souvent nommé unrolling radix 2 (déroulement en base 2) :

Canonical C

/* * FIR filtering function in canonical C */void fir_sp ( const float * restrict xk, \

const float * restrict a, \float * restrict pYk, \int nbCoeff){

int i;float yk_tmp = 0.0f;

/* FIR filter algorithm - dot product */for (i=0; i<nbCoeff; i++){

yk_tmp += a[i]*xk[i];}

*pYk = yk_tmp;}

Unrolling radix 2

/* * FIR filtering function with radix 2 unrolling */void fir_sp_r2 ( const float * restrict xk, \

const float * restrict a, \float * restrict pYk, \int nbCoeff){

int i;float xk_tmp1, xk_tmp2;float a_tmp1, a_tmp2;float mul1, mul2;float add1 = 0.0f, add2 = 0.0f;

/* FIR filter algorithm - dot product */for (i=0; i<nbCoeff; i+=2){

xk_tmp1 = xk[i];xk_tmp2 = xk[i+1];a_tmp1 = a[i];a_tmp2 = a[i+1];

mul1 = a_tmp1 * xk_tmp1;mul2 = a_tmp2 * xk_tmp2;

add1 += mul1;add2 += mul2;

}*pYk = add1 + add2;

}

46

Page 47: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Quelle limitation amène l'implémentation en base 2 ci-dessus ?

• Comme pour les algorithmes précédents, copier un bloc de code assurant les tests de conformité et de performance d'un algorithme puis le modifier de façon à obtenir une section de test pour l'algorithme fir_sp_r4.

• En vous aidant du travail préparatoire, implémenter le code de la fonction fir_sp_r4, effectuant un déroulement de boucle d'un facteur 4 sur les deux boucles internes de l'algorithme puis valider son fonctionnement. Comme pour chaque phase de développement, bien travailler en mode Debug.

• Après validation, lancer une exécution en mode Release (mode Debug coupé et options d'optimisations levées), puis reporter les résultats des tests dans le tableau d'analyse comparative à la fin de ce support de travaux pratiques.

47

Page 48: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3.6. Vectorisation de code en C

Dans cette ultime phase d'optimisation, nous allons réutiliser la totalité de nos anciens acquis afin d'obtenir, enfin, une implémentation optimale de notre algorithme de filtrage. Nous allons comprendre que les étapes précédentes, même si contre-performantes au seul regard des benchmarking, étaient nécessaires à une bonne compréhension des stratégies présentées ci-dessous.Afin, d'exploiter au mieux l'architecture matérielle parallèle, vectorielle, VLIW de chaque cœur, sans pour autant descendre à l'étage assembleur qui peut être très chronophage en temps de développement, nous allons devoir aiguiller au maximum notre chaîne de compilation en effectuant du refactoring de code. Découvrons quelques une des techniques les plus efficaces. Pour maîtriser la totalité du potentiel d'optimisation de notre chaîne de compilation, se référer au manuel SPRU187V – Optimizing Compiler proposé par Texas Instruments :

Examples of C intrinsics functionsfor C6600 compiler and architecture

C6600 assembly equivalence(automatics registers allocations by compiler)

__float2_t data10 ; // __float2_t container typeconst float ldData[2] = {0.0f,1.0f};data10 = _amemd8_const(&ldData[0]);

; data10 = A1:A0 ; &ldData[0] = ldData = A2LDDW *A2, A1:A0

__float2_t data10, data32 ;__float2_t result31_20 ;result31_20 = _daddsp(data10, data32);

; data10 = A1:A0, data32 = A3:A2,; result31_20 = A11:A10DADDSP A1:A0, A3:A2, A11:A10

__float2_t data10, data32 ;__float2_t result31_20 ;result31_20 = _dmpysp(data10, data32);

; data10 = A1:A0, data32 = A3:A2,; result31_20 = A11:A10DMPYSP A1:A0, A3:A2, A11:A10

__float2_t data10, data32 ;__float2_t data21 ;data21 = _ftod(_lof(data32), _hif(data10));

; data32 = A3:A2, data10 = A1:A0, data21= A11:A10MV A2, A11MV A1, A10

__float2_t data10 ;float stData[2] ;_amemd8(&stData[0]) = data10 ;

; data10 = A1:A0 ; &stData[0] = stData = A2STDW A1:A0, *A2

Les Fonctions intrinsèques ou intrinsics sont dépendantes de l'architecture cible. D'une architecture CPU et donc d'une chaîne de compilation à une autre, la prise en main de la nouvelle API est nécessaire. A l'image d'une fonction inline, une fonction intrinsèque force le compilateur à générer automatiquement une séquence d'instructions. Cependant, contrairement aux fonctions inlines, le compilateur possède une connaissance poussée de la fonction intrinsèque qui lui assure une insertion optimale pour un contexte donné. Dans notre cas, toutes les fonctions intrinsèques supportées conjointement par notre chaîne de compilation et notre architecture CPU sont énumérées dans la documentation technique

SPRU187V – Optimizing Compiler, Chapter 7.5.6 Using Intrinsics to Access Assembly Language Statements

48

Page 49: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Observons un exemple de comparaison entre une implémentation C canonique et une solution avec fonctions intrinsèques. __float2_t est un type conteneur (container type) sur 64bits et pouvant contenir 2 flottants en simple précision sur 32 bits :

Canonical C example Example of C intrinsic function

float data[2] = {0.0f, 1.0f};float data0, data1 ;

data0 = data[0]; // LDW assembly instructiondata1 = data[1]; // LDW assembly instruction

const float data[2] = {0.0f, 1.0f};__float2_t data10 ; // __float2_t container type

// LDDW assembly instructiondata10 = _amemd8_const(&data[0]);

• Assertion : l'objectif de cette technique est de donner un maximum d'informations (garanties par le développeur) sur une variable à la chaîne de compilation afin de l'aiguiller dans ses phases d'optimisation futures : valeur minimale, variable d'une valeur toujours multiple d'une autre valeur, alignement mémoire de données pointées …

Example of program with assertions Description

short i , size=4;const float data[4] = {0.0f, 1.0f, 2.0f, 3.0f} ;__float2_t acc = 0.0f ; // __float2_t container type

#pragma DATA_ALIGN(data, 8);

_nassert(size >= 2);_nassert (size % 2 == 0);_nassert((int) data % 8 == 0);

for (i=0; i<size; i+=2) { acc =_daddsp (acc, _amemd8_const(&data[i]);}

• Force l'éditeur de lien (linker) à aligner en mémoire les données du tableau data[] modulo 8 octets

• i est forcément supérieur ou égale à 2• i est forcément un multiple de 2• Les données pointées par a sont alignées

module 8 octets

• Alignement mémoire : dans l'exemple ci-dessus, la directive de compilation #pragma DATA_ALIGN force l'éditeur de lien ou linker à garantir un alignement mémoire modulo 8 octets des données visées par le pointeur passé en argument. Prenons un exemple d'alignement mémoire de données modulo 8 octets sur chaîne de compilation :

/* arrays alignments - CPU data path length 64bits */#pragma DATA_ALIGN(xk_sp, 8);

• Dans l'exemple de code avec assertions et alignement mémoire ci-dessus, que vaut la variable de type conteneur acc après exécution de la boucle ?

49

Page 50: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Comme pour les algorithmes précédent, copier un bloc de code assurant les tests de conformité et de performance d'un algorithme puis le modifier de façon à obtenir une section de test pour l'algorithme fir_sp_opt_r4.

• En vous aidant des conseils précédemment présentés, implémenter le code de la fonction fir_sp_opt_r4, effectuant un déroulement de boucle d'un facteur 4 sur les deux boucles internes de l'algorithme et utilisant les directives de compilation précédemment citées. Valider son fonctionnement en mode Debug.

• Après validation, lancer une exécution en mode Release (mode Debug coupé et options d'optimisations levées), puis reporter les résultats des tests dans le tableau d'analyse comparative à la fin de ce support de travaux pratiques.

• En vous aidant de l'annexe 1, création de projet, générer une bibliothèque statique nommée firlib.lib et la placer dans le répertoire /disco/c6678/firlib/lib/.

• Voilà, à ce stade nous venons d'effectuer une implémentation optimale de notre algorithme pour notre architecture. Porter un regard critique sur nos développements et citer les avantages et inconvénients de l'algorithme final

• L'exécution de l'algorithme tel qu'il a été écrit mathématiquement dans sa forme initiale ne peut pas être plus accélérée dans une optique de vectorisation en C sur notre architecture. Si nous souhaitons améliorer le temps de calcul de notre produit scalaire, il nous faudrait alors réduire sa complexité Mathématique en nombre de MACS. Les transformations à apporter ne seraient donc plus d'ordres technologiques dans un premier temps, mais d'ordre mathématique. Une fois ces transformations appliquées, nous pourrions alors repasser sur des phases d'optimisation architectures dépendantes telles que celles présentées dans cette partie.

• De plus, nous venons de le constater, du moment que nous avons une connaissance pousséede l'architecture, du jeu d'instructions et de notre chaîne de compilation, développer des bibliothèques spécialisées en assembleur peut s'avérer contre-productif au regard du ratio performance/effort. Ceci sera vrai sur toute architecture VLIW, EPIC et superscalaire, du moment que l'étage d'optimisation de la toolchain reste un minimum performant.

50

Page 51: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3.7. C canonique sur architecture IA-64

Dans cette dernière partie, nous allons effectuer un benchmarking entre architectures processeurs en mettant en opposition une architecture superscalaire GPP (General Purpose Processor) Intel corei7 en micro-architecture Haswell cadencée à 3,6GHz (machines de TP) et notre architecture DSP VLIW C6600 cadencée à 1,4GHz proposée par Texas Instruments. Notre première comparaison se fera sur une implémentation en C canonique.

Intel corei7 - 4790 Haswell 4th gen Texas Instruments TMS320C66783,6GHz, 105W en charge 1,4GHz, 10W en charge

prix unitaire : 325€ prix unitaire : 240€ (160€ pour 1Ku)

• Sauvegarder sur clé USB les fichiers fir_sp.c, fir_sp_r4.c et firtest_sys.c (ou directement le répertoire de travail dsp) puis démarrer une session sous GNU\Linux (Ubuntu). Si nécessaire, télécharger à nouveau l'archive dsp depuis la plateforme d'enseignement.

• Copier les fichiers fir_sp.c et fir_sp_r4 dans le répertoire /disco/ia64/firlib/src/ .

• Copier le fichier firtest_sys.c dans le répertoire /disco/ia64/test/src/ .

• Ouvrir un shell, se placer dans le répertoire de travail /disco/ia64/ (IA-64 ou Intel Architecture64bits), ouvrir le fichier README.txt puis lancer la commande de compilation depuis le répertoire courant. Interpréter et commenter la commande.

gcc -Wall -march=native -std=c99 -I./test/h -I./firlib/h -o3 ./test/src/firtest_main.c ./test/src/firtest_sys.c ./firlib/src/fir_sp.c ./firlib/src/fir_sp_r4.c ./firlib/src/fir_sp_sse_r4.c -o ./build/bin/firtest -lm

• Après compilation, exécuter le fichier binaire de sortie et analyser les résultats obtenus. De même, prenez le temps d'observer les quelques modifications mineures appliquées aux différents fichiers sources et fichiers d'en-têtes du projet (firlib.h, firtest.h, firtest_main.c).

Nous pouvons constater qu'une implémentation en C canonique, dans notre cas respectant le standard C99, garantit une portabilité du code, même sur des architectures matérielles différentes.

51

Page 52: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Dans le fichier firtest_main.c, nous pouvons observer la définition d'une fonction inline, dans notre cas implémentée en assembleur 64bits x64. Cette fonction force le CPU courant à vider son pipeline matériel puis réalise une lecture de la valeur courante du core timer TSC, comme précédemment sur architecture C6600. Sur architectures compatibles x86-x64, ce timer 64bitsest démarré à la mise sous tension de la machine et compte jusqu'à débordement. En vous aidant d'internet, rappeler le rôle du spécificateur inline, préciser l'intérêt et donner des exemples d'utilisation.

/* * flush pipeline and read current TSC value */inline unsigned long long __attribute__((always_inline)) rdtsc_inline() {

unsigned int hi, lo;__asm__ __volatile__(

// flush core pipeline"xorl %%eax, %%eax\n\t""cpuid\n\t"// read current TSC value"rdtsc"

: "=a"(lo), "=d"(hi): // no parameters: "rbx", "rcx");

return ((unsigned long long)hi << 32ull) | (unsigned long long)lo;}

• Quelles sont les principales différences entre une fonction inline et un fonction intrinsèque ?

• Répéter plusieurs exécutions successives du programme de test. Que constatons-nous ?

• Après une dizaine d'exécutions, reporter les valeurs maximales obtenues dans le tableau d'analyses comparatives présent en fin de cette trame de travaux pratiques. Dans un contexteréel, répéter une centaine d'exécution en chargeant notamment le cœur hyper-threadé par unautre applicatif offrirait un résultat plus significatif.

Nous venons d'observer l'un des principal problème des processeurs superscalaires (GPP/SoC/AP), leur déterminisme. En effet, contrairement aux architectures VLIW ou aux CPU à pipeline in-order classique présents sur MCU/GPU/DSP, la complexité matérielle des pipelines superscalaires amène un non-déterminisme relatif à l'exécution (dépendant de l'application ou de l'algorithme en cours de test). Ceci peut devenir gênant dans des applications temps réel où le déterminisme est le maîtremot. Néanmoins, les processeurs généralistes (essentiellement architectures x64 et ARM cortex-A) restent très utilisés dans les domaines du traitement du signal, essentiellement de part le culture des développeur et l'emprise de certains acteurs sur le marché (Intel, ARM, AMD).

52

Page 53: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

3.8. Vectorisation SSE4.1 sur architecture IA-64

Dans cette ultime partie, nous allons comparer ce qui peut être comparable, à savoir les performances de notre code vectorisé sur architecture C6600 à du code vectorisé sur architecture IA-64. Nous nous intéresserons notamment à l'extension vectorielle SIMD SSE4.1 proposée par Intel. Pour information, courant 2014, Intel proposa sur sa micro-architecture Haswell une extension DSP (Digital Signal Processing). Cette extension, nommée FMA (Fused Multiply-Add), est donc dédiée aux applications de traitement numérique du signal mais ne sera néanmoins pas abordée en travaux pratiques. Pour les plus curieux, ne pas hésiter à aller voir sur MSDN (MicroSoft Developer Network) les quelques fonctions intrinsèques proposées.

Dans cette partie, il est bien entendu hors de question de découvrir en profondeur l'architecture interne des processeurs compatibles x64 (Intel, AMD ...), notamment les architectures Intel. Néanmoins, nous allons pouvoir constater que nos précédents acquis nous permettent maintenant d'effectuer de la vectorisation de code sur toute architecture vectorielle processeur. Les concepts resteront le plus souvent les mêmes.

Avant tout, il faut savoir que les architectures x64 actuelles possèdent plusieurs banques de registres vectoriels :

• registres MMX 64bits : peut par exemple contenir 2 flottants 32bits• registres XMM 128bits : peut par exemple contenir 4 flottants 32bits• registres YMM 256bits: peut par exemple contenir 8 flottants 32bits

Dans notre cas, les instructions de l'extension SSE4.1 travaillent avec les registres XMM 128bits et sont aptes à manipuler les flottants en simple précision (IEEE754) par paquets de 4. Observons le pré-fixage et su-fixage des fonctions intrinsèques ainsi que l'un des types conteneurs associé. Le type __m128 peut donc contenir 4 flottants simple précision :

Intrinsic syntax : _mm_<intrinsic_name>_<data_type>container type (4 x 32bits floating point) : __m128

https://msdn.microsoft.com/fr-fr/library/y0dh78ez(v=vs.90).aspx

• Mise à zéro des éléments d'un vecteur de flottants. Pour information, ps signifie Packet Single,soit paquet de flottants en simple précision 32bits IEEE754 :

__m128 float_vector ; float_vector = _mm_setzero_ps ();

https://msdn.microsoft.com/fr-fr/library/tk1t2tbz(v=VS.90).aspx

53

Page 54: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Initialise les éléments d'un vecteur de flottants :

__m128 float_vector ; float_vector = _mm_set_ps (1.0, 2.2, 3.0, 7.0);

https://msdn.microsoft.com/fr-fr/library/afh0zf75(v=vs.90).aspx

• Chargement d'un vecteur de 4 flottants alignés depuis la mémoire vers un registre XMM dedestination :

float tab[4] = {1.0, 3.4, 5.0, 6.0} ;__m128 float_vector ; float_vector = _mm_load_ps (&tab[0]);

https://msdn.microsoft.com/fr-fr/library/zzd50xxt(v=vs.90).aspx

• Chargement d'un vecteur de 4 flottants non-alignés depuis la mémoire vers un registre XMM de destination :

float tab[4] = {1.0, 3.4, 5.0, 6.0} ;__m128 float_vector ; float_vector = _mm_loadu_ps (&tab[0]);

https://msdn.microsoft.com/fr-fr/library/x1b16s7z(v=vs.90).aspx

• Produit scalaire entre deux vecteurs de 4 flottants (result = a0.x0 + a1.x1 + a2.x2 + a3.x3). Le résultat du produit scalaire étant donc un nombre scalaire, le résultat est par défaut sauvé dans les 32bits de poids faibles du vecteur de destination :

__m128 float_vector_src1;__m128 float_vector_src2;__m128 float_vector_dst;float_vector_dst = _mm_dp_ps (float_vector_src1, float_vector_src2, 0xff);

https://msdn.microsoft.com/fr-fr/library/bb514054(v=vs.90).aspx

• Addition de deux vecteurs de 4 flottants :

__m128 float_vector_src1;__m128 float_vector_src2;__m128 float_vector_dst; float_vector = _mm_add_ps (float_vector_src1, float_vector_src2);

https://msdn.microsoft.com/fr-fr/library/c9848chc(v=vs.90).aspx

54

Page 55: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Sauvegarde en mémoire d'un vecteur de 4 flottants alignés :

float tab[4];__m128 float_vector ;float_vector = _mm_set_ps (1.0, 2.2, 3.0, 7.0);_mm_store_ps (&tab[0], float_vector);

https://msdn.microsoft.com/fr-fr/library/s3h4ay6y(v=vs.90).aspx

• Ouvrir le fichier /disco/ia64/firlib/h/firlib.h et observer les déclarations de type et d'union présentées ci-dessous. Cette union, greffée à une déclaration de type, permet, après déclaration d'une variable conteneur, d'accéder à un vecteur XMM soit élément par élément, soit directement au vecteur 128bits complet. En vous aidant d'internet, rappeler ce qu'est uneunion et préciser la différence avec une structure.

/* project specific types */union xmm_t {

__m128 m128_vec; // full access to XMM vector float m128_f32[4]; // access to XMM vector elements

} align16_xmm;typedef union xmm_t xmm_t;

• Dans l'exemple ci-dessous, comment accéder au 3ième élément de la variable data_vec de type conteneur XMM 128bits.

xmm_t data_vec;

55

Page 56: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Ouvrir le fichier /disco/ia64/firlib/src/fir_sp_sse_r4.c puis implémenter le code vectorisé pour architecture x64 correspondant à la fonction fir_sp_r4. Valider son bon fonctionnement sans oublier de s'assurer de l'alignement mémoire des différents vecteurs de données traités par l'algorithme.

• Répéter plusieurs exécutions puis reporter les valeurs maximales obtenues dans le tableau d'analyses comparatives présent en fin de cette trame de travaux pratiques.

• Nous venons d'effectuer de la vectorisation de code tout en ayant une connaissance minimede l'architecture processeur Intel. Une connaissance plus poussée de l'architecture et du jeu d'instructions supporté permettrait un gain supplémentaire en performance, sans pour autant être conséquente (extensions FMA3, FMA4 ...).

• De même, nous avons effectué nos compilations sous gcc (GNU Collection Compiler). Si nous souhaitons gagner en performance, il serait alors intéressant de travailler directement avec les outils fondeurs. Par exemple, si nous souhaitons garantir des performances optimales sur architecture Intel, il nous faudrait alors utiliser icc (Intel C++ Compiler) un compilateur développé par Intel et donc optimisé pour leurs architectures. Il en va de mêmepour tous les fondeurs du marché (Texas Instruments, ARM, MIPS ...).

56

Page 57: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Nous venons de conclure la partie vectorisation monocœur de code et nous allons essayer de synthétiser et d'analyser nos précédents résultats.

• Choix d'une architecture CPU et d'une famille de processeurs :

◦ pipeline in-order classique : faible consommation, faible performance, faible empreinte silicium, sauf si intégrés par milliers, prenons l'exemple des GPU. Applications sans OS (Operating System), avec petits exécutifs ou systèmes d'exploitation temps réel (Real Time Operating System). Dans le cas des GPU, applications de calcul massivement parallèle (traitement d'image, vidéo, graphique 3D, matriciel …). Il s'agit des architectures CPU les plus rencontrées en terme de volumes autour de nous, notamment grâce au marché des MCU (MCU STM32 STMicroelectronics, MCU PIC Microchip, Intel 8051, ARM Cortex-M ...)

◦ pipeline superscalaire : grande polyvalence (généraliste), le plus souvent grande puissancede calcul, pipeline complexe, donc forte intelligence déportée dans chaque cœur avec un faible niveau de parallélisme (typiquement 1, 2, 4, 8 cœurs vectoriels) : prédiction au branchement, étage d'exécution out-of-order, étage de retirement, étage de renommage des registres, mécanismes d'accélération aux étages de décodage et d'exécution le plus souvent, unités d'exécutions vectorielles … Applications avec OS lourds. Architectures pensées pour exécuter du code faiblement optimisé notamment avec beaucoup de branchements, le cœur se charge du reste. Cependant, dû à la complexité du pipeline, ces architectures peuvent offrir quelques irrégularités au regard du déterminisme à l'exécution (x86, x64, ARM cortex-A, IBM/APPLE/Freescale PowerPC, MIPS Aptiv…). Rapport performance (parallélisme)/consommation faiblement intéressant.

◦ Pipeline VLIW/EPIC : forte puissance de calcul, pipeline relativement simple en opposition aux architectures superscalaires, donc rapport performance (parallélisme)/consommation intéressant (intelligence déportée vers le développeur et la toolchain), grand déterminisme. Néanmoins, développements dépendants de l'architecture nécessaires, problèmes de portabilité de code. Rétrocompatibilité au niveau binaire difficile à suivre pour les fondeurs (DSP TI C6000, NXP TriMedia, DSP SHARC Analog Device, ST200 STMicroelectronics, Intel Itanium ...).

• Langage C vs Assembleur : dans une optique d'optimisation, un développement en langage C avec une bonne connaissance de l'architecture matérielle, du jeu d'instructions et des mécanismes d'optimisation de la toolchain peut éviter un passage à l'étage assembleur à notre époque (intrinsics, directives de compilation …) et donc accélérer le TTM du produit (Time To Market).

• Tests : ne pas négliger les procédures de test (conformité et performance), notamment dans une optique de benchmarking et d'optimisation d'algorithmes.

• processeurs superscalaires : intelligence déportée dans le cœur

• processeurs VLIW et EPIC : intelligence et compétences déportées dans le développeur et la chaîne de compilation

57

Page 58: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Dernière information, le processeur utilisé en travaux pratiques fait parti de la famille Keystone I proposée par Texas Instruments (http://processors.wiki.ti.com/index.php/Multicore). TI propose également la famille Keystone II. Il s'agit de SoC (System On Chip) intégrant 8 cœurs DSP VLIW C6600 et jusqu'à 4 cœurs ARM Cortex-A15 superscalaires afin d'embarquer un voire plusieurs systèmes d'exploitation avancés (Typiquement GNU\Linux). Cette architecture offre alors une grande flexibilité ainsi qu'une forte puissance de calcul. Néanmoins, avec la consommation et le coût qui l'accompagne.

Famille Keystone I, processeur C6678

Famille Keystone II, processeur 66AK2H14

58

Page 59: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

59

Page 60: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

HIERARCHIE MEMOIRE

60

Page 61: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

4. HIERARCHIE MEMOIRE Travail préparatoire

• 1. (1,5pt) Rappeler le principe de fonctionnement et l'usage fait du cache processeur par un CPU.

• 2. (0,5pt) Qu'est-ce-qu'une ligne de cache ?

• 3. (1,5pt) Comme pour beaucoup d'architectures actuelles, la famille DSP C6000 utilise une politique de remplacement de ligne de cache du type LRU (Least Recently Used). Que cela signifie-t-il ? Illustrer votre réponse à l'aide d'un schéma.

• 4. (1,5pt) En s'aidant de l'annexe ou de la documentation technique SPRS691E, quel intérêt pouvons-nous avoir à utiliser un ou plusieurs niveaux mémoire (L1/L2/L3) configurés en SRAMet non en cache ? Quelles différences majeures rencontrons-nous à l'usage ?

61

Page 62: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• 5. (5pt) Nous pouvons observer ci-dessous une implémentation en pseudo-code Matlab d'uneémulation de transferts mémoire de DDR vers L2 SRAM. Bien entendu, sous Matlab, la notion de hiérarchie n'a aucun sens, cette implémentation nous permet seulement de valider les tailles des vecteurs intermédiaires de stockage ainsi que les valeurs limites des boucles. Proposer une implémentation C en utilisant la fonction standard memcpy afin d'effectuer les transferts mémoire :

DDR_ARRAY_LENGTH = 65536; % 64K/256Kb : array length in DDRL2_ARRAY_LENGTH = 32768; % 32K/128Kb : array length in L2 SRAMA_LENGTH = length(a_sp); % 64/256b : length of coefficients arrayYK_LENGTH = DDR_ARRAY_LENGTH - A_LENGTH + 1; % length of output temporal array in DDR

%*** MEMORY TRANSFERS% floating point arrays lengths :% xk_sp_DDR |---------------------- 256Kb or 4Mb --------------------------|% xk_sp_L2 |------------- 128Kb + 256b - 4 -------------| overlap % a_sp_L1 |- 256b -|% yk_sp_L2 |------------- 128Kb -------------|% yk_sp_DDR |------------- (256Kb or 4Mb) - 256b + 4 ----------------|%% copy part of input array from DDR to L2 SRAM

for k=1 : A_LENGTH a_sp_L1(k) = a_sp(k); end

for i=1 : L2_ARRAY_LENGTH : DDR_ARRAY_LENGTH % memory copy DDR to L2 SRAM % rq : DDR_ARRAY_LENGTH % L2_ARRAY_LENGTH = 0 if i < DDR_ARRAY_LENGTH - L2_ARRAY_LENGTH for k=1 : L2_ARRAY_LENGTH + A_LENGTH - 1 xk_sp_L2(k) = xk_sp_DDR(i+k-1); end else for k=1 : L2_ARRAY_LENGTH xk_sp_L2(k) = xk_sp_DDR(i+k-1); end end % FIR filtering - algorithm working with L1D cache yk_sp_L2 = fir_sp(xk_sp_L2, a_sp_L1, A_LENGTH, L2_ARRAY_LENGTH); % memory copy L2 SRAM to DDR - coherency of output DDR array % rq : YK_LENGTH % L2_ARRAY_LENGTH = L2_ARRAY_LENGTH - A_LENGTH + 1 if i < YK_LENGTH - L2_ARRAY_LENGTH for k=1 : L2_ARRAY_LENGTH yk_sp_DDR(i+k-1) = yk_sp_L2(k); end else for k=1 : L2_ARRAY_LENGTH - A_LENGTH + 1 yk_sp_DDR(i+k-1) = yk_sp_L2(k); end end end

62

Page 63: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

4. HIERARCHIE MEMOIRE Travail en séance

Nous allons maintenant chercher à passer outre les mémoires caches L1D et L2 en ne configurant qu'une partie des niveaux L1D et L2 en cache et le reste en mémoires SRAM adressable par octet.

Dans l'exemple d'un produit scalaire, l'impact restera minime. Néanmoins, pour grand nombred'algorithmes du traitement numérique du signal (traitement d'image, traitement d'antenne ...), laisser opérer les contrôleurs cache sans ordonnancement des données avant traitement peut avoir une incidence énorme sur le temps d'exécution. Dans l'exemple qui suit, nous pouvons observer une matrice de données manipulée par indexage (chargement/lecture donnée 1 puis 2 puis 3 …) :

63

Page 64: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Un cache étant chargé par ligne (principe de localité spatiale), nous sommes alors amenés à charger un grand nombre de données ''potentiellement'' inutilisées en cache. Une technique couramment utilisée, consiste à ré-implémenter l'algorithme de façon à traiter des données pré-ordonnancées en mémoire (technique du corner turn). Cette stratégie permet de diminuer le nombred'accès au cache et assure une utilisation optimale des espaces de stockage en cache. Rappelons que l'accès aux ressources en mémoire est l'un des principal goulot d'étranglement à notre époque. Nous avons également remarqué que notre architecture possède un grand nombre de registres de travail généralistes. L'objectif étant de charger les données locales à une fonction ou une boucle dans les registres du cœur, pour les traiter par la suite en minimisant au plus les aller/retour vers le cache. Écritures différées en mémoire en fin de traitement.

Dans notre cas, l'objectif est différent. L'algorithme d'un produit scalaire sans transformations mathématiques dans une optique de diminution de sa complexité, manipule les vecteurs d'entrée dans l'ordre de façon séquentielle. Cet exercice n'a donc pour objectif que d'illustrer la possibilité d'obtenir un espace de stockage adressable à accès rapide physiquement proche du cœur (L1D et L2).Nous maîtriserons alors avec certitude les données présentes aux niveaux L1D et L2 afin de garantirun déterminisme à l'exécution. Cette solution permet par exemple de s'affranchir localement du principe de corner turn précédemment présenté. En effet, nous allons manuellement effectuer le travail des contrôleurs de cache utilisant quant à eux des mécanismes de localité temporelle (LRU) pour leurs allocations/libérations mémoire. Traitement impossible sur processeur généraliste GPP. Ceci permettra de rendre notre algorithmique quasiment insensible à la charge éventuelle du cache.

64

Page 65: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

4.1. Mémoire locale adressable

Nous avons possibilité de configurer les différents niveaux mémoire en cache ou en SRAM adressable de façon statique à la compilation ou dynamique à l'exécution. Étudions l'approche statique. Rappelons avant tout l'architecture mémoire de notre processeur :

• Dans notre projet CCS, remplacer le script C6678_unified.cmd par le fichier /disco/c6678/test/map/C6678_unified_fir_pjct.cmd

Le fichier .cmd est utilisé par le linker afin fixer les localisations mémoire des principaux segments (tas/heap, pile/stack et sections statiques) du projet. Sans pour autant figer les adresses mémoire (rôle de linker, résolution des liens symboliques avec la mémoire), nous pouvons fixer leur localisation dans l'architecture (DDR3 SRAM, MSM SRAM, L2 SRAM ou L1D/P SRAM).

65

Page 66: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Éditer le fichier /disco/c6678/test/map/C6678_unified_fir_pjct.cmd et analyser son contenu.

-stack 0x2000-heap 0x2000

MEMORY{ LOCAL_L1P_SRAM: origin = 0x00E00000 length = 0x00008000 /* 32kB LOCAL L1P/SRAM */ LOCAL_L1D_SRAM: origin = 0x00F00000 length = 0x00008000 /* 32kB LOCAL L1D/SRAM */ LOCAL_L2_SRAM: origin = 0x00800000 length = 0x00080000 /* 512kB LOCAL L2/SRAM */ MSMCSRAM: origin = 0x0C000000 length = 0x00400000 /* 4MB Multicore shared Memmory */ EMIF16_CS2: origin = 0x70000000 length = 0x04000000 /* 64MB EMIF16 CS2 Data Memory */ EMIF16_CS3: origin = 0x74000000 length = 0x04000000 /* 64MB EMIF16 CS3 Data Memory */ EMIF16_CS4: origin = 0x78000000 length = 0x04000000 /* 64MB EMIF16 CS4 Data Memory */ EMIF16_CS5: origin = 0x7C000000 length = 0x04000000 /* 64MB EMIF16 CS5 Data Memory */

/* TMDSEVM6678L board specific */ DDR3: origin = 0x80000000 length = 0x20000000 /* 512MB external DDR3 SDRAM */ } SECTIONS{

.text > MSMCSRAM

.stack > MSMCSRAM

.bss > MSMCSRAM

.cio > MSMCSRAM

.const > MSMCSRAM

.data > MSMCSRAM

.switch > MSMCSRAM

.sysmem > MSMCSRAM

.far > DDR3

.args > MSMCSRAM

.ppinfo > MSMCSRAM

.ppdata > MSMCSRAM

/* COFF sections */.pinit > MSMCSRAM.cinit > DDR3

/* EABI sections */.binit > MSMCSRAM.init_array > MSMCSRAM.neardata > MSMCSRAM.fardata > DDR3.rodata > MSMCSRAM.c6xabi.exidx > MSMCSRAM.c6xabi.extab > MSMCSRAM

/* project specific sections */

/* user sections */}

66

Page 67: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• A quoi correspond la zone MEMORY du script ?

• En vous aidant de l'annexe ou de la documentation technique SPRU187V, préciser le rôle de lazone SECTIONS du script.

• Dans quelle section est rangée la pile ou stack système (allocations automatiques) ?

• Dans quelle section est rangée le tas ou heap système (allocations dynamiques) ?

• Dans quelle section est rangé le code utilisateur ?

• Modifier le script de façon à configurer à la compilation les niveaux mémoire L1D et L2 comme suit :

◦ 32Ko L1D : 28Ko en L1D SRAM adressable et 4Ko en L1D cache

◦ 512Ko L2 : 480Ko en L2 SRAM adressable et 32Ko en L2 cache

• Créer 3 nouvelles sections propres au projet et les placer tel que précisé ci-dessous :

◦ .ddrsdram : section statique présente en DDR

◦ .l2sram : section statique présente en L2 SRAM

◦ .l1dsram : section statique présente en L1D SRAM

• Compiler puis exécuter le programme. Valider son bon fonctionnement.

67

Page 68: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Dans les langages compilés comme le langage C, une donnée est soit allouée statiquement à la compilation soit allouée dynamiquement/automatiquement à l'exécution. Par essence, les langagesinterprétés ne peuvent qu'allouer des ressources durant l'exécution (allocations dynamiques) :

• Allocations statiques : allocations à la compilation et structuration des familles de variables en sections par l'éditeur de liens (variables globales ou statiques initialisées,non-initialisées , constantes …). Exemples de sections :

• .data : section mémoire où se situe les données statiques initialisées• .bss : section mémoire où se situe les données statiques non initialisées• .rodata : données statiques initialisées en lecture seule (read-only)

• Allocations automatiques : allocations/dés-allocations à l'exécution sur la pile ou stack (variables locales, paramètres de fonctions, adresses de retour des fonctions)

• Allocations dynamiques : allocations/dés-allocations à l'exécution sur le tas ou heap (malloc, realloc, free ... et variantes). Attention à l'utilisation des fonctions malloc et surtout free d'allocation dynamiques de ressources sur processeur ne possédant pas de PMMU (Paged Memory Managment Unit). Ce qui est notre cas. En effet, l'allocation dynamique de ressources amène une fragmentation logique de la mémoire physique, palliée par l'unité de pagination sur processeur superscalaire généraliste (GPP et AP) possédant tous une MMU.

68

Page 69: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

4.2. Préchargement des données de DDR SRAM vers L2 SRAM

• Déclarer des vecteurs statiques (variables globales) qui assureront des stockages partiels de nos vecteurs d'entrée et de sortie. Ces vecteurs stockeront temporairement en L2 SRAM et L1D SRAM des morceaux de vecteurs à traiter. Respecter les dénominations imposées dans le fichier d'en-tête firtest.h :

/* arrays allocations (bytes) :* xk_sp (DDR) |------------------------- 256Kb or 4Mb --------------------------|* xk_sp_l2 |------------- 128Kb + 256b - 4 -------------| overlop* xk_sp_l1d |--- 8Kb + 256b - 4 ---| overlop* a_sp_l1d |- 256b -|* yk_sp_l1d |----- 8Kb -----|* yk_sp_l2 |------------- 128Kb -------------|* yk_sp (DDR) |------------------- (256Kb or 4Mb) - 256b + 4 -------------------|*/float32_t xk_sp_l2 [L2_ARRAY_LENGTH + A_LENGTH - 1];float32_t yk_sp_l2 [L2_ARRAY_LENGTH];float32_t xk_sp_l1d [L1D_ARRAY_LENGTH + A_LENGTH - 1];float32_t yk_sp_l1d [L1D_ARRAY_LENGTH];float32_t a_sp_l1d [A_LENGTH];

• En modifiant le script linker, nous venons de customiser l'organisation mémoire de notre architecture afin de l'adapter aux besoins de notre projet. En utilisant la directive d'édition desliens #pragma DATA_SECTION, placer les précédentes déclarations dans les sections concernées. Les vecteurs d'entrée et de sortie xk_sp, yk_sp, a_sp et yk_sp_ti seront quant à eux placés en DDR SRAM externe. Ne pas oublier d'assurer un alignement mémoire sur chaque nouveau vecteur (utilisation de l'algorithme fir_sp_opt_r4). Prenons un exemple :

/* memory segmentation */#pragma DATA_SECTION (xk_sp,".ddrsdram");

• Modifier le code de la fonction firtest_perf de façon à commuter d'un modèle mémoire à un autre en fonction de la valeur du paramètre d'entrée memoryModel. Ces modifications devront être intégrées dans la boucle assurant une répétition des tests de performance. Nous nous laisserons également la possibilité de pouvoir retirer du code à la pré-compilation :

/* memory model selection */if ( memoryModel == UMA_L2CACHE_L1DCACHE ) {

/* user code – partie 2.2 – test de performance */}

#if ( TEST_FIR_L2SRAM_L1DCACHE != 0 )else if ( memoryModel == UMA_L2SRAM_L1DCACHE ) {

/* user code – partie 4.2 – préchargement des données de DDR SRAM vers L2 SRAM */}

#endif

69

Page 70: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• A partir de maintenant et jusqu'à la fin de la trame de travaux pratiques, toutes nos futures optimisations (mémoire et périphériques d'accélération) utiliseront l'algorithme vectorisé fir_sp_opt_r4 précédemment développé et offrant un niveau optimum d'accélération.

• Comme pour les algorithmes précédents, copier dans la fonction main un bloc de code assurant les tests de conformité et de performance d'un algorithme puis le modifier de façon à obtenir une section de test pour l'algorithme fir_sp_opt_r4. Nous utiliserons dans un premier temps la macro TEST_FIR_L2SRAM_L1DCACHE qui nous permettra si nécessaire de retirer du code à la pré-compilation. De même, nous passerons maintenant la macro UMA_L2SRAM_L1DCACHE comme second argument de la fonction firtest_perf.

• Notre procédure de test complète utilisant à tour de rôle des modèles mémoire pleinement cachables ou des modèles mixtes cachables/SRAM adressables, nous allons nous offrir la possibilité de modifier à l'exécution le modèle mémoire du processeur.

En vous aidant de la documentation technique de CSL présente dans le répertoire de projet (/disco/c6678/doc/csl/docs/doxygen /html/index.html) et des macros et énumérateurs présents dans le header C:\ti\pdk_C6678_<version>\packages\ti\csl\csl_cache.h, compléter la fonction firtest_perf de façon à reconfigurer les caches processeurs concernés. L'exemple suivant permet de restaurer des niveaux L2 et L1D pleinement cachable :

/* memory model selection */if ( memoryModel == UMA_L2CACHE_L1DCACHE ) {

/* caches levels configurations */CACHE_setL2Size (CACHE_256KCACHE);CACHE_setL1DSize (CACHE_L1_32KCACHE);CACHE_setL1PSize (CACHE_L1_32KCACHE);

/* user code – partie 2.2 – test de performance */}

#if ( TEST_FIR_L2SRAM_L1DCACHE != 0 )else if ( memoryModel == UMA_L2SRAM_L1DCACHE ) {

/* caches levels configurations */

/* coefficients array loading */

/* user code – partie 4.2 – préchargement des données de DDR SRAM vers L2 SRAM */}

#endif

• En vous aidant du travail préparatoire, effectuer manuellement les transferts mémoire partielsdes différents vecteurs d'entrée et de sortie de la DDR SRAM vers la mémoire L2 SRAM. Comme pour chaque phase de développement, bien travailler en mode Debug.

70

Page 71: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Après validation, lancer une exécution en mode Release (mode Debug coupé et options d'optimisations levées), puis reporter les résultats des tests dans le tableau d'analyse comparative à la fin de ce support de travaux pratiques.

71

Page 72: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

4.3. Préchargement des données de L2 SRAM vers L1D SRAM

• Comme pour les algorithmes précédents, copier dans la fonction main un bloc de code assurant les tests de conformité et de performance d'un algorithme puis le modifier de façon à obtenir une section de test pour l'algorithme fir_sp_opt_r4. Nous utiliserons maintenant la macro TEST_FIR_L2SRAM_L1DSRAM qui nous permettra si nécessaire de retirer du code à la pré-compilation. De même, nous passerons maintenant la macro UMA_L2SRAM_L1DSRAM comme second argument de la fonction firtest_perf.

• Compléter le code de la fonction firtest_perf de façon à effectuer les traitements suivants :

◦ Commuter d'un modèle mémoire à un autre en fonction de la valeur du paramètre d'entrée memoryModel.

◦ Configurer les caches processeurs propre au modèle mémoire courant

◦ Précharger le vecteur de coefficients a_sp de la DDR SRAM vers le vecteur a_sp_l1d présent en niveau L1D. Utiliser la fonction standard memcpy.

• En vous aidant du travail précédent, effectuer maintenant des copies partielles manuelles des vecteurs de la mémoire L2 SRAM vers la mémoire L1D SRAM en respectant les tailles de vecteurs suivants. Si nécessaire, s'aider du code de prototypage Matlab dans /disco/matlab/ :

/* arrays allocations (bytes) :* xk_sp (DDR) |------------------------- 256Kb or 4Mb --------------------------|* xk_sp_l2 |------------- 128Kb + 256b - 4 -------------| overlop* xk_sp_l1d |--- 8Kb + 256b - 4 ---| overlop* a_sp_l1d |- 256b -|* yk_sp_l1d |----- 8Kb -----|* yk_sp_l2 |------------- 128Kb -------------|* yk_sp (DDR) |------------------- (256Kb or 4Mb) - 256b + 4 -------------------|*/

72

Page 73: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Après validation, lancer une exécution en mode Release (mode Debug coupé et options d'optimisations levées), puis reporter les résultats des tests dans le tableau d'analyse comparative à la fin de ce support de travaux pratiques.

• A ce stade là de nos développements, nous constatons une légère perte de performance mais néanmoins un déterminisme garanti à l'exécution (maîtrise totale des données présentes dans les niveaux L2 et L1D). Juste pour information, c'était déjà partiellement le cas précédemment avec un modèle pleinement cachable dans le cadre d'un produit scalaire (données manipulées séquentiellement dans l'ordre). Néanmoins, pour grand nombre d'autres algorithmes DSP avec indexages complexes (exemple de la FFT), nous aurions pu avoir de mauvaises surprises à n'utiliser que du cache.

• Nous avons cependant, sans pour autant modifier notre modèle mémoire, possibilité d'accélérer nos transferts. En effet, jusqu'à présent nous avons utilisé la fonction standard memcpy réalisant les transferts via le CPU (instructions LDx/STx). Nous allons maintenant regarder de plus près les périphériques DMA (Direct Memory Access), spécialisés dans les transferts mémoire autonomes sans passer par le CPU.

73

Page 74: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

74

Page 75: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

PERIPHERIQUES

D'ACCELERATION

75

Page 76: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

5. PERIPHERIQUES D'ACCELERATIONTravail préparatoire

• 1. (1,5pt) Qu'est-ce-qu'un DMA ? Bien entendu, Direct Memory Access n'est pas la réponse attendue ...

• 2. (1,5pt) Qu'est-ce qu'un canal DMA (DMA channel) pour un DMA ?

• 3. (0,5pt) En s'aidant de la documentation technique ''SPRUGW0C – CorePac'' (répertoire /disco/c6678/doc/datasheet/ ou en ligne), combien de canaux possède chaque IDMA de notre processeur. De même, combien d'IDMA possède notre processeur DSP C6678 ?

• 4. (2,5pt) En vous aidant de la documentation technique de CSL (/disco/c6678/doc/csl/docs/doxygen /html/index.html), présenter l'API de programmation utile à l'utilisation du canal 0 de l'IDMA. La citer et expliquer brièvement son fonctionnement.

• 5. (4pt) Proposer une implémentation par transferts IDMA de la fonction standard memcpy utilisant quant à elle le CPU pour effectuer des transferts mémoires (instructions LDx/STx). S'aider de la documentation technique de CSL (/disco/c6678/doc/csl/docs/doxygen /html/index.html) ainsi que des exemples présentés. Voici le cahier des charges à respecter ainsi que le prototype de la fonction :

◦ Utiliser le canal numéro 1

◦ IDMA priorité maximale vis à vis du CPU

◦ Attendre la fin de la totalité du transfert avant de quitter la procédure

◦ Valider la génération et l'envoi d'une interruption après la fin du transfert

◦ Les pointeurs d'entrée pointeront sur des flottants 32bits (float)

/** * @brief IDMA (CorePac Internal Direct Memory Access) bytes copy* from L2 array source to destination array in L1D memory * @param dst pointer on destination array * @param src pointer on source array * @param nbBytes number of bytes to copy */void idmacpy( void *dst, \

void *src, \Uint16 nbBytes);

76

Page 77: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

5. PERIPHERIQUES D'ACCELERATIONTravail en séance

Dans cet ultime partie, nous allons nous intéressé à des périphériques d'accélération standards sur architectures processeurs évoluées, les DMA (Direct Memory Access). Rappelons que letravail d'un DMA est d'effectuer des transferts mémoires sans passer par le CPU. Un DMA possède sespropres bus et est, après configuration, une entité autonome de l'architecture du processeur. Un DMA classique effectue des copies d'une zone mémoire à une autre et est capable, comme tout périphérique, de prévenir le CPU de la fin d'un transfert par l'envoi d'une interruption matérielle (IRQ,Interrupt ReQuest). Des DMA plus évolués (exemple des Enhanced DMA chez TI ou des Smart DMA chez Freescale) sont capables d'effectuer des transferts avec modes d'adressages et indexations complexes (manipulation de matrices, de cubes de données), peuvent synchroniser des transferts sur événements matériels issus de périphériques, peuvent capturer et garder des grands nombres de pré-configurations … Une étude approfondie de ces types de DMA peut alors prendre des mois.

Dans un premier temps, nous travaillerons avec les IMDA (Internal DMA) de notre processeur. Ces IMDA sont présents dans chaque cœur et ne proposent que des services standards de copies :

Dans le schéma ci-dessus, nous pouvons observer plus finement l'architecture interne d'un corePac (ensemble CPU/cœur, caches associés et utilitaires matériels spécifiques, exemple des IDMA). Bien faire la distinction entre les mémoires caches (espaces de stockages) et les contrôleurs de caches (DMA autonome travaillant dans notre cas avec des mécanismes de localités temporelles LRU pour le remplacement des lignes de caches). Un contrôleur de cache effectuant des copies de mémoires àmémoires, il n'est donc qu'un DMA autonome.

77

Page 78: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

5.1. Transferts par IDMA

• Comme pour les algorithmes précédents, copier dans la fonction main un bloc de code assurant les tests de conformité et de performance d'un algorithme puis le modifier de façon à obtenir une section de test pour l'algorithme fir_sp_opt_r4. Nous utiliserons maintenant la macro TEST_FIR_L2SRAM_L1DIDMA qui nous permettra si nécessaire de retirer du code à la pré-compilation. De même, nous passerons maintenant la macro UMA_L2SRAM_L1DIDMA comme second argument de la fonction firtest_perf.

• Compléter le code de la fonction firtest_perf de façon à effectuer les traitements suivants :

◦ Commuter d'un modèle mémoire à un autre en fonction de la valeur du paramètre d'entrée memoryModel.

◦ Configurer les caches processeurs propre au modèle mémoire courant

◦ Précharger le vecteur de coefficients a_sp de la DDR SRAM vers le vecteur a_sp_l1d présent en niveau L1D

• Ajouter au projet le fichier source /disco/c6678/idmalib/src/idmacpy.c puis s'assurer de la bonne compilation du projet.

• En vous aidant du travail préparatoire, compléter le code de la fonction idmacpy de façon à effectuer des transferts par IDMA et non plus par le CPU. Modifier le code de la fonction firtest_perf (section UMA_L2SRAM_L1DIDMA) de façon à effectuer les transferts mémoires L2 SRAM / L1D SRAM / L2 SRAM par IDMA.

• Après validation, lancer une exécution en mode Release (mode Debug coupé et options d'optimisations levées), puis reporter les résultats des tests dans le tableau d'analyse comparative à la fin de ce support de travaux pratiques.

Cette solution est légèrement plus rapide que la précédente car n'oublions pas qu'un DMA reste un périphérique spécialisé et qu'en aucun cas il n'est capable d'exécuter des instructions contrairement à un CPU (pipeline complexe : fetch, decode, execute et writeback). Même si dans notre cas ses bus/paths restent moins larges que ceux du CPU, une fois configuré, il les utilise exclusivement afin d'effectuer la fonction de copie pour laquelle il a été détaché.

78

Page 79: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

5.1. Stratégie Ping Pong

Même si la solution précédente reste plus rapide qu'une copie par CPU, elle n'est pas optimale. Notre IMDA possède 2 canaux indépendants par cœurs. Ces canaux peuvent alors être utilisés en parallèles en manipulant chacun deux vecteurs temporaires de stockage en L1D SRAM. Cette stratégie très générique de copie se nomme Ping Pong, lorsque le côté Ping est en cours de traitement (algorithme de traitement du signal), le côté Pong est en cours de chargement/sauvegarde, etc. Rappelons d'ailleurs que nous possédons 24Ko de cache L1D SRAM adressable, nous autorisant ainsi à pouvoir définir de nouveaux vecteurs temporaires de stockage. Observons par exemple une séquence de transferts Ping Pong en 6 étapes :

• Canal 0 : Dédié aux chargements mémoires L2 SRAM vers L1D SRAM

• Canal 1 : Dédié aux sauvegardes mémoires L1D SRAM vers L2 SRAM

• Étape 1 : Chargement donnée xk_sp du côté Ping de L2 SRAM vers L1D SRAM

• Étape 2 : Chargement donnée xk_sp du côté Pong de L2 SRAM vers L1D SRAM et si chargement du côté Ping terminé, application de l'algorithme de filtrage sur les données précédemment chargées du côté Ping

• Étape 3 : Si traitement algorithmique terminé, sauvegarde des données de sortie yk_sp du côté Ping de L1D SRAM vers L2 SRAM et si chargement du côté Pong terminé,application de l'algorithme de filtrage sur les données précédemment chargées du côtéPong

• Étape 4 : Chargement donnée xk_sp du côté Ping de L2 SRAM vers L1D SRAM

• Étape 5 : Si traitement algorithmique terminé, sauvegarde des données de sortie yk_sp du côté Pong de L1D SRAM vers L2 SRAM

• Étape 6 : Si traitement algorithmique terminé, sauvegarde des données de sortie yk_sp du côté Ping de L1D SRAM vers L2 SRAM

• Voilà, pour cette année la trame de travaux pratiques s'arrête ici ! Si vous le souhaitez et si vous avez le temps, vous pouvez tenter d'implémenter la stratégie Ping Pong. Bien entendu, cela entraînera un refactoring non négligeable de code.

79

Page 80: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

80

Page 81: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

BILAN

81

Page 82: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Cœur de métier

Nous venons de faire un rapide tour d'horizon du potentiel de notre architecture processeur. Nous comprenons mieux maintenant le sens du nom de l'enseignement ''Processeurs Spécialisés''. Beaucoup des mécanismes d'accélération déterministes présentés sont impossibles ou en tous cas bien moins performants sur architectures généralistes (MCU, AP, GPP). Néanmoins, une bonne compréhension des stratégies présentées précédemment vous assurera une adaptabilité relativementforte sur la plupart des architectures processeurs parallèles du marché (AP, GPP, DSP, GPU).

Il faut maintenant savoir que le plus souvent en milieu industriel, notamment dans les grands groupes, les ingénieurs bas niveaux chargés du développement des bibliothèques spécialisées sont différents des ingénieurs assurant l'intégration logicielle :

• Développeurs temps réel bas niveaux : ingénieurs spécialisés dans les architectures matérielles processeurs et le développement de bibliothèques spécialisées

• Développeurs logiciels hauts niveaux : intégrateurs système hauts niveaux travaillant dans les couches hautes de l'applicatif et utilisant les bibliothèques en modes boîtes noires.

Par exemple, il ne nous reste plus qu'à faire un copier/coller du code proposant les copies mémoires L2 SRAM / L1D SRAM / L2 SRAM par transferts EDMA/IDMA dans le code source de la fonction fir_sp_r4 ainsi que d'inclure le code vectorisé développé dans la fonction fir_sp_opt_r4 afin d'offrir une boîte noire utilisable par un développeur haut niveau dans une optique d'intégration logicielle. Cette boîte noire offre alors une abstraction totale de l'architecture matérielle du processeur et masque la grande complexité des mécanismes d'accélérations appliqués :

82

Page 83: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

Architectures multi-coeurs

Nous allons maintenant présenter un exemple d'utilisation d'architecture multi-coeurs, par exemple la famille C6678 de TI. Nous constaterons alors tout le potentiel d'une programmation vectorielle monocœur efficace. Une architecture multi-coeurs peut-être détournée à d'autres fins qu'une simple parallélisation d'un algorithme sur plusieurs cœurs. Prenons l'exemple d'une chaîne de traitement numérique du signal. Ce type de chaîne algorithmique peut par exemple être rencontrée dans les domaines du traitement d'image, applications radars, applications télécoms ...

Supposons que nous travaillons sur une architecture 4 cœurs vectoriels et que nous avons de lourdes contraintes temps réel afin d'exécuter la chaîne complète. Après instrumentations et mesuressur la chaîne, l'algorithme imposant le plus long temps d'exécution est le numéro 4 (produit scalaire par exemple). Observons deux exemples d'implémentations possibles, la plus efficace n'étant pas forcément celle que l'on croit.

• Optimisations vectorielles monocœurs et parallèles multi-coeurs appliquées à chaque algorithme afin de minimiser leurs temps d'exécutions respectifs :

Cette solution implique donc une vectorisation ainsi qu'une parallélisation de code appliquées à chaque algorithme. Tous les cœurs du processeur voient passer la chaîne algorithmique optimisée complète. Cette solution, qui nécessite de nombreux allez/retours en mémoire principale, est la plus couramment rencontrée sur processeurs GPP.

83

Page 84: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

• Optimisations vectorielles monocœurs et pipelining matériel algorithmique :

Chaque CPU est dédié à l'exécution d'un algorithme ou d'une série d'algorithmes. Nous utilisons alors nos CPU comme un pipeline algorithmique. Les premières données traverseront le pipeline complet, néanmoins celles qui suivent seront chaînées et ne dureront que le temps d'exécution d'un étage du pipeline. Néanmoins, un ordonnanceur ou scheduler est nécessaire pour la synchronisation des différents échanges. Sur notre processeur DSP C6678, nous pouvons nous projeter avec 7 cœurs dédiés au traitement numérique de la chaîne et 1 cœur pour l'ordonnancement et les échanges avec l'extérieur.

84

Page 85: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

BENCHMARKING

85

Page 86: SOMMAIRE - foad.ensicaen.fr

DIGITAL SIGNAL PROCESSOR

Travaux Pratiques

BENCHMARKING

ANALYSE COMPARATIVEAlgorithme

(vecteur d'entré 64Ksamples ou 256Ko)

ArchitectureTemps

d'exécution(ms)

Performances(MACS per cycle,

maximum 8)

Temps de Développement

(heures)Observations et Limitations

DSPF_sp_fir_gen

TIC6600

1,096ms 2,73 0cf. documentation DSPLIB TI

nr and nh are a multiples of 4 and greaters than or equalsto 4. x, h and r are double-word aligned. Interruptible code.

GenuineIntel

corei7IA-64

(Haswell)

86