Up Right Billige Uhr und Uhrenvergleiche

Billige Uhr mit TSC

Idee

Die Abfrage eines TSC, als high resolution Timer bezeichnet (HR) kostet nichts, aber der Nachteil ist, dass sich die Taktrate des Prozessors ändern kann

Daher ist die Idee, daß hin- und wieder eine teurere gettimeofday(2)-Abfrage unsere billige Uhr kalibriert.

Überlegung lineare Interpolation

Es gibt zwei Gründe für die Interpolation aus zwei Punkten

  1. Die Taktrate könnte sich ändern, damit macht es gar keinen Sinn, eine längere Historie zu halten und da einen genauere Geschichte zu berechnen
  2. Das ausgeklügelte Berechnen kostet wieder Rechenzeit

Lineare Interpolation durch zwei Punkte (x1,y1) und (x2,y2) ergibt:

Y=(X-x2)*(y2-y1)/(x2-x1)+y2

Wir benötigen zwei Meßpunkte von der Systemuhr TSys gettimeofday(2) und zwei zugehörige von dem HR. (thr)
Mit thr=X und tsys=Y ergibt sich also:

T=(Thr-thr2)*(tsys2-tsys1)/(thr2-thr1)+tsys2

Bei einem neuen Eingang einer Systemzeit passen wir unsere Stützstellen an.

Def. Korrelationsfaktor correlationfactor = (tsys2-tsys1)/(thr2-thr1)

Dieses funktioniert durchaus mit double-Rechnungen, allerdings ist die Nutzung der Floatingpoint-Arithmetik zu teuer.

Da thr2-thr1 > tsys2-tsys1 , behelfen wir uns mit dem

Def. Inversen Korrelationsfaktor invcorrelationfactor := (thr2-thr1)/(tsys2-tsys1)

Damit ergibt sich die Formel zu: T=(Thr-thr2)/invcorrelationfactor + tsys2.

Leider zeigt der Versuch, dass es einen Fehler bis zu 1ms gibt - das ist nicht akzeptabel. Offensichtlich schneidet die Division im inversen Korrelationsfaktor uns zu viele Stellen ab.

Um mehr Stellen zu erhalten, multiplizieren wir den Nenner mit 1024 (<<10), und korrigieren im Zähler das wieder, so

T=((Thr-thr2)<<10)/invcorrelationfactor+tsys2,
mit invcorrelationfactor=((thr2-thr1)<<10)/(tsys2-tsys1)

Der Test zeigt ein befriedigtes Ergebnis.

Aufruf des Testprogrammes

clocktest [intervalllänge in s| random]

Nach jedem Intervall wird die Zeit verglichen.
Bei Random sind die Intervalle 500+EXPonentialverteilt gewählt, um eine unreglmässige Kalibrierung zu simulieren.

Tests

Linux x86_64 2.27GHz (auf vmware esxi)

Kosten gettimeofday = 1572
Kosten timesample   = 714
kosten cheapclock   = 383

d.h. Faktor 4 ist die Uhr billiger als die gettimeofday(2)

Der Fehler tritt in der letzen Stelle der us-Darstellung auf und scheint unabhängig von der Intervalllänge.

die Operationen von cheapclock auf:
100*gettimeofday 7650 ticks 1*getimeofday 76.5 ticks
100*cheap.gettime 21842 ticks 1*cheap.gettime 218.42 ticks
100*cheap.timesample 15646 ticks 1*cheap.timesample 156.46 ticks

Offensichlich ist hier die "CheapClock" teuer wie der gettimeofday-Systemaufruf !

Diese Anormalie erklärt sich durch die VSyscalls, die keinen richtigen Wechsel in den Kern vornehmen.

64bit openSUSE 11.1, Xeon 2.67 GHz

(freundliche externe Messung vergleichbar mit clockvergleich):

Kosten gettimeofday = 74 ticks
Kosten timesample   = 368 ticks
kosten cheapclock   = 145 ticks

Linux i386 2.20GHz

Kosten gettimeofday = 6664 ticks
Kosten timesample   = 45072 ticks
kosten cheapclock   = 4616 ticks

hier nur einen Faktor von 1.4. - vermutlich wird zuviel 64 bit-Arithmetik verwendet.

interessanterweise sind auch die Unterschiede bis ca. 15us und grösser als beim x86_64

clockvergleich sagt:

100*gettimeofday 212792 ticks 1*getimeofday 2127.92 ticks
100*cheap.gettime 79744 ticks 1*cheap.gettime 797.44 ticks
100*cheap.timesample 80704 ticks 1*cheap.timesample 807.04 ticks

hier ergibt sich ein Speedupfaktor von 2.6

32bit openSuSE 11.0, Pentium IV 2.8GHz

(freundliche externe Messung vergleichbar mit clockvergleich):

Kosten gettimeofday = 1092 ticks
Kosten timesample   = 45936 ticks
kosten cheapclock   = 651 ticks

Speedupfaktor von etwa 1.7

Download

cheapclock.tgz (LGPL-Lizenz , siehe AGB).
Informatik- und Netzwerkverein Ravensburg e.V Rudolf Weber