Vitesse d'exécution des VIs

Aide LabVIEW 2014

Date d'édition : June 2014

Numéro de référence : 371361L-0114

»Afficher les infos sur le produit
Télécharger l'aide (Windows uniquement)

Bien que LabVIEW compile les VIs et produit du code qui s'exécute en général très rapidement, vous voudrez obtenir les performances les meilleures lorsque vous travaillez sur des VIs critiques en temps. Cette section traite des facteurs qui affectent la vitesse d'exécution et suggère des techniques de programmation pour vous aider à obtenir les meilleures performances possibles.

Étudiez les éléments suivants pour déterminer la cause d'une performance ralentie :

  • Entrée/Sortie (fichiers, GPIB, acquisition des données, réseau)
  • Affichage à l'écran (grandes commandes, commandes qui se chevauchent, trop d'afficheurs)
  • Gestion de la mémoire (utilisation inefficace de tableaux et de chaînes, structures de données inefficaces)
  • Optimisations du compilateur (les choix effectués par le compilateur pour trouver l'équilibre entre la réactivité de l'éditeur et la vitesse d'exécution des VIs)

En général, les autres facteurs, comme le temps système utilisé pour l'exécution et l'appel des sous-VIs, ont peu d'effet sur la vitesse d'exécution.

Entrée/Sortie

En général, les appels d'entrée/sortie (E/S) consomment beaucoup de temps système. Ils prennent souvent beaucoup plus de temps qu'une tâche de calcul. Par exemple, une simple opération de lecture de port série peut être associée à plusieurs millisecondes de temps système. Ce temps système est présent pour toute application qui utilise des ports série car un appel d'E/S nécessite le transfert d'informations via plusieurs couches d'un système d'exploitation.

La meilleure façon de diminuer un temps système excessif consiste à réduire le nombre des appels d'E/S à effectuer. Les performances seront meilleures si vous pouvez structurer le VI de telle sorte que chaque appel transfère une grande quantité de données, plutôt que d'avoir plusieurs appels d'E/S transférant chacun moins de données.

Par exemple, si vous créez un VI d'acquisition de données (NI-DAQmx), vous avez deux options pour lire les données. Vous pouvez utiliser une fonction de transfert de données ponctuel comme le VI AI-Échantillonner une voie ou une fonction de transfert multi-points comme le VI AI-Acquérir un signal. Si vous devez acquérir 100 points, utilisez le VI AI-Échantillonner une voie dans une boucle avec une fonction Attendre pour établir le cadencement. Vous pouvez aussi utiliser le VI AI-Acquérir un signal avec une entrée indiquant que vous voulez 100 points.

Vous pouvez obtenir des fréquences d'échantillonnage de données beaucoup plus élevées et précises en utilisant le VI AI-Acquérir un signal car il utilise des horloges matérielles pour gérer l'échantillonnage des données. De plus, le temps système du VI AI-Acquérir un signal est à peu près le même que celui d'un appel du VI AI-Échantillonner une voie, bien qu'il transfère beaucoup plus de données.

Affichage à l'écran

La mise à jour fréquente des commandes d'une face-avant peut constituer l'une des opérations qui ralentit le plus une application. Ceci est particulièrement vrai dans le cas des affichages les plus complexes, comme les graphes et les graphes déroulants. La plupart des indicateurs ne sont pas actualisés si les nouvelles données qu'ils reçoivent sont identiques aux anciennes, mais les graphes et les graphes déroulants sont constamment actualisés. Si le taux d'actualisation pose un problème, les meilleures solutions consistent à réduire le nombre d'objets sur la face-avant et à garder l'affichage de la face-avant aussi simple que possible. Dans le cas de graphes et de graphes déroulants, vous pouvez désactiver la mise à l'échelle automatique, les marqueurs d'échelles, le lissage et les grilles pour accélérer l'affichage.

Comme pour les autres sortes d'E/S, il y a une certaine quantité de temps système fixe dans l'affichage d'une commande. Vous pouvez transmettre plusieurs points à la fois à un indicateur en utilisant certaines commandes, par exemple des graphes déroulants. Vous pouvez minimiser le nombre de mises à jour des graphes déroulants en transférant plus de données à chaque fois. Vous obtiendrez des taux d'affichage des données beaucoup plus élevés si vous recueillez les données de votre graphe déroulant pour afficher plusieurs points à la fois au lieu d'afficher chaque point dès qu'il arrive.

Vous ne devez pas vous soucier du temps système de l'affichage lorsque vous développez des sous-VIs qui s'exécuteront avec la face-avant fermée. Si la face-avant est fermée, vous n'avez pas de temps système pour l'affichage des commandes, et les graphes ne prennent pas plus de temps que les tableaux.

Dans les systèmes multithreads, vous pouvez utiliser l'élément de menu local Avancé»Affichage synchrone pour définir s'il faut retarder les mises à jour des commandes et des indicateurs. Par défaut, les commandes et les indicateurs utilisent des affichages asynchrones, ce qui signifie que le système d'exécution peut continuer l'exécution dès qu'il a transféré les données aux commandes et aux indicateurs de la face-avant. Par après, le système de l'interface utilisateur remarque que la commande ou l'indicateur doit être mis à jour et les retrace pour afficher les nouvelles données. Si le système d'exécution essaie de mettre à jour la commande plusieurs fois en succession rapide, vous ne verrez peut-être pas certaines des mises à jour intermédiaires.

Dans la plupart des applications, les affichages asynchrones accélèrent considérablement l'exécution sans affecter ce que l'utilisateur voit. Par exemple, vous pouvez mettre à jour une valeur booléenne plusieurs centaines de fois par seconde, ce qui dépasse le nombre de mises à jour perceptibles à l'œil nu. Les affichages asynchrones permettent au système d'exécution de passer davantage de temps à exécuter les VIs en réduisant automatiquement la fréquence des mises à jour effectuées par le thread de l'interface utilisateur.

Pour activer l'affichage synchrone, cliquez avec le bouton droit de la souris sur la commande ou l'indicateur, et sélectionnez Avancé»Affichage synchrone dans le menu local pour cocher la case à côté de l'élément de menu.

Remarque  N'activez l'affichage synchrone que s'il faut afficher toutes les valeurs des données. Sur les systèmes multithreads, l'utilisation d'un affichage synchrone ralentit considérablement les performances.

Vous pouvez aussi utiliser la propriété Retarder MàJ face-avant pour remettre à plus tard toutes les nouvelles requêtes de mise à jour de la face-avant.

Les performances d'un VI sont aussi fonction des paramètres du moniteur et des commandes placées sur la face-avant. Diminuez la profondeur de couleurs et la résolution de votre moniteur, et activez l'accélération matérielle de votre moniteur. Reportez-vous à la documentation de votre système d'exploitation pour obtenir des informations supplémentaires sur l'accélération matérielle. Vous pouvez aussi améliorer les performances d'un VI en utilisant les commandes de la palette Classique au lieu des commandes de la palette Moderne.

Gestion de la mémoire

Tenez compte des suggestions suivantes pour gérer la mémoire dans un VI afin d'optimiser la vitesse d'exécution.

Optimisations du compilateur

Pour améliorer la réactivité de l'éditeur pour les VIs complexes, le compilateur LabVIEW limite les optimisations susceptibles d'améliorer la vitesse d'exécution de ces VIs. Lorsque vous avez fini de développer un VI complexe, vous pouvez configurer LabVIEW pour donner priorité à la vitesse d'exécution plutôt qu'à la réactivité de l'éditeur. Vous pouvez également configurer LabVIEW pour qu'il applique toutes les optimisations du compilateur à toute une spécification de construction.

Transmission des données dans le cadre d'une application

Vous pouvez choisir parmi plusieurs techniques pour transmettre des données dans une application LabVIEW. La liste suivante répertorie les méthodes les plus courantes selon leur efficacité.

  1. Fils de liaison — Utilisez des fils de liaison pour transmettre des données et permettre à LabVIEW de contrôler l'optimisation des performances. Cette technique est la plus rapide en langage par flux de données puisqu'il y a une source d'écriture unique, et une ou plusieurs sources de lecture.
  2. Nœud de rétroaction — Utilisez un nœud de rétroaction pour stocker des données d'un VI ou d'une itération précédente. Un nœud de rétroaction apparaît automatiquement si vous câblez la sortie d'un sous-VI, d'une fonction ou d'un groupe de sous-VIs et de fonctions à l'entrée de ce VI, de cette fonction ou de ce groupe, et que vous activez Nœud de rétroaction automatique dans les boucles sur la page Diagramme de la boîte de dialogue Options. LabVIEW active Nœud de rétroaction automatique dans les boucles par défaut. Un nœud de rétroaction conserve les données de la dernière exécution du VI, de la fonction ou du groupe, et peut les passer à l'exécution suivante ou définir une nouvelle valeur initiale, selon que vous déplacez le terminal d'initialisation ou non. Dans les boucles, les registres à décalage stockent des données de la même façon que le nœud de rétroaction mais nécessitent des fils de liaison s'étendant sur toute la boucle.
  3. Registres à décalage — Utilisez des registres à décalage si vous avez besoin de stockage ou de rétroaction à l'intérieur d'une boucle. Les registres à décalage transmettent les données via une source d'écriture et une source de lecture externes, et une source d'écriture et de lecture interne. Cet accès limité aux données maximise l'efficacité de LabVIEW. Vous pouvez remplacer les registres à décalage par un nœud de rétroaction pour obtenir la même fonctionnalité sans faire traverser la boucle par des fils de liaison.
  4. Variables globales et variables globales fonctionnelles — Utilisez des variables globales pour des données simples et un accès facile. Dans le cas de données nombreuses ou complexes, une variable globale lit et transmet toutes les données. Utilisez des variables globales fonctionnelles pour contrôler la quantité de données renvoyées par LabVIEW.

Utilisation de commandes, de références de commandes et de nœuds de propriété comme variables

Les commandes, les références de commandes et les nœuds de propriété peuvent être utilisés pour transmettre des données entre plusieurs VIs, mais ils ne sont pas conçus pour être utilisés comme variables car ils fonctionnent par le biais de l'interface utilisateur. N'utilisez des variables locales et la propriété Valeur que pour effectuer des actions sur l'interface utilisateur ou arrêter des boucles qui s'exécutent en parallèle.

En général, les actions sur l'interface utilisateur sont lentes sur les ordinateurs. LabVIEW transmet une valeur double via un fil de liaison en quelques nanosecondes ; il lui faut entre quelques centaines de microsecondes et quelques millisecondes pour tracer une partie de texte. Par exemple, LabVIEW peut transférer un tableau de 100K via un fil de liaison entre 0 nanosecondes et quelques microsecondes. Il faut quelques dizaines de millisecondes pour tracer la courbe de ce tableau 100K. Comme les commandes sont connectées à une interface utilisateur, l'utilisation de commandes pour transférer des données a pour effet secondaire le retraçage des commandes, ce qui augmente l'utilisation de mémoire et ralentit les performances. Si les commandes sont cachées, LabVIEW transfère les données plus rapidement, mais il doit tout de même mettre la commande à jour puisqu'elle risque d'être affichée à tout moment.

Effets du multithreading sur les actions de l'interface utilisateur

Les actions sur l'interface utilisateur utilisent davantage de mémoire car LabVIEW doit passer du thread d'exécution au thread de l'interface utilisateur. Par exemple, si vous définissez la propriété Valeur, LabVIEW simule un utilisateur qui change la valeur de la commande, arrête le thread d'exécution et passe au thread d'interface utilisateur pour changer la valeur. Ensuite, LabVIEW met à jour le buffer d'opération qui stocke les données à la commande même et retrace la commande si la face-avant est ouverte. Ensuite, LabVIEW renvoie les données au thread d'exécution dans le buffer de transfert, une zone protégée de la mémoire. Puis LabVIEW repasse au thread d'exécution. La prochaine fois que le thread d'exécution lit la commande, LabVIEW trouve les données dans le buffer de transfert et reçoit la nouvelle valeur pour le buffer d'exécution qui stocke les données sur le diagramme.

Si vous écrivez dans une variable locale ou globale, LabVIEW ne passe pas immédiatement au thread d'interface utilisateur. Au lieu de cela, LabVIEW écrit la valeur dans le buffer de transfert. L'interface utilisateur effectue la mise à jour à la prochaine mise à jour planifiée. Il se peut de mettre à jour une variable plusieurs fois avant que LabVIEW passe à un autre thread ou que l'interface utilisateur soit mise à jour. Ceci est dû au fait que les variables ne sont utilisées que sur le thread d'exécution.

Les variables globales fonctionnelles peuvent être plus efficaces que les variables globales ordinaires car elles n'utilisent pas de buffers de transfert. Les variables globales fonctionnelles existent uniquement dans le thread d'exécution et n'utilisent pas de buffers de transfert, sauf si vous affichez leurs valeurs sur une face-avant ouverte.

Diagrammes parallèles

Lorsque vous avez plusieurs diagrammes s'exécutant en parallèle, le système d'exécution passe régulièrement de l'un à l'autre. Si certaines de ces boucles sont moins importantes que d'autres, utilisez la fonction Attendre (ms) pour que les boucles moins importantes prennent moins de temps.

Par exemple, considérez le diagramme suivant.

Il y a deux boucles en parallèle. L'une des boucles acquiert des données et doit s'exécuter aussi souvent que possible. L'autre boucle surveille les entrées de l'utilisateur. De la façon dont le programme est structuré, les boucles reçoivent autant de temps l'une que l'autre. La boucle qui surveille les actions de l'utilisateur peut s'exécuter plusieurs fois par seconde.

En pratique, il suffit que la boucle qui surveille le bouton s'exécute tout au plus deux fois par seconde. En appelant la fonction Attendre (ms) dans la boucle de l'interface utilisateur, vous donnez bien plus de temps à l'autre boucle.

Itérations de boucle For en parallèle

Si vous utilisez une boucle For, LabVIEW exécute les itérations de la boucle en séquence. Si une boucle For nécessite beaucoup de calculs, vous pouvez améliorer les performances en exécutant les itérations de la boucle en parallèle. Les itérations de boucle en parallèle permettent à LabVIEW de tirer parti des systèmes à plusieurs processeurs pour exécuter la boucle For plus rapidement. Toutefois, les itérations de boucle en parallèle doivent être indépendantes de toutes les autres itérations. Utilisez la boîte de dialogue Résultats de la recherche de boucles capables de parallélisme pour déterminer quelles boucles For peuvent être exécuter en parallèle. Pour activer les itérations de boucle en parallèle, cliquez avec le bouton droit sur le bord de la boucle For et sélectionnez Configurer le parallélisme des itérations dans le menu local pour afficher la boîte de dialogue Parallélisme des itérations de boucle For.

Une fois que vous avez activé les itérations de boucle en parallèle, le terminal d'instances parallèles apparaît au-dessous du terminal de décompte . Vous pouvez utiliser ce terminal pour spécifer le nombre d'instances de la boucle que LabVIEW utilisera ainsi que pour identifier quelle instance exécute une itération spécifique.

Passez en revue les informations se rapportant aux performances avant d'activer les itérations de boucle For en parallèle.

National Instruments vous conseille d'afficher les mises en garde dans la fenêtre Liste des erreurs pour que LabVIEW vous avertisse si les itérations d'une boucle en parallèle risquent de poser problème dans un VI.

Temps système des sous-VIs

Lorsque vous appelez un sous-VI, il y a une certaine quantité de temps système associée à l'appel. Ce temps système est assez court (de l'ordre de quelques dizaines de microsecondes), surtout en comparaison du temps système des E/S et de l'affichage, qui peut varier de quelques millisecondes à quelques dizaines de millisecondes. Cependant, dans certains cas, ce temps système peut devenir plus important. Par exemple, si vous appelez un sous-VI 10 000 fois dans une boucle, ce temps système pourrait affecter considérablement la vitesse d'exécution. Dans ce cas, vous devriez envisager d'incorporer la boucle dans le sous-VI.

Une autre façon de minimiser le temps système des sous-VIs consiste à transformer les sous-VIs en sous-programmes en sélectionnant Exécution dans le menu déroulant Catégorie de la boîte de dialogue Propriétés du VI puis sous-programme dans le menu déroulant Priorité. Ceci a cependant des inconvénients. Les sous-programmes ne peuvent pas afficher les données de la face-avant, appeler les fonctions de temps ou de dialogue, autoriser les mises au point ou gérer les erreurs automatiques, ou fonctionner en mode multitâche avec d'autres VIs. En général, les sous-programmes sont mieux adaptés aux VIs qui ne requièrent pas d'interaction utilisateur et qui représentent de courtes tâches qui s'exécutent fréquemment.

Une troisième façon de minimiser le temps système des sous-VIs consiste à effectuer l'inlining des sous-VIs dans les VIs appelants. Lorsque vous implémentez l'inlining pour un sous-VI, LabVIEW insère le code compilé du sous-VI dans le code compilé du VI appelant. Si vous apportez par après des changements au sous-VI, LabVIEW recompile tous les VIs qui appellent ce sous-VI pour intégrer les changements. Fondamentalement, l'inlining d'un sous-VI élimine la nécessité d'appeler le sous-VI à l'exécution. À la place, LabVIEW exécute le code du sous-VI à l'intérieur du code compilé du VI appelant.

L'inlining de sous-VIs est particulièrement utile pour les petits sous-VIs, les sous-VIs dans une boucle, les sous-VIs dotés de sorties non câblées et les sous-VIs appelés une seule fois. Pour effectuer l'inlining d'un sous-VI, sélectionnez l'option Sous-VI incorporé dans les VIs appelants sur la page Exécution de la boîte de dialogue Propriétés du VI. Vous devez aussi sélectionner Exécution réentrante avec copies préallouées sur la même page de la boîte de dialogue. LabVIEW préalloue automatiquement des clones pour chaque instance lorsqu'il incorpore le sous-VI.

Un sous-VI que vous voulez incorporer ne doit avoir aucune des caractéristiques suivantes :

  • Être récursif
  • Utiliser la gestion automatique d'erreur
  • Contenir certains nœuds du diagramme, tels que des nœuds de propriété et des nœuds de méthodes. Ces nœuds génèrent des messages d'erreur lors de l'édition si vous activez l'inlining du sous-VI.
  • Autoriser la mise au point. Vous devez désactiver la mise au point des sous-VIs que vous voulez incorporer.
  • Être un des types de VIs suivants :
    • VI de dispatch dynamique d'une classe LabVIEW
    • VI pour une cible CGen ou FPGA
    • VI de commande - VIs qui définissent une commande ou un indicateur personnalisé
    • VI polymorphe
    • VI de variable globale
    • VI de commandeX
    • VI de méthode d'une bibliothèque de commandeX
    • VI qui ne peut être placé que sur un diagramme de simulation dans le module LabVIEW Control Design and Simulation

Même si le sous-VI ne possède aucune des caractéristiques précédentes, LabVIEW ne l'incorpore pas aux types d'appels suivants :

De plus, si vous incorporez un sous-VI, LabVIEW ignore tous les paramètres de priorité ou d'exécution préférée.

Reportez-vous au VI Execution Properties.vi du répertoire examples\Performance\VI Properties pour voir un exemple d'amélioration des performances qui résulte de l'inlining d'un sous-VI.

Temps système dû aux variables partagées

Les variables partagées publiées sur réseau causent une utilisation accrue de temps système et de mémoire. Si votre application utilise un grand nombre de variables partagées publiées sur réseau, envisagez d'utiliser plutôt le composant STM (Simple Messaging Reference Library). Reportez-vous au document de support à ni.com pour en savoir plus sur STM.

Si vous devez envoyer un flux continu de données d'un périphérique de calcul à un autre, utilisez les fonctions Flux réseau.

Calculs superflus dans les boucles

Évitez de placer un calcul dans une boucle s'il produit la même valeur pour toutes les itérations. Placez-le plutôt en dehors de la boucle et faites passer le résultat dans la boucle.

Par exemple, étudiez le diagramme suivant.

Le résultat de la division est le même pour chaque itération ; vous pourriez donc améliorer les performances en déplaçant la division en dehors de la boucle, comme le montre le diagramme qui suit.

Reportez-vous au diagramme suivant.

Si vous savez que la valeur de la variable globale ne sera pas changée par un autre diagramme ou VI qui s'exécute en même temps que cette boucle, ce diagramme perd du temps en lisant et en écrivant la variable globale à chaque itération de la boucle.

Si aucun autre diagramme n'a besoin de lire ou d'écrire la variable globale pendant cette boucle, vous pourriez substituer le diagramme suivant.

Remarquez que les registres à décalage doivent transférer la nouvelle valeur du sous-VI à l'itération suivante de la boucle. Le diagramme suivant illustre une erreur courante pour les débutants. Comme il n'y a pas de registre à décalage, le résultat du sous-VI n'est jamais renvoyé au sous-VI comme nouvelle valeur d'entrée.

CET ARTICLE VOUS A-T-IL ÉTÉ UTILE ?

Pas utile