Mise au point d'applications multicœurs avec le toolkit Real-Time Execution Trace
Introduction
Série de tutoriaux sur les principes fondamentaux de la programmation multicœur
Série de tutoriaux sur les principes fondamentaux de la programmation multicœur
La mise au point est la phase de développement de logiciel qui prend le plus de temps [1]. À la conférence Embedded Systems de 2007, 56 pour cent des participants à un sondage d'opinion ont indiqué que la partie de leur travail qui prend le plus de temps est la mise au point. 59 pour cent ont rapporté que l'outil de mise au point qu'ils utilisent ne supporte pas le développement multicœur ou multiprocesseur [2]. Ce document traite de la mise au point des applications multicœurs.
Table des matières
Introduction
Le multithreading est supporté nativement par LabVIEW depuis le milieu des années 90. Avec l'introduction des microprocesseurs multicœurs, les développeurs peuvent tirer plein parti des capacités de cette nouvelle technologie en utilisant LabVIEW. La programmation parallèle pose de nouveaux défis lors du développement d'applications pour des microprocesseurs multicœurs, entre autres en matière d'affinité de processeur et de synchronisation d'accès simultané de la mémoire partagée par plusieurs threads. LabVIEW gère automatiquement la plupart des tâches de multithreading tout en laissant aux utilisateurs la possibilité d'assigner des threads à des microprocesseurs spécifiques (ou à des cœurs spécifiques d'un même microprocesseur).
Si vous développez une application temps réel, le meilleur moyen de contrôler précisément l'utilisation du microprocesseur et d'autres événements est de capturer les traces d'exécution des cibles temps réel. Grâce au toolkit Real-Time Execution Trace, vous pouvez visualiser et analyser les traces d'exécution des tâches temps réel, y compris les threads Instruments virtuels (VIs) et Système d'exploitation (OS). Le toolkit Real-Time Execution Trace est un complément logiciel pour LabVIEW Real-Time 7.1.1 (et versions ultérieures) et LabWindows/CVI Real-Time 8.5 (et versions ultérieures) ; il est fourni avec une période d'évaluation de 30 jours. Il comporte deux parties : les VIs d'instrumentation et l'utilitaire de visualisation des traces (Trace Viewing Utility). Les VIs d'instrumentation doivent être ajoutés autour du code dont vous voulez tracer l'exécution. L'utilitaire Trace Viewing Utility sert à visualiser la trace d'exécution capturée.
Il est crucial d'avoir accès aux informations sur l'exécution bas niveau afin d'optimiser et de mettre au point des applications temps réel. En effet, c'est à cette condition que vous pouvez identifier les sources de jitter telles que l'affinité de processeur, les allocations de mémoire, l'héritage de priorité et les situations de compétition.
L'utilisation de ressources partagées par plusieurs threads de priorités différentes risque de provoquer un comportement inattendu de l'application. Le tableau n°1 présente des ressources partagées et les problèmes qui risquent d'apparaître dans une application.
|
Ressources partagées |
Problèmes potentiels |
|
|
Tableau n°1. Ressources partagées et problèmes potentiels associés.
Dans les deux paragraphes suivants, nous allons voir comment assigner et tracer l'affinité de processeur, et mettre au point les problèmes potentiels liés aux ressources partagées.
Affinité de processeur
Les deux captures d'écran suivantes représentent les traces d'exécution d'un programme exécuté sur une cible temps réel multicœur embarquée. Dans NI LabVIEW, la programmation parallèle a été implémentée en utilisant deux structures Boucles cadencées (TL). Chaque boucle TL a été assignée à un processeur différent. Tout le code qui se trouve dans une boucle TL donnée s'exécute sur le même processeur. L'affinité de processeur est conservée jusqu'à ce que l'exécution du programme soit terminée. Les figures n°1 et n°2 montrent clairement l'affinité de processeur de chaque thread. Les threads associés à un processeur donné sont mis en évidence alors que les autres sont grisés. Remarquez aussi l'exécution parallèle des threads qui s'exécutent sur des processeurs différents.

Figure n°1. Cette trace d'exécution montre les threads associés au processeur CPU 0. Les autres threads sont grisés.

Figure n°2. Cette trace d'exécution montre les threads associés au processeur CPU 1.
Voir aussi :
LabVIEW et Hyper-Threading,
Le multitâche dans LabVIEW,
Création de VIs multithread avec LabVIEW pour un maximum de performances et de fiabilité
Ressources partagées
L'utilisation de ressources partagées par un thread temps critique (un thread qui doit s'exécuter dans une période de temps déterministe) peut introduire un jitter dans votre application temps réel. Le gestionnaire de mémoire LabVIEW représente une de ces ressources partagées. Il est chargé d'allouer la mémoire de manière dynamique.
Lorsqu'un programme à priorité normale est en possession du gestionnaire de mémoire, les autres threads, y compris le thread temps critique, doivent attendre que la ressource partagée soit libérée. Dans ce cas-là, un jitter est inévitablement introduit dans le thread temps critique. Pour résoudre ce problème, le planificateur de threads assigne l'exécution de l'application à priorité normale au thread temps critique pour que l'application se termine plus vite et qu'elle libère le gestionnaire de mémoire plus tôt. Ce phénomène est connu sous les termes "héritage de priorité" et "inversion de la priorité". Pour éviter ce genre de problème, National Instruments vous déconseille d'utiliser des ressources partagées. Dans le cas du gestionnaire de mémoire, vous pourriez préallouer de la mémoire pour les tableaux.
L'héritage de priorité peut parfois être amélioré en combinant deux systèmes de planification de priorité : au niveau du VI et au niveau de la boucle cadencée. Par exemple, dans la figure n°3, vous pouvez voir un sous-VI critique (icône rouge) et une boucle cadencée qui sont en compétition pour les mêmes ressources de mémoire. La compétition pour les ressources partagées entre le sous-VI critique et la boucle cadencée conduit à un héritage de priorité.

Figure n°3. Exemple d'utilisation de deux systèmes d'affectation de priorité.
Dans la figure n°4, vous pouvez voir que la boucle cadencée commence à s'exécuter la première mais qu'elle est évincée par le sous-VI critique. Les drapeaux pourpres indiquent le démarrage et les drapeaux jaunes la fin de l'évincement de la boucle cadencée. À la fin de l'évincement, la boucle cadencée a hérité de la priorité du sous-VI critique. Ceci est indiqué par le drapeau orange sur la trace d'exécution. Pour réduire ce type de conflits, efforcez-vous de ne pas utiliser de ressources partagées dans les threads temps critique. De plus, National Instruments vous suggère d'utiliser un seul système d'affectation de priorité : soit des sous-VIs, soit des boucles cadencées de niveaux de priorité différents.

Figure n°4. Évincement de la boucle cadencée et héritage de la priorité
La figure n°5 représente la trace d'un autre programme qui comporte un sous-VI à priorité normale et un sous-VI critique qui partagent une ressource commune, le gestionnaire de mémoire. Les drapeaux verts indiquent l'allocation de mémoire dynamique, alors que les drapeaux orange indiquent l'héritage de priorité. L'exécution du thread temps critique a été interrompue pour que le sous-VI à priorité normale puisse être exécuté dans le thread temps critique afin de libérer plus tôt la ressource partagée. Ceci finit par détruire le déterminisme du sous-VI critique.

Figure n°5. Les drapeaux verts indiquent l'allocation de mémoire dynamique (autrement dit, l'accès au gestionnaire de mémoire). Le drapeau orange indique l'héritage de propriété.
Voir aussi :
Préallocation de tableaux pour les boucles déterministes
Comment éviter les ressources partagées et les inversions de priorité pour les applications déterministes
Gestion de la mémoire dans LabVIEW Real-Time (exemple de code)
Comment éviter les conflits de mémoire contiguë (module RT)
Pourquoi utiliser le toolkit Real-Time Execution Trace ?
- Pour rechercher les problèmes d'exécution et mettre au point les applications à un ou plusieurs processeurs
- Pour identifier les ressources partagées et les allocations de mémoire
- Pour confirmer le comportement de cadencement prévu
- Pour surveiller l'utilisation du processeur et l'interaction multicœur
- Pour en savoir plus sur le modèle d'exécution de LabVIEW
Utilisation d'autres outils de mise au point
Outre le toolkit Real-Time Execution Trace, nous vous conseillons vivement d'utiliser les autres outils de mise au point standard pour obtenir les performances attendues de vos applications.
Outils de mise au point des VIs
- Sondes, points d'arrêt, animation de l'exécution
- VIs NI Timestamp (RDTSC)
- VI RT Debug String
- Code utilisateur
Outils de mise au point du système
- Real-Time System Manager (visualisation de l'utilisation des processeurs à l'écran)
- VI Profiler
- Toolkit Real-Time Execution Trace
Références :
- Richard Goering, Embedded Developer Survey Reveals Debugging Challenges, EETimes, 11 Mai, 2007
- Sondage d'opinion mené par Virtutech à la conférence "Embedded Systems Conference 2007" avec 354 participants
Ressources supplémentaires sur la programmation multicœur
Série de tutoriaux sur les principes fondamentaux de la programmation multicœur
- www.ni.com/multicore/f
- Introduction au multitraitement symétrique de LabVIEW Real-Time
- En savoir plus sur NI LabVIEW
Législation
Ce tutorial a été développé par National Instruments. Bien qu'un support technique puisse être fourni pour ce tutorial, il n'a pas été complètement testé ni vérifié, et NI ne garantit pas sa qualité, ni qu'il continuera à être supporté pour les nouvelles versions des produits et drivers qui y sont rattachés. CE TUTORIAL EST FOURNI "EN L'ÉTAT" SANS GARANTIE D'AUCUNE SORTE, ET EST SUJET À CERTAINES RESTRICTIONS COMME PLUS SPÉCIFIQUEMENT DÉTERMINÉES DANS LES CONDITIONS D'UTILISATION DE NI.COM (http://ni.com/legal/termsofuse/unitedstates/us/).
