Arateris
Messages postés6Date d'inscriptionsamedi 25 mars 2006StatutMembreDernière intervention18 juillet 2007
-
18 juil. 2007 à 00:16
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019
-
18 juil. 2007 à 18:08
Bonjour,
pour une appli en C/C++, j'aurais
besoin qu'un thread se mette en pause pour une durée courte (1,2,5 ou 10ms) de
facon fiable. Mon but étant de faire un simulateur, cette précision est
importante.
En faisant des tests avec des fonctions qui regarde l'heure
:
Je vois qu'un sleep(1) dure environs 1.8 ms
(l'appel de la fonction current_time est négligeable, de l'ordre de la centime
de millisecondes)
un Sleep(2) dure 2.8ms également en moyenne (avec des rares
pointes à 17-33ms).
J'ai lu de nombreuses fois sur le net que les sleep
courts sont imprécis (et je l'ai bien constaté) puisqu'ils bloquent le thread
pour une durée minimale.
Pour contourner ce problème, j'ai essayé un truc du
genre :
void attendre(unsigned long
time){
double start = 1000*current_time(); // en
millisecondes.
SetThreadPriority(GetCurrentTh<wbr>read(),15);
while
(1000*current_time() < (start+time)){ }</wbr>
SetThreadPriority(GetCurrentTh<wbr>read(),0);
printf("TIME
after: %f\n",1000*current_time()<wbr>-start);
}
</wbr></wbr>
J'arrive à obtenir des temps d'attentes tout à fait
raisonnables (1.00ms) et assez stable, mais j'ai également des pointes
ponctuelles au dela des 10-20ms d'attentes.
Le fait de changer de priorité le
thread n'a en fait que peu d'influence, surtout que le but n'est pas de bloquer
le reste de la machine sur laquelle tourne une application serveur video et une
socket de réception sur un thread parallèle.
J'ai meme essayé de combiner un Sleep(1) puis while
(1000*current_time() < (start+time)) (pour une attente de 2ms par exemple..)
Là encore je suis la plupart du temps stable, mais avec les mêmes
pointes.
Y a-t-il une solution pour éviter d'avoir des
pointes d'attentes si élevée ou moins fréquement?
Le fait d'avoir 3 choses qui tournent en même temps
sur le pc (Win XPau passage) est surement une des clés du problèmes, mais pas de
la solution.
Passer sur un ensemble complètement linéaire
(serveur+socket+appli en un seul thread) résoudrait-il le problème?(ou alors de
toute facon, le fait d'avoir windows et n'importe quoi derrière ca plante
tout..?)
victorcoasne
Messages postés1101Date d'inscriptionjeudi 24 avril 2003StatutMembreDernière intervention23 juillet 20237 18 juil. 2007 à 01:03
Bonjour,
Pourquoi as-tu besoin d'un traitement toutes les millisecondes.
Tu n'es pas tout seul sur le système ;)
Soit tu lance une boucle pour conserver les ressources restantes soit tu te créé un système d'exploitation (bonne chance).
PS : Ce n'est pas à prendre sur un ton de critique mais sur un conseil disant que le système il faut bien qu'il tourne et que il y a 1000ms dans une seconde toutes ne sont pas réservés à un seul programme [vous me suivez ?].
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 18 juil. 2007 à 10:07
Clair qu'un système multi taches préemptif n'est pas fait pour du temps réel mais pour que l'action utilisateur ait toujours priorité.
Il faut y ajouter qu'un appel de fonction n'est pas gratuit, minimum de 4 octets PUSHés (registre EIP). Si comme ici il y a dans cette fonction 2 appels externes et une division en flottant, alors pas de quoi s'étonner qu'on se retrouve loin de la ms.
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 18 juil. 2007 à 12:41
Salut,
Sur un processeur cadencé à 2GHz, il y a un front d'horloge toutes les 0,000.000.000.5 secondes, et 2.000.000 de fronts d'horloge par millisecondes.
Avec ces deux millions de fronts, on peut bien espérer 500.000 instructions sur un mauvais processeur, à partir du moment ou le processeur travail sans attendre le dur ou autre chose. On peut sans problème chronométrer une boucle tournant à quelques dizaines de micro secondes quand elle n'est pas interrompue par un autre thread.
Mais bon comme dit plus haut, le préamptif fait que Windows va donner du temps à d'autre thread. Il y a pas de solution gratuites sous XP (LabView...), mais y a des Linux temps réel.
La solution pour avoir du (presque) temp réel sous Windows passe probablement par la modification de la config du PIT.
A ce que j'ai compris c'est ce compteur qui est responsable de lancer
une interruption IRQ0, et cette interruption lance l'ordonanceur qui
peut avoir l'idée de choisir un autre thread.
Ce composant à pas l'air trop compliqué, mais a ce que j'ai compris, il faut passer en adressage réel pour avoir accès aux adresses qui le concerne...
Vous n’avez pas trouvé la réponse que vous recherchez ?
Arateris
Messages postés6Date d'inscriptionsamedi 25 mars 2006StatutMembreDernière intervention18 juillet 2007 18 juil. 2007 à 14:10
J'arrive à obtenir des temps d'attentes tout à fait raisonnables (1.00ms) et assez stable, mais j'ai également des pointes ponctuelles au dela des 10-20ms d'attentes.
Le fait de changer de priorité le thread n'a en fait que peu d'influence, surtout que le but n'est pas de bloquer le reste de la machine sur laquelle tourne une application serveur video et une socket de réception sur un thread parallèle.
J'ai meme essayé de combiner un Sleep(1) puis while (1000*current_time() < (start+time)) (pour une attente de 2ms par exemple..) Là encore je suis la plupart du temps stable, mais avec les mêmes pointes.
Y a-t-il une solution pour éviter d'avoir des pointes d'attentes si élevée ou moins fréquement?
Le fait d'avoir 3 choses qui tournent en même temps sur le pc (Win XPau passage) est surement une des clés du problèmes, mais pas de la solution.
Passer sur un ensemble complètement linéaire (serveur+socket+appli en un seul thread) résoudrait-il le problème?(ou alors de toute facon, le fait d'avoir windows et n'importe quoi derrière ca plante tout..?)
je vais me renseigner sur le PIT..
merci de vos réponse :)
Arateris
Messages postés6Date d'inscriptionsamedi 25 mars 2006StatutMembreDernière intervention18 juillet 2007 18 juil. 2007 à 14:20
Oupss problème avant le post précedent.. (on peut pas éditer un post?? si un modo passe par ici, il peut supprimer le message d'avant qui copie-colle mon premier message)
Bon je recommence :
Mon problème n'est pas d'atteindre la milliseconde, ca j'y arrive. Le soucis c'est d'assurer un taux d'erreur minimum. Par taux d'erreur, comprendre timeout trop long.
J'ai bidouillé un peu ma fonction pour integrer le current_time et gagner du temps d'execution...bref
J'ai fait des essais et j'arrive à un taux de timeout > 1.01ms (pour 1ms demandée) qui tourne autour de 1%. ( PC = Windows XP, P4@2GHz, 512Mo)
C'est un taux assez faible, mais mon application a des besoins assez stricts, spécialement, il faut éviter les grosses erreurs, puisque 0,1% des timeout dépassent les 2ms et certains vont jusqu'a atteindre 60ms!
Et comme mon appli fait tourner des milliers de ces timeout..ca arrive forcément un moment ou un autre.
Je vais me renseigner sur PIT.
Je crois malheureusement que je pourrais pas faire grand chose de plus sur windows facilement. (et je suis contraint à utiliser windows..)
en tout cas merci de vos réponses.
Arateris
Messages postés6Date d'inscriptionsamedi 25 mars 2006StatutMembreDernière intervention18 juillet 2007 18 juil. 2007 à 14:20
Oupss problème avant le post précedent.. (on peut pas éditer un post?? si un modo passe par ici, il peut supprimer le message d'avant qui copie-colle mon premier message)
Bon je recommence :
Mon problème n'est pas d'atteindre la milliseconde, ca j'y arrive. Le soucis c'est d'assurer un taux d'erreur minimum. Par taux d'erreur, comprendre timeout trop long.
J'ai bidouillé un peu ma fonction pour integrer le current_time et gagner du temps d'execution...bref
J'ai fait des essais et j'arrive à un taux de timeout > 1.01ms (pour 1ms demandée) qui tourne autour de 1%. ( PC = Windows XP, P4@2GHz, 512Mo)
C'est un taux assez faible, mais mon application a des besoins assez stricts, spécialement, il faut éviter les grosses erreurs, puisque 0,1% des timeout dépassent les 2ms et certains vont jusqu'a atteindre 60ms!
Et comme mon appli fait tourner des milliers de ces timeout..ca arrive forcément un moment ou un autre.
Je vais me renseigner sur PIT.
Je crois malheureusement que je pourrais pas faire grand chose de plus sur windows facilement. (et je suis contraint à utiliser windows..)
en tout cas merci de vos réponses.
Arateris
Messages postés6Date d'inscriptionsamedi 25 mars 2006StatutMembreDernière intervention18 juillet 2007 18 juil. 2007 à 14:24
Il n'y pas d'interet à une opération toute les millisecondes (dans mon cas).
J'ai besoin de creer une pause de 1,2 ou 5ms pour mon appli, afin de simuler le temps d'une transmission. La pause ne me sert pas à générer une boucle régulière.
Arateris
Messages postés6Date d'inscriptionsamedi 25 mars 2006StatutMembreDernière intervention18 juillet 2007 18 juil. 2007 à 15:06
(re) Bonjour,
Je simule une liaison radio. Il faut donc modéliser l'envoi de paquet, qui est nettement plus lent qu'en local, ethernet ou même passage de paramètre intra-applicatifs.
Je vais essayer de compenser les timeout erronés ainsi que le temps de traitement de mon appli en faisant non pas des temps de pause fixes mais basé sur une sorte d'horloge qui sera incrémenté mathématiquement et sur laquelle devra se baser mon appli pour "s'arreter" (en fait, il ne s'arrete plus, mais il boucle sur la récupération du current_time..pas top niveau utilisation processus, mais ca gene pas tant que ca au final)
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 18 juil. 2007 à 18:08
Surtout pas de timer, c'est quasi pire que Sleep().
Faudrait dédier un PC à ce processus. A cet effet, désactiver presque tous les services et tu fais une boucle perpétuelle dans un thread. Avant la boucle tu calcules combien de ticks il faut pour faire ta ms et dedans te suffit de l'appeler.
Modéle ici, tu verras si convient:
http://www.asmfr.com/code.aspx?id=23802