Präzision von (QT-)Timern

Verschiedenes zu Qt
lx2
Beiträge: 75
Registriert: 5. Mai 2009 03:13

Präzision von (QT-)Timern

Beitrag von lx2 »

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 !)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Diese Verzögerungen glaube ich nicht. Und ja MS hat recht ungenaue Timer, aber trotzdem denke ich nicht dass es so schell zu solchen Abweichungen kommt.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
kater
Beiträge: 306
Registriert: 29. Dezember 2009 01:13
Wohnort: Darmstadt

Beitrag von kater »

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. (IM Gegensatz zu pure C/Assembler) IMO

Aber am wichtigsten ist es: Was hast du programmiert? (Zeig den Code!)
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

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 finde diese Aussage sehr präzise => Es ist vom Betriebssystem abhängig.
lx2
Beiträge: 75
Registriert: 5. Mai 2009 03:13

Beitrag von lx2 »

upsala hat geschrieben:
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 finde diese Aussage sehr präzise => Es ist vom Betriebssystem abhängig.
Ich eben nicht! Was sind denn bitte diese "other systems that we have tested " und mal ganz ehrlich, wer benutzt denn heut noch win98.

Zum Code:

Code: Alles auswählen

   QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(labelUpdaten()));
    timer->start(100);
Oder einfach mal das QtCreator Projekt im Anhang anschauen.

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 :shock: (Athlon xp 4000+ , win xp pro, 2gig ram, 4% cpu auslastung)
Dateianhänge
qttimertesttest.rar
(8.86 KiB) 231-mal heruntergeladen
chrislo1976
Beiträge: 105
Registriert: 24. Februar 2008 09:45

Beitrag von chrislo1976 »

Hallo!
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.
Wenn da hin und wieder ein Tick "lautlos" verschluckt wird, ist die Abweichung erklärbar.

Gruß,
Christian
lx2
Beiträge: 75
Registriert: 5. Mai 2009 03:13

Beitrag von lx2 »

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.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

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!
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
lx2
Beiträge: 75
Registriert: 5. Mai 2009 03:13

Beitrag von lx2 »

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!
Hey Chris, ich hab doch den Code (sogar das ganze Projekt) schon anghängt. Schau mal meinen vorletztes posting

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]
Uwe
Beiträge: 176
Registriert: 9. Oktober 2005 13:37
Wohnort: München

Beitrag von Uwe »

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!
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.

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
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Naja, gibt es denn dann überhaupt (außerhalb von QT) eine einigermaßen gute Lösung?
Jein ....

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 ..
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

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 :shock: (Athlon xp 4000+ , win xp pro, 2gig ram, 4% cpu auslastung)
Laufzeit: 3'20'', Anzeige 2000. Schaut für mich absolut exakt aus.
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:

Beitrag von Christian81 »

Uwe hat geschrieben:kann so ein QTimeEvent sogar viel zu spät kommen.
Ich habe nie was anderes behauptet... ich habe mich auf seine Aussage bezogen:
Beide Methoden Führen bei Intervallen von 100ms schon nach einer Minute zu deutlichen Zeitverzögerungen ( >1 Sekunde !)
Die Timer werden alle korrekt abgehandelt, wenn er einen Event-Stau provoziert indem er die Eventloop nie aufruft... naja
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Uwe
Beiträge: 176
Registriert: 9. Oktober 2005 13:37
Wohnort: München

Beitrag von Uwe »

Christian81 hat geschrieben:Die Timer werden alle korrekt abgehandelt, wenn er einen Event-Stau provoziert indem er die Eventloop nie aufruft... naja
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.

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
lx2
Beiträge: 75
Registriert: 5. Mai 2009 03:13

Beitrag von lx2 »

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

Code: Alles auswählen

i++;
ui->label->setText(QString::number(i));


3. Also die Aussagen von Uwe sind am präzisesten.
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.
Genau das ist anscheinend der kritische Punkt: Das Neuzeichnen!
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:
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.
Danke!

4. @Christian81
Die Timer werden alle korrekt abgehandelt, wenn er einen Event-Stau provoziert indem er die Eventloop nie aufruft... naja
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.

Was würdest du denn dagegen machen???
Antworten