Forum: PC-Programmierung usdelay braucht zu lange


von Peter (Gast)


Lesenswert?

Hallo.

Ich habe ein Programm mit einem Thread.
Dieser Thread hat eine While(1) schleife und liest Daten ein.
Das einlesen mache ich mit readfile mit overlapped und dann regelmäßiges 
schauen ob Daten da sind.

Beim Testen ist mir aufgefallen das meine Prozessor last auf Max steigt 
sowie ich den Thread starte.
Dann habe ich mit gettime mir nach jedem 10 einlesen die Verbrauchte 
Zeit anzeigen lassen (20-30ms). Was somit ca 2-3ms pro read bedeutet.

Nun habe ich ein usdelay(50) eingebaut und nun brauche ich auf einmal 
100-120ms.

Kann mir das jemand erklären oder mir einen Tip geben wie ich dem Thread 
schlafen legen kann ohne das mir gleich alles einfriert?

von Peter (Gast)


Lesenswert?

Ich benutze usleep und nicht usdelay!

von Andreas B. (andreas_b77)


Lesenswert?

Ein usleep(50) schläft für mindestens 50 µs. Kann aber auch beliebig 
viel länger sein.

von Peter (Gast)


Lesenswert?

Ist anscheinend beliebig lang, nur wie kann ich das anders lösen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peter schrieb:
> Ich benutze usleep und nicht usdelay!

Welches Betriebssystem?

Unter Windows ist "usleep" keine Win32-API-Funktion; einen Thread legt 
man mit Sleep (oder mit einer der Wait..-Funktionen) schlafen -- die 
Wartedauer allerdings kann nur in msec angegeben werden.

Das ist auch kein Wunder, weil hier die Granularität des Schedulers ins 
Spiel kommt, und die beträgt bestenfalls 1 msec, standardmäßig sogar 
nur 10 msec.

Wenn Du kürzere Verzögerungszeiten verwenden möchtest, geht das nicht 
über den Scheduler, sondern nur mit aktivem Warten -- und das wirkt sich 
auf die Prozessorlast aus, wie Du auch schon beobachtet hast.

von Georg A. (georga)


Lesenswert?

> Welches Betriebssystem?

Overlapped klingt sehr WINdig ;) Aber da kann man doch auch mit 
WaitFor(Single)Object bequem den Treiber das Warten auf neue Daten 
erledigen lassen. Geht grob so:

OVERLAPPED ovl;
ovl.hEvent=CreateEvent(...)
ReadFile(...,&ovl)

und dann später:

WaitForSingleObject(ovl.event,INFINITE)

von Peter (Gast)


Lesenswert?

Sorry ist natürlich Windows.

Ich könnte auch 1ms warten, wenn es dann auch bei 1ms bleibt.
Das mit den 50us war nur ein Test, weil es im Ursprungs Code mal drin 
war allerdings mir 5000us.

Soll das heißen in kann nur ein Wait/ Sleep von mindestens 10ms machen?

von Peter (Gast)


Lesenswert?

Das mit den Wait Funktionen hatte ich drin, aber wenn man auf mehrere 
Geräte gleichzeitig wartet hatte das mein Timming total zerlegt.

Jetzt ohne jedes Wait ist das timming perfekt bis auf die Systemlast.
Und die muss ich jetzt noch runter bekommen.

von Georg A. (georga)


Lesenswert?

> Geräte gleichzeitig wartet hatte das mein Timming total zerlegt.

Dann musst du das besser managen ;)

> Jetzt ohne jedes Wait ist das timming perfekt bis auf die Systemlast.
> Und die muss ich jetzt noch runter bekommen.

AFAIR gibts da nichts ausser RTOS-Erweiterungen, eine garantierte 
Reaktionszeit ist ja jetzt auch mit BusyWaiting nicht gegeben. In Zeiten 
von Multicores ist zwar ein Core mit BusyWaiting nicht wirklich schlimm, 
aber an sich schon ein Zeichen, dass irgendwas am Systemdesign faul ist 
:P

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peter schrieb:
> Soll das heißen in kann nur ein Wait/ Sleep von mindestens 10ms machen?

Nein, die Granularität des Schedulers lässt sich auf 1 msec verfeinern. 
Das geht mit der Win32-API-Funktion timeBeginPeriod.

http://msdn.microsoft.com/en-us/library/windows/desktop/dd757624%28v=vs.85%29.aspx

Das muss einmal mit der gewünschten Granulariät (welchen anderen Wert 
als 1 will man hier wohl haben?) aufgerufen werden, und schon ist das 
umgestellt.

Obwohl diese Funktion in den Scheduler eingreift, kann sie von normalen 
Usermode-Programmen aufgerufen werden; sie ist/war primär für 
Multimedia-Programme und die dort erforderliche präzise Zeitsteuerung 
gedacht, bei älteren Versionen von Windows NT lag die Granulariät 
standardmäßig sogar bei 15 msec.

Zur Synchronisation mehrerer Threads lassen sich Funktionen wie 
WaitForSingleObject bzw. WaitForMultipleObjects verwenden, die auf 
verschiedene Dinge warten können, wie z.B. Events.

von Peter (Gast)


Lesenswert?

Habe mit timeBeginPeriod die Zeit auf 1ms runter geschraubt und nun habe 
ich eine saubere Pause (Sleep(1)) von 1ms in meiner Schleife drin

Habe auch noch einiges im Ablauf gedreht, hat mir gut 50% Zeitersparnis 
gebracht. Damit meine ich Anzahl Kommunikation zu Schleifen Durchläufe.

Endresultat: kann schneller kommunizieren und meine Systemlast ist auch 
runter.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.