[C++] Timer

[Moepi]1

Lt. Commander
Registriert
Jan. 2002
Beiträge
1.233
Hallo,
ist es möglich, interm in einem C++-Programm einen Timer mitlaufen zu lassen, der am Ende ausgibt, wie lange das Programm lief? Es soll also am Ende das Ergebnis einer Berechnung inkl. der dafür benötigten Zeit zurückgegeben werden.
 
speicher die aktuelle zeit zu beginn des programmablaufes in einer globalen variable.
registriere dann mit atexit (mittels fkt-pointer vom typ (*funktion)(void) )ein abschluß-fkt in der du die dann aktuelle zeit nimmst und die differenz zu der bei startzeit ermittelt und diese dann ausgibst. das ist glaub ich der einfachste weg.
atexit ist ein c89 standard-fkt. funktioniert aber auch mit c++.
 
okay... - lösungsansatz verstanden, aber keinen Plan, was ich tun soll :D
 
Code:
#include <windows.h>

DWORD start=GetTickCount();

//berechnungen;

DWORD dauer=GetTickCount()-start;
GetTickCount gibt die Zeit zurück, seitdem Windows läuft (in Millisekunden).
 
Code:
time_t anfangszeit; //globale varialben sind häßlich aber hier brauchbar.

static void abbruch_fkt(void)
{
     cout << difftime( time(0),anfangszeit) << " Sekunden sind vergangen" << endl;
}

int main(int argc, char**argv)
{
   anfangszeit=time(0);
   atexit(abbruch_fkt);
....
}

so müsste das gehen.
 
auch wenn es völlig offtopic ist: warum neigen so viele windows-prorgrammierer dazu, windows fkt.s zu verwenden auch wenn die portable (als c/c++-standard) lösung genauso lang und/oder aufwendig ist?
 
Danke! Jetzt kann ich meinen Assembler Code Benchmarken ;)
 
@ghorst: Zu meiner Rechtfertigung: Ich habe bewusst die Windows API-Funktion gewählt, weil sie eben die Millisekunden zurückgibt und nicht nur die Sekunden. [Moepi]1 hat ja nichts über den Zeitraum gesagt. Wenns es sich um mehrere Sekunden handelt, dann kann man natürlich deine Methode verwenden.

//edit
@ghorst: btw: Edit-Button.
 
Zuletzt bearbeitet:
Ich bin auf jeden Fall dankbar für die Millisekunden - Fibonacci Zahlen, die man in nem 32Bit Register unterbringt, brauchen nunmal nicht allzulange ;)
 
Oaaar ne ned schonnewidda Fibonacci. Hatten das die ganzen letzten Wochen in der Schule, heute Schlussprüfung geschrieben, jetz wäre das Thema endlich abgehakt... und ich geh online, auf CB, rein in die Programmierer-Sektion, siehe da: ein Hilferuf zu einem Timercode! JA, fix rein, und jetz das .... der ganze Tag im Eimer ;)
 
Naja. Für die ersten 40 Fibonacci Zahlen brauch mein Prozessor (AMD64 3200+ auf WinXP32) 3.5s. C++ Programme sind aber natürlich langsamer als reiner Assembler-Code, wenn du den richtigen Algorithmus verwendest. Ich hab meinen in C++ jetzt mit Rekursion geschrieben, weiß jetzt nicht ob es mit Iteration schneller geht.

BTW: Im ersten Post schreibst du "C++-Programm" jetzt ist es auf einmal ein Assembler?

@AndrewPoison: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 ;)
 
Zuletzt bearbeitet:
Fibonacci-Zahlen sind mit Abstand das schlechteste Beispiel für Rekursion. Die iterative Lösung ist genauso trivial und hat lineare Komplexität, anstatt exponenzielle.


Die Zeitmessungsmethoden, die C++ zur Verfügung stellt sind eher bescheiden. Wenn, dann bietet sich clock() an. time() ist je nach benötigter Genauigkeit ziemlich bescheiden. GetTickCount ist aber ähnlich ungeeignet, da der Zähler nicht wirklich gleichmäßig läuft und nur im 55ms Takt arbeitet.
Für verlässliche Performancemessung bietet sich tatsächlich die entsprechende API der Betriebssystems an. Unter Windows ist das QueryPerformanceCounter und QueryPerformanceFrequency. Die Funktionen arbeiten auch beim Einsatz mehrerer Prozessoren (mit Hyperthreading hat man zwei logische Prozessoren) korrekt.


"Timer" ist übrigens die falsche Bezeichnung für die gesuchte Lösung. Darunter vesteht man überlicher Weise etwas, was nach einer definierten Zeit ein Ereignis auslöst.

Die Variante mit dem atexit ist auch nicht so gut, da man hier unter Umständen den Deinitialisierungsaufwand der C-Laufzeit-Umgebung mitmisst. Okay, es aber kommt immer auf die benötigte Genauigkeit an. Am besten lässt man die zu messende Funktion eh nicht nur einmal laufen, sondern gleich 100, 1000, 10000 mal oder sonstwie oft laufen.


Wie schnell sie tatsächlich ist, findet man damit nicht wirklich raus. Einmal hängt das vom Algorithmus ab, dann von der Ausprogrammierung, dann vom Compiler und dann noch vom Prozessor. Aussagekräftig sind die Zahlen, die man erhält also nicht wirklich. Benutz lieber einen Profiler und schau drauf, wo die Zeit im Algorithmus bleibt.



Das C++ Programme natürlich langsamer als reiner Assemblercode sind, halte ich mal für ein ganz gewaltiges Gerücht.
 
@Quidoff und sogar das kann man ohne jeden aufwand portabel machen, wenn man weiß, dass das programm unter etwa 1h laufen wird. (bei allem anderen ist ein genauigkeit über einer sekunde eh nur augenwischerrei. genau wie die windows angabe in millisekunden.).
der messbarezeitraum ist abhängig von der implementierung von clock_t.
das mit atexit ist natürlich nur nötig, wenn das programm mehr als einen beendungsroutine hat.
Code:
clock_t anfangszeit; //globale variablen sind häßlich aber hier brauchbar.

static void abbruch_fkt(void)
{
     cout << double(clock - anfangszeit) /CLOCKS_PER_SEC << " Sekunden sind vergangen" << endl;
}

int main(int argc, char**argv)
{
   anfangszeit=clock();
   atexit(abbruch_fkt);
....
}

btw. ich mag die edit-funktion nicht, wenn ich grobe änderungen an einem beitrag durchführen. ist ein erfahrungswert, nach ein paar sehr hitzigen diskussionen und leuten dazwischen, die ihre posts nachträglich wies böse geändert haben.
 
7H3 N4C3R schrieb:
Fibonacci-Zahlen sind mit Abstand das schlechteste Beispiel für Rekursion. Die iterative Lösung ist genauso trivial und hat lineare Komplexität, anstatt exponenzielle.
hab ich dsa überlesen, dass er das mit rekursion gelöst hat?
7H3 N4C3R schrieb:
Das C++ Programme natürlich langsamer als reiner Assemblercode sind, halte ich mal für ein ganz gewaltiges Gerücht.
assembler ist dann schneller, wenn man ihn _tatsächlich_ für den verwendeten prozessor/chipsatz/speicheranbindung anpasst und jedes byte einzeln und von hand bewußt eingibt. also auch dinge wie bus anbindung, befehlsverarbeitung im prozessor (inkl. der sprungvorhersagen) und cache-aufteilung beachtet. wenn man das nicht tut, fährt man mit einem compiler, der wenigstens die hälfte davon beachtet deutlich besser.
die konsequenz aus _effektiver_ assembler programmierung ist, dass man seinen handoptimierten assembler code nur auf der einen rechner benutzen sollten. bei allem anderen läuft man gefahr sich von einem c/c++/fortran-compiler abhängen zu lassen.
 
ghorst schrieb:
hab ich dsa überlesen, dass er das mit rekursion gelöst hat?
Quidoff hatte das geschrieben. Deshalb.

Natürlich kann liebevoll angepasster, handoptimierter Assembercode schneller sein. An einen modernen Compiler heranzukommen ist aber ein hartes Stück Arbeit. Dann noch perfekt für einen ganz bestimmten Prozessor zu optimieren, ist noch schlimmer. Performancetuning auf dieser Ebene ist nicht wirklich sinnvoll. Solange der Algorithmus gut ist (vor allem Komplexität), ist das okay. Optimieren kann man immernoch, wenn ein Profiler sagt, dass genau an dieser Stelle Bedarf ist. Premature optimization is the root of all evil. (Verfrühte Optimierung ist die Wurzel alles Bösen)
 
Zuletzt bearbeitet:
7H3 N4C3R schrieb:
Quidoff hatte das geschrieben. Deshalb.
aso. hatte den letzten thread über fibonacci nur überflogen. aber das mit rekursion zu machen ist schon echt eine leistung.
Premature optimization is the root of all evil. (Verfrühte Optimierung ist die Wurzel alles Bösen)
man kann es nicht besser ausdrücken. es hat keinen sinn unwartbaren assembler-code zu erzeugen, wenn man bei bestmöglicher programmierung den billigsten compilern aus aktueller produktion nur noch 1% bis max. 10% voraus ist. (wenn man den c/c++ code mit ähnlich viel liebe behandelt, wie den assembler code. also erst hirn, dann tastatur.)
die zeiten in denen c und insbesondere c++ compiler wirklich langsamen code ausgespuckten haben sind sehr lange vorbei.
der griff zum assembler lohnt eigentlich heute nur noch wenn man auf einem mikrokontroller unterwegs, aber da auch nur, weil der c-code schnell genauso lang und unübersichtlich wird, wie der assembler code... (die dinger haben einfach viel zu viele spezialfunktionen.)
 
Zurück
Oben