From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Discussions au sujet des autres produits NI

annuler
Affichage des résultats de 
Rechercher plutôt 
Vouliez-vous dire : 

Multithread sous CVI

Bonjour,

Je suis stagiaire dans un laboratoire au Vietnam, et comme tout bon stagiaire qui se respecte, je suis submergé de problèmes 😄

Plus sérieusement, j'ai en charge de faire l'acquisition du 8flux audios via un bornier BNC2110 et une carte PCI 6035E. Le matériel est imposé.

Pour faire l'aqcuisition des huits voies, tout s'est plutôt bien déroulé. La qualité demandé n'est pas excpetionnelle (16khz sur 16bits) donc l'enregistrement est de bonne qualité.

Pour ce faire, et pour économiser les ressources systèmes, j'ai mis ma fonction d'acquisition dans un CALLBACK sur Timer que je règle légèrement en decà de ma durée d'acquisition. Le résultat est satisfaisant et la charge processeur est très faible.

Je dois ajouter un traitement en temps réel sur mon acquisition. Se traitement se fait sur des échantillons de 1s.

Mon problème intervient à ce moment là.

Comment mettre en parallèle ces traitements puisque ceux ci un peu complexe, afin de rester dans les contraintes "temps réel".

J'ai donc penser à paralléliser les traitement en les insérants dans des threads. Or, je n'arrive pas à contrôler spécifiquement le lancement des threads, comme on pourrait le faire avec l'envois de signaux. En effet, étant donné que je dois partager les Datas entre la fonction d'acquisition et la threads de traitement, j'ai besoin de contrôler le début de l'éxécution des threads.

Donc ma question est la suivante :
- Utiliser des threads dans mon application est-il judicieux ?
- Si oui, comment contrôler le début de ceux dessus sans utiliser des variable globalde dans des while bloquant ? (ex : while(lock);)

Je vous remercie par avance pour vos réponses.

Cordialement,

Frédéric

0 Compliments
Message 1 sur 6
3 627 Visites
Bonjour Frédéric,

Vous avez tout à fait raison en pensant à des threads différents. Plusieurs choses pourraient être intéressantes dans votre cas.
Tout d'aobrd, prenez le temps de lire un document qui se trouve dans le répertoire <CVI>/bin/ et qui s'appelle "MultiThreading Overview.pdf"

Sont décrits dans ce fameux document:
1. Qu'est ce que le multithreading
2. Pourquoi l'utiliser avec CVI (quelle fonctionnalité de l'application sont à faire tourner dans des threads différents) ?
3. L'utilisation des fonctions permettant de créer des threads et éventuellement des thread pools
4. Les différentes possibiité de communication inter-thread.

Passez un peu plus de temps sur l'explication concernant la planification de l'éxécution d'une fonction dans un thread, l'utilisation des timers asynchrones (pour votre acquisition à 1s) et enfin sur les thread safe queue.

Une fois ce document lu, vous aurez certainement de nouvelle question auxquelles je me ferai un plaisir de répondre.

Cordialement,

Message 2 sur 6
3 621 Visites
Bonjour,

J'avais effectivement pris connaissance de ce document... Mais après relecture j'ai trouvé mon erreur, et compris par ailleurs le passage de parametres.

Je vous présente la structure de mon programme, car un doute subsiste.

Ce programme écrit donc continuellement les enregistrement sur le HD et crée des variables, à chaque acquisition qui vont être analysé (je suis obliger de sauvegarder la totalité sur HD)

main{
gestion_affichage();
initialisation_timer();
}

fonction acquisition ONTIMER {
//Cette fonction est appelée par un timer toutes les 0.990 secondes
acquisition_des_donnees();
ecriture_data_sur_hd();
ecriture_data_dans_memoire_pour_analyse_par_thread();
CmtScheduleThreadPoolFunction(thread1)
.
.
CmtScheduleThreadPoolFunction(thread8)
}

int CVICALLBACK thread1(void* functiondata){
analyse_de_la_serie_de_donnee_1();
}
.
.
int CVICALLBACK thread8(void* functiondata){
analyse_de_la_serie_de_donnee_8();
}

Je fais l'hypothèse pour le moment qu'il n'y a pas de passage d'argument entre thread.


Cette structure est-elle correct ? Le fait de créer des threads dans une fonction appellé par un timer est-il quelquechose de faisable ? Cohérent ?

Si ma fonction appellé par le timer, tente de réecreer des nouveaux threads, alors que les précédents ne sont pas terminé, cela ne va-t-il pas être problématique ?

QUestion subsidiaire : Combien de thread peut-on créer au maximum... J'ai l'impression que les 8 ne peuvent pas être crée sur ma machine...

Je vous remercie pour votre réponse passée, votre patience, et par avance pour vos réponses futures,

Frédéric

Message Edité par FredPastis le 04-12-2007 05:15 AM

0 Compliments
Message 3 sur 6
3 614 Visites
Bonjour Fred,

Désolé pour la réponse tardive, j'étais 'out of office cette semaine' et sans accès internet.
Je vous conseille de jetter un oeil sur les timers asynchrones, lesquels permettent de plannifier l'éxécution d'une fonction de manière périodique dans un thread à part.

Concernant la manière de structurer votre code, je la trouve étrange, mais ne l'ayant pas testée, je ne saurai dire à 100% si elle doit fonctionner. Cependant, je ne vois rien qui me ferait dire que votre manière de coder ne fonctionerait pas. Ceci dit, voici comment je procèderai.

1. Un thread pour l'interface utilisateur (le thread par défaut)
2. Un thread pour l'écriture sur disque (l'écriture sur disque doit en effet être séparée de l'acquisition)
3. Autant de thread que nécessaires (8 d'après ce qe vous écrivez précédemment) pour vos différentes acquisition (cependant, vous est-il nécessaire de faire 8 threads différents ?). Chacun de ces threads se résumera à l'acquisition proprement dite, et à l'envoi des données acquises vers un organe de dialogue inter-thread (sorte de tampon)

Le but de tout ceci étant de ne jamais bloquer votre acquisition (que l'enregistrement des données sur le disque ou que l'interface utilisateur soit bloquée n'a aucune importance, mais que l'acquisition soit bloquée posera tôt ou tard des problèmes)
Pour la communication inter-thread, utilisez les thread safe queue avec une taille dynamique. Le mécanisme de lock est déjà inclu dans une thread-safe queue et en taille dynamique, vous ne rencontrerez aucun problème quels que soient les blocages éventuels des threads qui viennent lire les informations dans la queue (et 'vider' la queue). La seule limite possible serait de bloquer le thread lecteur (la queue ne ferait alors que de se remplir) jusqu'à éclater votre RAM de PC... Smiley surpris

Concernant le nombre max de thead que vous pouvez créer, il est certainement bien plus grand que ce dont vous aurez besoin. Par contre, par pool (sorte de groupement de threads), vous ne pouvez pas en avoir autant que vous le souhaitez. Le nombre est limité (de tête, mais la formule exacte est repris dans le document il me semble) à 2*nb de processeurs + 2. En l'occurence, cela veut dire que sur une machine monoprocesseur, vous pouvez avoir 4 threads par pool. Pour faire tourner plus de threads en paralèlle, créez un nouveau pool de threads, et vous aurez 4 nouveaux threads disponibles.

En espérant que cela puisse vous aider. N'hésitez pas à poursuivre dans vos questions.
Cordialement,

Message Edité par Mathieu Steiner le 04-13-2007 03:41 PM


0 Compliments
Message 4 sur 6
3 603 Visites
Bonjour,

Alors vous me conseillez de créer un thread pour l'écriture sur disque OK, je comprend et vois pourquoi.

Mais je ne comprend pas les 8 threads d'acquisition par contre... Actuellement, mon acquisition se fait uniquement par un appel à DAQmxReadBinU16 sur mes 8 canaux. Je sépare ensuite les données acquise dans différents tableaux et c'est ensuite que ces tableaux sont envoyé aux 8 threads de traitement.

Comment et quel gain m'apporterai de créer 8 thread pour l'acquisition ?

Je vais regarder de plus près les timer asynchrones...

En vous remerciant pour votre réponse,

Fredéric
0 Compliments
Message 5 sur 6
3 593 Visites

Bonjour Fred,

Je compreds votre question, mais me permets de vous retourner la question. Quel intérêt avez vous à créer 8 threads ? (le seul que je vois et que le données sont déjà "rangées" dans 8 tableaux différents)

Personnellement, je pense à un seul thread, car pour 8 voies analogiques, vous devez avoir 1 tâche dans laquelle vous avez ajouté 8 voies analogiques. Ceci dit, votre solution est correcte.

Cordialement,


0 Compliments
Message 6 sur 6
3 568 Visites