Salut,
Déjà un grand bonjour à tous.
J'ai un soucis de réactivité avec un thread, j'ai trouvé un moyen de le contourner probablement le problème mais ce n'ai pas une solution très élégante
* Description :
L'application est du W32 natif (C) compilé sur VC2008. Elle doit gérer un capteur de pression très finement et prendre des mesures à des instants très précis par une demande provenant du réseau. L'application est donc connecté a un serveur. (Mode client/serveur UDP avec des socket DATAGRAM)
* Architecture :
En gros, j'ai 3 threads de lancé :
- 1 thread "thread_recv", bloqué sur un recvfrom(), dès qu'un paquet arrive il est mis dans un spool, puis signal un evenement "evt_recu" et retourne a son recvfrom().
- 1 thread "thread_network", bloqué sur un WaitForMultipleObject, il attend le "evt_recu" (pour traiter traite le spool) et un evenement d'arrêt du thread.
- 1 thread "thread_sensor", bloqué sur un WaitForMultipleObject, il attend un evenement "evt_sensor_data" qui indique que des données sont prêtent dans un buffer (provenant du driver du capteur)
L'événement "evt_sensor_data" arrive toute les 32059 µs environs (32ms).
Le driver met à dispo un buffer qui contient des données sur 32 mesures (une toutes les millisecondes). une boucle traite donc ces 32 mesures
A chaque mesure traité, un compteur "sample_count" est incrémenté. (incrémenté toutes les millisecondes). A chaque événement "evt_sensor_data" le compteur est donc incrémenté en tout de 32.
(32 fois sample_count++ pour être précis)
Le thread "thread_sensor" ne met que 27 µs à traiter le buffer, puis attend 32ms le prochain buffer, etc...
* But
Mon but est de pouvoir, par l'intermédiaire du serveur, demander à 2 machines en même temps de m'envoyer leur valeur courante de "sample_count" pour connaitre le décalage temporelle entre les 2.
* Problème
J'ai implémenté cette mécanique, ca fonctionne, mais pas assez finement. En effet, lorsque j'envois la trame de demande du "sample_count" par le serveur, je récupère des valeurs multiple de 32 de la part des clients. (-32, 32, -64, 64, etc...) .
Je souhaite obtenir la valeur exacte du "sample_count", donc que mon thread réseau "préempte" mon thread "sensor"
* Précision
- J'ai déja essayé de "yielder" mon thread après chaque incrémentation de "sample_count" ( SwitchToThread() )
- J'ai mis des priorité plus haute sur mes threads reseaux THREAD_PRIORITY_HIGHEST, j'ai même essayé THREAD_PRIORITY_TIME_CRITICAL
- Je n'ai pas protégé mon compteur "sample_count" car je ne fais qu'un simple "sample_count++;" qui me semble t'il est une opération atomique ?
* Piste de résolution
J'ai l'impression que mon traitement est trop rapide 27 µs pour traité les données de 32 ms temporelle, je pense que mes temps de bufferisation, spool et traitement de la requête réseau sont plus long que 27 µs.
Mon idées est de ralentir de thread entre chaque incrémentation du compteur et de yielder le thread.
Par exemple laissé bouclé pendant 200 µs entre chaque incrémentation soit 6.4 ms mangé sur le quantum, que mes thread reseau pourrait donc prendre la main durant ces laps de temps...
Par contre je devrais utiliser le QueryPerformanceCounter, car je ne vois pas comment attendre autrement, proprement 200µs (sur des machines a vitesse de proc différente.
* Questions :
- Mon raisonnement est t'il valable ?
- Est t'il courant de ralentir un thread ?
- N'y a t'il pas meilleur solution ?
- Si non avec vous une idées autre que QPC ou une boucle ASM pour attendre ~200µs (dans cette ordre de grandeur < 1 ms)
Merci d'avance pour vos conseils
Merci de m'avoir lu
Molox
Partager