Präzision von (QT-)Timern
Präzision von (QT-)Timern
Hi,
laut http://doc.trolltech.com/4.6/timers.html hat man ne ziehmlich schwammige Aussage über die Präzision von Timern.
Ich benutze Windows Xp und Windows7.
Gibt es Algorithmen oder sogar QT interne Klassen, die wirklich eine 1ms-Genauigkeit schaffen, oder wird es einfach bedingt duch die Gegebenheiten des Betriebssystem (viele Threads, Scheduling ...) einfach nie möglich sein, das in Windows XP / 7 zu realisieren???
Mein Programm benutzt QTimer und QTimeLine.
Beide Methoden Führen bei Intervallen von 100ms schon nach einer Minute zu deutlichen Zeitverzögerungen ( >1 Sekunde !)
laut http://doc.trolltech.com/4.6/timers.html hat man ne ziehmlich schwammige Aussage über die Präzision von Timern.
Ich benutze Windows Xp und Windows7.
Gibt es Algorithmen oder sogar QT interne Klassen, die wirklich eine 1ms-Genauigkeit schaffen, oder wird es einfach bedingt duch die Gegebenheiten des Betriebssystem (viele Threads, Scheduling ...) einfach nie möglich sein, das in Windows XP / 7 zu realisieren???
Mein Programm benutzt QTimer und QTimeLine.
Beide Methoden Führen bei Intervallen von 100ms schon nach einer Minute zu deutlichen Zeitverzögerungen ( >1 Sekunde !)
-
Christian81
- Beiträge: 7319
- Registriert: 26. August 2004 14:11
- Wohnort: Bremen
- Kontaktdaten:
Joar ich halte das für möglich. Ohnehin ist es mit einem Betriebsystem nicht so weiteres möglich genau zu messen.
In Qt ist erstmal alles in Klassen /OO gekapselt. Da kann an der ein oder anderen Stelle ein Overhead erzeugt werden der für diese Spezielle Aufgabe garnicht gebraucht wird.
M Gegensatz zu pure C/Assembler) IMO
Aber am wichtigsten ist es: Was hast du programmiert? (Zeig den Code!)
In Qt ist erstmal alles in Klassen /OO gekapselt. Da kann an der ein oder anderen Stelle ein Overhead erzeugt werden der für diese Spezielle Aufgabe garnicht gebraucht wird.
Aber am wichtigsten ist es: Was hast du programmiert? (Zeig den Code!)
Ich finde diese Aussage sehr präzise => Es ist vom Betriebssystem abhängig.The upper limit for the interval value is determined by the number of milliseconds that can be specified in a signed integer (in practice, this is a period of just over 24 days). The accuracy depends on the underlying operating system. Windows 98 has 55 millisecond accuracy; other systems that we have tested can handle 1 millisecond intervals.
Ich eben nicht! Was sind denn bitte diese "other systems that we have tested " und mal ganz ehrlich, wer benutzt denn heut noch win98.upsala hat geschrieben:Ich finde diese Aussage sehr präzise => Es ist vom Betriebssystem abhängig.The upper limit for the interval value is determined by the number of milliseconds that can be specified in a signed integer (in practice, this is a period of just over 24 days). The accuracy depends on the underlying operating system. Windows 98 has 55 millisecond accuracy; other systems that we have tested can handle 1 millisecond intervals.
Zum Code:
Code: Alles auswählen
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(labelUpdaten()));
timer->start(100);
Testetet das mal bitte. Also bei mir hängt das nach ner minute 3 sekunden hinterher. Nach 10 Minuten ist er sogar schon 57 Sek zu spät
- Dateianhänge
-
- qttimertesttest.rar
- (8.86 KiB) 230-mal heruntergeladen
-
chrislo1976
- Beiträge: 105
- Registriert: 24. Februar 2008 09:45
Hallo!
Gruß,
Christian
Wenn da hin und wieder ein Tick "lautlos" verschluckt wird, ist die Abweichung erklärbar.Accuracy and Timer Resolution
Timers will never time out earlier than the specified timeout value and they are not guaranteed to time out at the exact value specified. In many situations, they may time out late by a period of time that depends on the accuracy of the system timers.
The accuracy of timers depends on the underlying operating system and hardware. Most platforms support a resolution of 1 millisecond, though the accuracy of the timer will not equal this resolution in many real-world situations.
If Qt is unable to deliver the requested number of timer clicks, it will silently discard some.
Gruß,
Christian
Naja, gibt es denn dann überhaupt (außerhalb von QT) eine einigermaßen gute Lösung?
Mann kann ja in C++ Assembler Befehle einbinden.
Meint Ihr sowas umgeht dan das Problem, oder werd ich trotzden noch ungenauigkeiten haben. Ziel ist es zumindest eine 100ms-Akkuranz hinzubekommen.
Was mich jetzt echt immer brennender Interessiert: was sind die Betriebssysteme die die Trolls getestet haben.
Wenns Linux war kann man sich ja ne LiveCd basteln und da das Programm laufen lassen.
Hat jemand Linux und kann mal einen 100ms-Timer testen.
Mann kann ja in C++ Assembler Befehle einbinden.
Meint Ihr sowas umgeht dan das Problem, oder werd ich trotzden noch ungenauigkeiten haben. Ziel ist es zumindest eine 100ms-Akkuranz hinzubekommen.
Was mich jetzt echt immer brennender Interessiert: was sind die Betriebssysteme die die Trolls getestet haben.
Wenns Linux war kann man sich ja ne LiveCd basteln und da das Programm laufen lassen.
Hat jemand Linux und kann mal einen 100ms-Timer testen.
-
Christian81
- Beiträge: 7319
- Registriert: 26. August 2004 14:11
- Wohnort: Bremen
- Kontaktdaten:
Hey Chris, ich hab doch den Code (sogar das ganze Projekt) schon anghängt. Schau mal meinen vorletztes postingChristian81 hat geschrieben:Also nochmal.
Ein Timer der alle 100ms etwas auslösen sollte (also nicht immer wieder neu) wird auch alle 100ms feuern und nicht nach wenigen Sekunden auf einmal falsch gehen. Zeig uns Code!
Hab aber was interessantes gefunden:
http://www.online-tutorials.net/system/ ... 9-244.html
bzw.: http://msdn.microsoft.com/en-us/library ... 85%29.aspx[/url]
Bei Qt Timern passiert gar nichts asynchron, sondern es wird ganz banal am Ende der Qt Eventloop überprüft ob bei einem der angelegten Timer die Zeit abgelaufen ist um gegebenfalls ein Timer Event zuzustellen. D.h ein mit Hilfe von QTimer aufgezogener Timer ist fast immer zu spät ( und nie zu früh). Wenn das Abarbeiten eines der vorherigen Events lange dauert ( z.B irgendein aufwändiges Zeichnen ) kann so ein QTimeEvent sogar viel zu spät kommen.Christian81 hat geschrieben:Also nochmal.
Ein Timer der alle 100ms etwas auslösen sollte (also nicht immer wieder neu) wird auch alle 100ms feuern und nicht nach wenigen Sekunden auf einmal falsch gehen. Zeig uns Code!
Wenn man halbwegs genaue Intervalle benötigt ( z.B zum Abgreifen von Werten an externen Schnittstellen ) würde ich eine eigenen Thread empfehlen und dort ausschliesslich mit Betriebssytemaufrufe arbeiten.
Mit QTime::elapsed() bekommst Du dagegen verlässliche Werte im Millisekunden Genauigkeit. Wenn es genauer sein soll kannst Du dir die Implementierung von QwtSystemClock::elapsed() aus dem Qwt Projekt http://qwt.svn.sourceforge.net/viewvc/q ... iew=markup anschauen.
Uwe
Jein ....Naja, gibt es denn dann überhaupt (außerhalb von QT) eine einigermaßen gute Lösung?
Du musst dein system umstellen ... oder ein echtzeitbetriebssystem das zu deinen parametern passt, waehlen ...
eigentlich braucht man die timer selber nie so genau, aber oft braucht man eine recht genaue angabe ueber die abweichung.
Linux und windows nehmen sich da technisch bedingt vond er genauigkeit eh nicht viel. einzig unterschied iss, wie der scheduler arbeitet ... kann auf einem system zu mehr oder weniger genau werden wie das andere, aber prinzipiell ungenau iss alles.
Das "genausste" was Du bekommst aufn PC (ohne extra hardware) sind die ticks durch den systemtaktgeber ...
die sind wiederum vom Quarz und dessen geute sowie betriebstemp abhaengig. Das quarz iss meist nen 08/15 teil, womit man nie genau messen kann ... iss auch wurscht ... du kannst die anzahl der ticks pro sekunde abfragen fuern ersten lauf. das ist weder genau noch sonstwas, sondern nur nen richtwert, aber quasi iss das deine interne PC uhr, die im bereich weniger ns konstant (und nicht genau) laeuft. Allerdings als irgendweine zeiteinheit. Wenn du nun absolut genaue zeiten brauchst, musst du die zeiten noch gegen eine verlaessliche quelle korrelieren. dazu gibts sogar protokolle feur mehrere uebertragungsmedien (fuer TCP/IP und internet gibts auch was). du kannst aber auch nen DCF77 Empfaenger an den PC direkt anschliessen, dann wirst um paar Stufen genauer beim korrelieren...
Wenn du lange genug und genau korrelierst, schwankungen mit einbeziehst, kannst du kleinere zeiteinheiten sogar auf unter 1µs Genauigkeit glattrechnen ...
Wie gesagt du musst nur damit rechnen, das keinerlei PC timer genau kommt, sondern immer zu spaet, wie oben beschrieben, und du die verspaetung immer mit einrechnen(und klar, auch ermitteln) musst.
Ciao ..
Laufzeit: 3'20'', Anzeige 2000. Schaut für mich absolut exakt aus.lx2 hat geschrieben:Testetet das mal bitte. Also bei mir hängt das nach ner minute 3 sekunden hinterher. Nach 10 Minuten ist er sogar schon 57 Sek zu spät(Athlon xp 4000+ , win xp pro, 2gig ram, 4% cpu auslastung)
AthlonIIX3 435, mit gedrosselten 800MHz, 4GB RAM DDR3-1333 CL7, alles neue Hardware.
Kann es sein dass dein Rechner schon etwas älter ist?
Ich lass jetzt zum Spaß mal länger laufen, denke aber nicht dass es da groß nen Unterschied geben wird.
Die Timerfrequency hab im im Kernel auf 1000Hz gestellt, möglich wären auch 2000, seh ich aber keinen Grund so zu übertreiben.
// sooo
15'10'' -> Anzeige 9100: Treffer versenkt
-
Christian81
- Beiträge: 7319
- Registriert: 26. August 2004 14:11
- Wohnort: Bremen
- Kontaktdaten:
Ich habe nie was anderes behauptet... ich habe mich auf seine Aussage bezogen:Uwe hat geschrieben:kann so ein QTimeEvent sogar viel zu spät kommen.
Die Timer werden alle korrekt abgehandelt, wenn er einen Event-Stau provoziert indem er die Eventloop nie aufruft... najaBeide Methoden Führen bei Intervallen von 100ms schon nach einer Minute zu deutlichen Zeitverzögerungen ( >1 Sekunde !)
MfG Christian
'Funktioniert nicht' ist keine Fehlerbeschreibung
'Funktioniert nicht' ist keine Fehlerbeschreibung
Dem Codeschnippsel kann man entnehmen, daß die Applikation irgendwelche Labels updaten will also in jedem Fall etwas neuzeichnen will - eventuell läuft da aber auch noch die Layoutmaschine mit allen möglichen Folgeaktionen.Christian81 hat geschrieben:Die Timer werden alle korrekt abgehandelt, wenn er einen Event-Stau provoziert indem er die Eventloop nie aufruft... naja
Wenn das länger als 100 ms dauert wird die Applikation die Timer Events nie rechtzeitig bekommen. Das ist dann aber nur eine Folge und nicht die Ursache des eigentlichen Problems.
Uwe
So jetzt erst mal alle zu ruhe kommen 
1. Ich hab mich leider in der Thread-Überschrift nicht präzise genug ausgedrückt. Mein Ziel ist es meinen Counter mit 100ms-Genauigkeit Events abfeuern zu lassen. Mir geht es nicht darum ein Zeitintervall möglichst auf Mikrosekunden zu messen, sondern, dass die Events wirklich rechtzeitig kommen. Und das auch noch nach 10 Minuten.
Hintergrund: Das Programm ist ein Übungsprogramm für Gedächtnismeister, die sich Zahlen merken und damit auf Meisterschaften gehen. Solche Leude: http://www.memoriade.net/. Es generiert Zufallszehlen und sollte bis zu einer Geschwindigkeit von 100ms zuverlässig funktionieren.
Wenn Die mit dem Programm üben und 'n Rekord aufstellen und dann auf die Meisterschaft gehen und merken: "mist das Programm hat mir nicht die richtigen Zeiten ausgegeben" ist das sch.... .
Und da gehts tatsächlich manchmal um Millisekunden. (Für Weltrekorde usw.)
2. Ich finde es sehr komisch, dass Leute einfach drauflosreden ohne sich das Testprojekt mal angeschaut zu haben. Ich hab doch extra ein Projekt in den Anhang gesteckt. Da kann man doch mal kurz reinschauen oder einfach mal schnell kompilieren bevor man mitredet und irgendwelche "Halbwahrheiten" kreirt.
Für alle die dafür keine Zeit haben, hab ich extra die Funktion die aufgerufen wird "labelUpdaten()" genannt. Die mach eigentlich nichts anderes als einen integer erhöhen und das Label upzudaten
3. Also die Aussagen von Uwe sind am präzisesten.
Ich hab das ganze (wie franzf) jetzt auch mal mit einer Ubuntu 8.10 LiveCD getestet. Und siehe da: Sogar nach 30 min läuft alles rund auf 1ms genau.
Was mir auch aufgefallen ist, wenn man die Fenstergröße in Windows ändert friert der Counter auch kurzfristig ein.
Das beste wird also tatsächlich die schon von Uwe beschriebene Methode sein, um das ganze für Windows brauchbar zu machen:
4. @Christian81
Was würdest du denn dagegen machen???
1. Ich hab mich leider in der Thread-Überschrift nicht präzise genug ausgedrückt. Mein Ziel ist es meinen Counter mit 100ms-Genauigkeit Events abfeuern zu lassen. Mir geht es nicht darum ein Zeitintervall möglichst auf Mikrosekunden zu messen, sondern, dass die Events wirklich rechtzeitig kommen. Und das auch noch nach 10 Minuten.
Hintergrund: Das Programm ist ein Übungsprogramm für Gedächtnismeister, die sich Zahlen merken und damit auf Meisterschaften gehen. Solche Leude: http://www.memoriade.net/. Es generiert Zufallszehlen und sollte bis zu einer Geschwindigkeit von 100ms zuverlässig funktionieren.
Wenn Die mit dem Programm üben und 'n Rekord aufstellen und dann auf die Meisterschaft gehen und merken: "mist das Programm hat mir nicht die richtigen Zeiten ausgegeben" ist das sch.... .
Und da gehts tatsächlich manchmal um Millisekunden. (Für Weltrekorde usw.)
2. Ich finde es sehr komisch, dass Leute einfach drauflosreden ohne sich das Testprojekt mal angeschaut zu haben. Ich hab doch extra ein Projekt in den Anhang gesteckt. Da kann man doch mal kurz reinschauen oder einfach mal schnell kompilieren bevor man mitredet und irgendwelche "Halbwahrheiten" kreirt.
Für alle die dafür keine Zeit haben, hab ich extra die Funktion die aufgerufen wird "labelUpdaten()" genannt. Die mach eigentlich nichts anderes als einen integer erhöhen und das Label upzudaten
Code: Alles auswählen
i++;
ui->label->setText(QString::number(i));3. Also die Aussagen von Uwe sind am präzisesten.
Genau das ist anscheinend der kritische Punkt: Das Neuzeichnen!Wenn das Abarbeiten eines der vorherigen Events lange dauert ( z.B irgendein aufwändiges Zeichnen ) kann so ein QTimeEvent sogar viel zu spät kommen.
Ich hab das ganze (wie franzf) jetzt auch mal mit einer Ubuntu 8.10 LiveCD getestet. Und siehe da: Sogar nach 30 min läuft alles rund auf 1ms genau.
Was mir auch aufgefallen ist, wenn man die Fenstergröße in Windows ändert friert der Counter auch kurzfristig ein.
Das beste wird also tatsächlich die schon von Uwe beschriebene Methode sein, um das ganze für Windows brauchbar zu machen:
Danke!Wenn man halbwegs genaue Intervalle benötigt ( z.B zum Abgreifen von Werten an externen Schnittstellen ) würde ich eine eigenen Thread empfehlen und dort ausschliesslich mit Betriebssytemaufrufe arbeiten.
4. @Christian81
Das ist im endeffekt jetzt genau der Knackpunkt. Windows schafft das Neuzeichnen nicht , Linux schon. Habsogar grad mal ein 1ms intervall getestet. während Windows krampfhaft versucht der Darstellung nachzukommen läuft in Linux alles astrein.Die Timer werden alle korrekt abgehandelt, wenn er einen Event-Stau provoziert indem er die Eventloop nie aufruft... naja
Was würdest du denn dagegen machen???