OVH Cloud OVH Cloud

prehemption

27 réponses
Avatar
Ambassadeur Kosh
on a 2 valeurs à aller pecher sur des ports differents.
le probleme est que entre ces deux "acquisitions", le thread peut se faire
prehempter.
c'est normal, l'ordonanceur fait son boulot.

la question est, comment faire en sorte de ne pas être prehempté. paske
sinon, ça cree un décalage énorme dans le temps (100ms, ça n'est pas rien)
et du coup, le couple de valeurs n'a pas de sens.

bon, c'est le même probleme que pour le port série, donc ça doit se résoudre
d'une façon trés voisine. mais comment faire en sorte d'avoir les bonnes
propriétés : cad pas de perte de donnée, pas d'attente active, pas de
prehemption au moment ou je pique mes deux valeurs pour avoir la
"simultaneité". en clair, comment écrire le Read.

j'ai un début d'idée, mais je voudrais bien un exposé technique des habitués
du forum avant de faire pencher la balance. ( Arnaud, Quentin ou Amcd pour
ne citer qu'eux :) )

d'avance merci

10 réponses

1 2 3
Avatar
Ambassadeur Kosh
> et en mettant ca dans un thread TIME_CRITICAL...


pas bête.
mais n'est ce pas qu'un paliatif ?
ceci dit, ci on diminue le nombre d'objets mal mesurés suffisament, on
pourra mettre les cas restant sur le dos du materiel :)

> entre le moment ou la donnée arrive physiquement sur le port et ou le


read
> est debloqué (c'est à dire entre t0 et (1)) , il peut s'écouler un temps
> trés long, et plusieurs threads ont pu prendre la main (normal, y'a pas
> urgence, le systeme bufferise le COM). résultat identique au précedent.


faut essayer puis constater.

Le système bufferise le COM si on veut. En principe le FileRead rend la


main
des que le nombre d'octet demandé est arrivé , sauf timeout... sa vitesse


de
réaction est fonction aussi du baudrate, à combien etes vous configuré !?


38400. la je découvre un truc.

Peut être que dans votre cas , vous devriez utiliser le port com en
événementiel... je fais un peu de remoting par COM , j'ai jamais constaté
des 100ms de délai sur acquisition, même avec des thread de basse


priorité,
donc je ne crois pas que votre délai soit du au multitache windows (à


moins
que vous soyez en train de copier 4 fichiers de 30 Go en permanence sur le
réseau évidemment)


ben y'a du monde dans le train en fait.
une optimisation bien couteuse en calculs qui tourne en permanence, des
écritures régulieres dans la base de données, une autre appli qu'on lance de
temps en temps pour faire du reporting sur la base et de l'impression. plus
quelques threads que je soupsonne de faire de l'attente active. (j'ai cru
comprendre que cette technique bancale, avait tendance a tirer un peu plus
que de rigueur sur le processeur)

et tout ça fait que on a des écarts importants sur la mesure.
Avatar
Vincent Burel
"Ambassadeur Kosh" wrote in message
news:bmjr93$moa$
> et en mettant ca dans un thread TIME_CRITICAL...
pas bête.
mais n'est ce pas qu'un paliatif ?



Ben non. Pourquoi !?

> réaction est fonction aussi du baudrate, à combien etes vous configuré


!?
38400. la je découvre un truc.



ca fait 4 octets par ms à peu près... donc faut voir la taille des données
que vous recevez et déduire l'erreur temporelle inhérente.

ben y'a du monde dans le train en fait.
une optimisation bien couteuse en calculs qui tourne en permanence, des
écritures régulieres dans la base de données, une autre appli qu'on lance


de
temps en temps pour faire du reporting sur la base et de l'impression.


plus
quelques threads que je soupsonne de faire de l'attente active. (j'ai cru
comprendre que cette technique bancale, avait tendance a tirer un peu plus
que de rigueur sur le processeur)



de l'attente active !? vous voulez dire une boucle du style :

while (f_continue)
{
if (thereissomethingtodo) DoIt();
Sleep(10);
}

et tout ça fait que on a des écarts importants sur la mesure.



Ben, faudrait peut-être essayer d'abord de faire cette acquisition avec le
minimum de truc en route... Après ca dépend de la précision que vous voulez
atteindre, faut savoir que rien n'est précis en dessous de la ms sous
Windows et en terme de temps-réel on considère dans l'audio que rien ne peut
se faire fiablement en dessous de 5 ms.

Vincent Burel
Avatar
Johann Dantant
"Vincent Burel" a écrit dans le message de
news:bmjstd$uqj$

"Ambassadeur Kosh" wrote in message
news:bmjr93$moa$



> ben y'a du monde dans le train en fait.
> une optimisation bien couteuse en calculs qui tourne en permanence, des
> écritures régulieres dans la base de données, une autre appli qu'on


lance
de
> temps en temps pour faire du reporting sur la base et de l'impression.
plus


[...]
Ben, faudrait peut-être essayer d'abord de faire cette acquisition avec le
minimum de truc en route... Après ca dépend de la précision que vous


voulez
atteindre, faut savoir que rien n'est précis en dessous de la ms sous
Windows et en terme de temps-réel on considère dans l'audio que rien ne


peut
se faire fiablement en dessous de 5 ms.



Et au delà de ça, utiliser le thread TIME_CRITICAL pour effectuer les
acquisitions et les "empiler" avec chacune son timestamp dans une file
d'attente... SURTOUT ne pas risquer de bloquer le thread d'acquisition sur
un accès disque (ou pire sur une requête SQL). Je ne sais pas si on peut
faire ça avec les objets d'échanges standards. AMHA il faut s'allouer une
zone de mémoire partagée suffisamment importante, s'assurer qu'elle ne sera
pas swapée, et envisager une exclusion mutuelle qui ne fera jamais attendre
le thread d'acquisition. C'est surement possible, mais au prix d'un travail
que j'ai du mal à évaluer d'ici...

Enfin, sinon, chez nous on fait de "l'acquisition critique" de messages qui
se promènent sur un bus CAN. Un bête micro-controlleur permet de récupérer
tous les messages sans en louper aucun, et, "quand le PC a le temps", il
vient les relire via une bête liaison série à 9600 bauds. Seule contrainte,
avoir un débit d'acquisition bien inférieur à celui sur la liaison série, et
avoir suffisamment de RAM dans le micro pour bufferiser quelques secondes.
En l'occurrence, 1 journée de technicien électronique + 1 journée de soft
embarqué, c'est pas gratuit mais c'est pas cher, et c'est réutilisable à
l'infini dans un environnement similaire.

J.D.
Avatar
Ambassadeur Kosh
"Vincent Burel" a écrit dans le message de
news:bmjstd$uqj$

"Ambassadeur Kosh" wrote in message
news:bmjr93$moa$
> > et en mettant ca dans un thread TIME_CRITICAL...
> pas bête.
> mais n'est ce pas qu'un paliatif ?

Ben non. Pourquoi !?


parceque j'ignore comment fonctionne le TIME_CRITICAL.
j'ai observé à l'oeil les conséquences globales, mais je me demandais si un
thread TIME_CRITICAL ne pouvait pas rester prehemptible pour filer la main à
un autre thread qui n'a rien foutu depuis 48 heures.

ca fait 4 octets par ms à peu près... donc faut voir la taille des données
que vous recevez et déduire l'erreur temporelle inhérente.


c'est un Int64

de l'attente active !? vous voulez dire une boucle du style :

while (f_continue)
{
if (thereissomethingtodo) DoIt();
Sleep(10);
}



tout pile. avec le 10 qu'on transforme en 1 en accusant au passage "la
gestion des threads d'etre une vraie m... sous windows" parcequ'on loupe des
thereissomethingtodo :)

Ben, faudrait peut-être essayer d'abord de faire cette acquisition avec le
minimum de truc en route... Après ca dépend de la précision que vous


voulez
atteindre, faut savoir que rien n'est précis en dessous de la ms sous
Windows et en terme de temps-réel on considère dans l'audio que rien ne


peut
se faire fiablement en dessous de 5 ms.



eh ben c'est pas gagné... pfffff....
merci pour ces infos.
Avatar
Vincent Burel
"Ambassadeur Kosh" wrote in message
news:bmlgsg$d03$

"Vincent Burel" a écrit dans le message de
news:bmjstd$uqj$
>
> "Ambassadeur Kosh" wrote in message
> news:bmjr93$moa$
> > > et en mettant ca dans un thread TIME_CRITICAL...
> > pas bête.
> > mais n'est ce pas qu'un paliatif ?
>
> Ben non. Pourquoi !?
parceque j'ignore comment fonctionne le TIME_CRITICAL.



comme un autre thread , sauf qu'il est de priorité 15 (sur une appli
normale) et que donc rien ne peut lui passer dessus (sauf un autre thread de
même priorité, puisque windows distribue les resources d'abord au thread de
même priorités ensuite aux thread de priorité plus basse si il y a le temps
: ce qui veut dire que votre Thread TIME CRITICAL doit "respirer" sinon ca
va vous bloquer même la souris. )

j'ai observé à l'oeil les conséquences globales, mais je me demandais si


un
thread TIME_CRITICAL ne pouvait pas rester prehemptible pour filer la main


à
un autre thread qui n'a rien foutu depuis 48 heures.



Alors vous verrez que le thread TIME_CRITICAL peut se faire préempter,
typiquement par des taches systèmes qui sont considérées par le noyau comme
prioritaire : le réseau souvent, mais aussi tout ce qui au niveau hardware
est plus prioritaire que ce que vous utilisez dans votre THREAD_CRITICAL.

Et c'est la que Windows n'est pas fait pour ce genre d'appli (et dans votre
cas il vaudrait carrément mieux avoir une carte d'acquisition qui mesure le
temps elle-même pour vous le transmettre) car le système fait ce qu'il veut,
comme il veut , en fonction de ce qui est installé. Shématiquement, si la
carte son est de meilleurs priorité d'interruption que le port série, ben
"le BIP" d'une messagebox, peut vous préempter.

Sous Win98 , j'ai un exemple terrible. Je lance un flux audio en
TIME_CRITICAL meme avec un bufferisation énorme, style 50 ou 100ms. Et quand
je ballade ma souris sur le l'icone de fermeture d'une fenètre, j'ai l'info
bulle qui apparait "CLOSE" et cette apparition me casse le flux, c'est à
dire que cela provoque une coupure dans le son. Alors pourquoi !? je n'en
sais rien, c'est peut-être Windows, c'est peut-être mon display driver de
G450 dual screen... on en sait rien et c'est ce qui fait que Windows n'est
pas fiable pour tout ce qui concerne les contraintes temporelles...

> ca fait 4 octets par ms à peu près... donc faut voir la taille des


données
> que vous recevez et déduire l'erreur temporelle inhérente.
c'est un Int64

> de l'attente active !? vous voulez dire une boucle du style :
>
> while (f_continue)
> {
> if (thereissomethingtodo) DoIt();
> Sleep(10);
> }

tout pile. avec le 10 qu'on transforme en 1 en accusant au passage "la
gestion des threads d'etre une vraie m... sous windows" parcequ'on loupe


des
thereissomethingtodo :)



Ca consomme un peu, tout dépend de la valeur dans le Sleep (sans vulgarité
:-) et si DoIt() est appelé souvent, parce que bon, le test d'un flag , même
par rapport à un Sleep(1), c'est négligeable.

Vincent Burel
Avatar
Vincent Burel
"Johann Dantant" wrote in message
news:bmlh4m$ikn$
"Vincent Burel" a écrit dans le message de
news:bmjstd$uqj$
>
> "Ambassadeur Kosh" wrote in message
> news:bmjr93$moa$

> > ben y'a du monde dans le train en fait.
> > une optimisation bien couteuse en calculs qui tourne en permanence,


des
> > écritures régulieres dans la base de données, une autre appli qu'on
lance
> de
> > temps en temps pour faire du reporting sur la base et de l'impression.
> plus
[...]
> Ben, faudrait peut-être essayer d'abord de faire cette acquisition avec


le
> minimum de truc en route... Après ca dépend de la précision que vous
voulez
> atteindre, faut savoir que rien n'est précis en dessous de la ms sous
> Windows et en terme de temps-réel on considère dans l'audio que rien ne
peut
> se faire fiablement en dessous de 5 ms.

Et au delà de ça, utiliser le thread TIME_CRITICAL pour effectuer les
acquisitions et les "empiler" avec chacune son timestamp dans une file
d'attente... SURTOUT ne pas risquer de bloquer le thread d'acquisition sur
un accès disque (ou pire sur une requête SQL).



c'est certain , le thread TIME_CRITICAL doit faire le minimum de chose

Je ne sais pas si on peut
faire ça avec les objets d'échanges standards. AMHA il faut s'allouer une
zone de mémoire partagée suffisamment importante, s'assurer qu'elle ne


sera
pas swapée, et envisager une exclusion mutuelle qui ne fera jamais


attendre
le thread d'acquisition. C'est surement possible, mais au prix d'un


travail
que j'ai du mal à évaluer d'ici...



Généralement la mémoire qu'on utilise de manière permanente n'est jamais
swapée ou alors on rajoute 128 Mo... (on peut faire un globalalloc en
mémoire physique, c'est pas dur, mais franchement je ne pense pas que ce
soit nécessaire)
pour le partage des données, sur du critique , la meilleur solution c'est de
faire des copy dans une liste d'attente ou un buffer tournant à l'intérieur
d'une section critique. (La section critique est l'élément de
synchronization le plus rapide - arpres l'incrément atomique - et c'est
simple d'utilisation) Surtout dans ce cas , ou sur Mono processeur, de part
la différence de priorité qu'il y aura entre le thread d'acquisition et le
thread d'analyze, la section critique ne sera jamais réellement en
concurrences.

Enfin, sinon, chez nous on fait de "l'acquisition critique" de messages


qui
se promènent sur un bus CAN. Un bête micro-controlleur permet de récupérer
tous les messages sans en louper aucun, et, "quand le PC a le temps", il
vient les relire via une bête liaison série à 9600 bauds. Seule


contrainte,
avoir un débit d'acquisition bien inférieur à celui sur la liaison série,


et
avoir suffisamment de RAM dans le micro pour bufferiser quelques secondes.
En l'occurrence, 1 journée de technicien électronique + 1 journée de soft
embarqué, c'est pas gratuit mais c'est pas cher, et c'est réutilisable à
l'infini dans un environnement similaire.



voila, c'est la meilleur méthode sous Windows, avoir un un bout
d'electronique additionnel qui fait la partie délicate.

A+
Vincent Burel
Avatar
Ambassadeur Kosh
> while (f_continue)
[...]
Ca consomme un peu, tout dépend de la valeur dans le Sleep (sans vulgarité
:-) et si DoIt() est appelé souvent, parce que bon, le test d'un flag ,


même
par rapport à un Sleep(1), c'est négligeable.



lol.
Avatar
Ambassadeur Kosh
> En français, c'est vite vu : que dalle ;o).


merci de ne pas me laisser d'espoir :)


En anglais, les livres de base sont ceux de Walter Oney et de Art
Baker/Jerry Lozano. Quelques sites :

- http://www.chsw.com/ddk/
- http://students.cs.byu.edu/~nbushman/drivers.htm
- http://www.osronline.com/article.cfm?id5



y'a apparement tout ce qu'il faut pour attaquer le sujet.
merci tout plein
Avatar
adebaene
"Vincent Burel" wrote in message news:<bmjstd$uqj$...
"Ambassadeur Kosh" wrote in message
news:bmjr93$moa$
> > et en mettant ca dans un thread TIME_CRITICAL...
> pas bête.
> mais n'est ce pas qu'un paliatif ?

Ben non. Pourquoi !?



Parce que :
1) Laisser un thread avec ce niveau de priorité pendant longtemps (ie
plus de quelques ms) a la facheuse tendance à déstabiliser Windows
(certains de ces services indsipensables n'ayant plus de temps
processeur pour travailler).

2) On peut toujours être préhempté par une interruption.

Il me semble qaue la solution serait d'écrire un driver pour le port
série qui, lorsqu'il recoit l'interruption de données disponible,
lance immédiatement l'acquisition sur la carte dédiée (éventuellement
en levant une autre INT gérée par le driver de la carte
d'acquisition). Par contre, je ne connais pas assez le DDK pour donner
des conseils de mise en oeuvre de ce genre de choses.

Arnaud
Avatar
Vincent Burel
"Arnaud Debaene" wrote in message
news:
"Vincent Burel" wrote in message


news:<bmjstd$uqj$...
> "Ambassadeur Kosh" wrote in message
> news:bmjr93$moa$
> > > et en mettant ca dans un thread TIME_CRITICAL...
> > pas bête.
> > mais n'est ce pas qu'un paliatif ?
>
> Ben non. Pourquoi !?

Parce que :
1) Laisser un thread avec ce niveau de priorité pendant longtemps (ie
plus de quelques ms) a la facheuse tendance à déstabiliser Windows
(certains de ces services indsipensables n'ayant plus de temps
processeur pour travailler).



Wow, faut pas diaboliser le TIME_CRITICAL ! au pire vous aurez une
comportment en saccade si le Thread TIME_CRITICAL fait des traitement long
de 30ms par exemple toutes les 50 ms. Mais bon faut savoir qu'est ce que
vous voulez prioriser dans votre application. Mais une instabilité ! non.
sauf si le thread ne "respire" pas. c'est sur, si vous lancez un Thread TIME
CRITICAL pour copier 50 Go de données, alors là votre Windows pourra
paraitre un peu bloqué jusqu'à la fin de l'opération ou presque... Mais dans
l'exemple qui nous concerne, le thread en question ne fera pratiquement rien
puisqu'il passera son temps à attendre un event du port série via la
fonction read... donc vous le sentirez même pas qu'il est TIME_CRITICAL..

2) On peut toujours être préhempté par une interruption.

Il me semble qaue la solution serait d'écrire un driver pour le port
série qui, lorsqu'il recoit l'interruption de données disponible,
lance immédiatement l'acquisition sur la carte dédiée (éventuellement
en levant une autre INT gérée par le driver de la carte
d'acquisition). Par contre, je ne connais pas assez le DDK pour donner
des conseils de mise en oeuvre de ce genre de choses.



qu'est ce que ca change , que vous écriviez le driver ou pas , c'est pas
vous qui allez dire à Windows que le port série doit être plus prioritaire
que le controler IDE et la carte réseaux. Et puis les drivers communiquent à
l'application par event, et c'est windows qui s'occupe des event. Même dans
l'audio, les faiseurs de driver n'arrivent pas à garantir l'arrivée des
event à temps. parce que le mécanisme Windows ne le permet tout simplement
pas.

Vincent Burel
1 2 3