PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wie kann man in C++ die Zeit in Millisekunden messen?



Catonga
19-08-2002, 09:40
Hallo,

Ich möchte bei verschiedenen Programmroutinen und Algorithmen die Zeit messen,
um die bestmögliche Programmroutine oder Algorithmus zu finden.
Im moment habe ich das via der time() Funktion getan, aber das ist für manche
Zwecke viel zu ungenau, da mir die time Funktion nur Werte im Sekundenbereich liefert.


Wie kann ich mit C++ die Zeit in Millisekunden (oder noch besser in Nanosekunden) messen?
Und wie geht es in C?

Tobias
19-08-2002, 13:45
Hi

man gettimeofday
ist auf Microsekunden genau.

mit gprof kannst du die Zeit, die eine Funktion benötigt, auch messen.

Tobias

Catonga
20-08-2002, 04:30
Vielen dank, ich werde mir das mal genauer anschauen. ;)

Catonga
20-08-2002, 15:54
So, ok.

Ich habe jetzt die Funktion in mein Programm eingebaut.

Leider bin ich aber auf 2 Probleme gestoßen:


1.

Laut Manpage besteht das Argument timeval, welches
bei gettimeofday verwendet wird aus:

struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};


Wenn ich jetzt eine Zeitmessung vornehme,
dann beträgt tv_sec z.b. 0 Sekunden.

tv_usec beträgt aber bei der gleichen Messung ca. 2000 Millisekunden.

Das kann ja irgendwie nicht stimmen, da ja eine Sekunde 1000 Millisekunden
beträgt, daher müßte die Anzahl der Sekunden 2 sein und nicht 0.


Kann es vielleicht sein, das dies Nanosekunden sind und nicht Millisekunden
(wie in der man Page angegeben)?




2.

Da tv_usec eine Variable vom Typ long ist neigt sie dazu
über ihren Wertebereiuch zu laufen wenn der Test zu lange dauert.
Das verfälscht natürlich die Meßergebnisse.

Wie kann ich jetzt aber vom Zeitpunkt 0 gesehen den kompletten Testdurchgang
der vielleicht 5 Sekunden dauert in Millisekunden messen?

Im moment fällt mir nur folgende Lösung ein:
Jedesmall tv_usec auf 0 setzen wenn tv_sec (also die Sekunden) um 1 erhöht wird.
Dazu benötige ich aber eine If Anweisung die zeit kostet und den Meßwert
ebenfalls unnötig verfälscht.

Alternativ dazu, würde es noch die Möglichkeit geben, eine Variable um den Wert 1 zu erhöhen, sobald tv_usec einen überlauf macht.
Danach müßte ich dann tv_usec wieder auf 0 Setzen.
Diese zusätzliche Variable wäre dann mein Multiplikator.
Also würde eine Zeitmessung aus folgender Formel bestehen:

x mal den positiven Wertebereich von tv_usec + dem letzten tv_usec Wert.

Leider benötigt diese Variante auch wieder zusätzlche Rechenschritte.

Gibt es eventuell noch andere Möglichkeiten?

Tobias
20-08-2002, 20:35
Hi

1.
Es sind Microsekunden, micro ist 10^-6, also 0.000 001.

2.
Die Zeit wird seit "the Epoch" ( irgendwann im letzten jahrtausend ).
Diese zeit wir in sekunden + microsekunden angegeben,
d.h. nach 999 999 microsekunden wird eine neue Sekunde dazugezählt.

mit long long solltes du sekunden und microsekunden als microsekunden darstellen können

Tobias

Catonga
21-08-2002, 05:46
Original geschrieben von Tobias


1.
Es sind Microsekunden, micro ist 10^-6, also 0.000 001.


Ach Microsekunden, das erklärt natürlich alles,
und ich dachte die ganze Zeit an Millisekunden,
so ein dummer Fehler von mir aber auch.
Keine Ahnung was ich gestern getrunken haben muß. :rolleyes:

Nochmals vielen vielen Dank, das erklärt natürlich auch Punkt 2. :)

HeadShot
23-08-2002, 07:54
1.

Laut Manpage besteht das Argument timeval, welches
bei gettimeofday verwendet wird aus:

struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};


also lesen sollte man schon können :D

Catonga
23-08-2002, 08:51
Original geschrieben von HeadShot


also lesen sollte man schon können :D

Ach was, mich stört das kein bischen.
Ich weiß ja, das du ebenfalls tausend Fehler machst
von daher bin ich nicht der einzige. :D

HeadShot
23-08-2002, 10:50
Original geschrieben von Catonga


Ach was, mich stört das kein bischen.
Ich weiß ja, das du ebenfalls tausend Fehler machst
von daher bin ich nicht der einzige. :D

jaja, immer von sich selbst auf andere schliessen .. hat man schon gerne :rolleyes:

jgbauman
23-08-2002, 17:23
Bei Benchmarks auf eine Multitaskingsystem sollte man aber aufpassen was man mißt:
- reale Zeit: Wirklich verstrichene Zeit während der Aufgabe (enthält auch Zeitverbrauch anderer gleichzeit laufender Prozesse),e.g. gettimeofday()
- Prozesszeit: Wirklich nur die CPU-Zeit die ein Prozess zugeteilt bekommt, z.B. getrusage().

Der unterschied wird umso wichtiger je länger so ein Benchmakr dauert. Leider hat die
Prozesszeit meist nur eine Auflösung von ~ 0.1 sec. Allerdings wird AFAIK daran gearbeitet die CPU timestamp counter dafür zu benutzten (zählt die Taktsignal der CPU).

Den kann man übrigens für x86 (>=P5) ganz leicht selber auslesen (-Wno-long-long unterdrückt Fehlermeldung wegen long long bei -ansi):

typedef unsigned long long tsc_t;

tsc_t rdtsc() {
unsigned long long tsc;
__asm__ __volatile__ ("rdtsc":"=A"(tsc));
return tsc;
}


Damit erhält man auf einer 1 Ghz CPU Nanosekundenauflösung ;-)