Zeitmessung std::chrono
-
hustbaer schrieb:
Wenn man nebenbei viele andere Programme laufen lässt (die viel CPU Zeit saugen) sind die Ergebnisse auf Multitaskingsystemen doch immer etwas daneben - ganz egal wie man misst.
Wieso? Meinst du die minimalen Verluste, die man bekommt, wenn zwischendurch ein anderer Task arbeitet und man die CPU-Pipeline wieder füllen muss? Das ist doch wirklich praktisch nichts. Aber die Echtzeit zu messen anstatt der CPU-Zeit gibt dir einen Fehlerfaktor von 1/CPU-Last, was dann eben sehr leicht sehr groß werden kann.
Die period der Clock ist die Länge eines Ticks.
Die Clocks ticken aber nicht Tick für Tick, sondern üblicherweise mehrere Ticks auf einmal.
Die Effektive Auflösung kann man soweit ich weiss gar nicht abfragen.Sicher? Bei clock() ist das so, aber die Beschreibung von den chrono clocks klingt anders. Ich habe es aber nicht ausprobiert, sondern mich nach der Dokumentation gerichtet.
Zeitmessung schrieb:
Ich hab mal alle drei Clocks, die chrono anbietet, durchprobiert. Die Zeiten stimmen aber bei allen drei. In welchem Fall würden die Zeiten denn nicht mehr stimmen, SeppJ?
Die messen ja auch alle drei das gleiche mit unterschiedlichen Feinheiten. Miss mal die CPU-Zeit deines Programms, die sollte so gegen 0 gehen.
-
SeppJ schrieb:
hustbaer schrieb:
Wenn man nebenbei viele andere Programme laufen lässt (die viel CPU Zeit saugen) sind die Ergebnisse auf Multitaskingsystemen doch immer etwas daneben - ganz egal wie man misst.
Wieso? Meinst du die minimalen Verluste, die man bekommt, wenn zwischendurch ein anderer Task arbeitet und man die CPU-Pipeline wieder füllen muss? Das ist doch wirklich praktisch nichts.
Speicherbandbreite, geteilte Rechenwerke, Spinlocks und die 1000 anderen Sachen an die ich jetzt nicht denke.
Das kann einiges ausmachen.Aber die Echtzeit zu messen anstatt der CPU-Zeit gibt dir einen Fehlerfaktor von 1/CPU-Last, was dann eben sehr leicht sehr groß werden kann.
Hö?
Wenn mein Programm nur einen Fred verwendet kann ich mit quasi jeder beliebigen Clock messen und werde korrekte Ergebnisse bekommen. Und wenn es mehrere Freds verwendet ist auch oft interessant wie viel Zeit auf der Uhr an der Wand vergangen ist -- man muss dann halt wissen was man messen will und was man gemessen hat.Die period der Clock ist die Länge eines Ticks.
Die Clocks ticken aber nicht Tick für Tick, sondern üblicherweise mehrere Ticks auf einmal.
Die Effektive Auflösung kann man soweit ich weiss gar nicht abfragen.Sicher?
Ich musste jetzt gerade an die Bundeslade denken
OK, gaaanz sicher bin ich mir nicht. Aber 99%.
clock::ratio
ist ja statisch, und da die erreichbare Genauigkeit oft erst zur Laufzeit bekannt ist kann es schonmal nicht genau stimmen.ps: gaaanz bin ich mir dass es MSVC so umsetzt wie ich gesagt habe (was natürlich nicht heisst dass es standardkonform wäre)...
-
hustbaer schrieb:
Speicherbandbreite, geteilte Rechenwerke, Spinlocks und die 1000 anderen Sachen an die ich jetzt nicht denke.
Das kann einiges ausmachen.Meiner Erfahrung nach absolut vernachlässigbar. Aber:
hustbaer schrieb:
Aber die Echtzeit zu messen anstatt der CPU-Zeit gibt dir einen Fehlerfaktor von 1/CPU-Last, was dann eben sehr leicht sehr groß werden kann.
Hö?
Wenn mein Programm nur einen Fred verwendet kann ich mit quasi jeder beliebigen Clock messen und werde korrekte Ergebnisse bekommen. Und wenn es mehrere Freds verwendet ist auch oft interessant wie viel Zeit auf der Uhr an der Wand vergangen ist -- man muss dann halt wissen was man messen will und was man gemessen hat.Was hat das mit Threads zu tun? Wenn dein Programm nur 50% CPU-Last bekommt, weil gleichzeitig ein anderes Programm mit gleicher Priorität läuft, dann misst du eine doppelt so große Echtzeit wie das Programm eigentlich bräuchte.
Und ja, wenn dein Programm parallelisiert ist, dann ist Echtzeit vermutlich auch nicht das was du wissen möchtest, schließlich will man ja allgemeine wissen, wie viel CPU-Leistung ein Programm verbraucht hat, damit man einschätzen kann, wie viel Echtzeit es auf einem anderen System braucht.
-
hustbaer schrieb:
MSVC 11 RC verwendet z.B. für alle
std::
Clocks die Systemzeit (was total bekloppt ist weil es unter Windows fürsteady_clock
den Tick-Count gäbe und fürhigh_resolution_clock
QueryPerformanceCounter
).
Und die Systemzeit unter Windows hat ne Auflösung von irgendwo zwischen 1 und 15ms.Nachdem hustbaer das geschrieben hatte, hab ich mir mal QueryPerformanceCounter angeschaut, herausgekommen ist das:
namespace resolution { static const double ns = 1000000000.0; static const double us = 1000000.0; static const double ms = 1000.0; static const double s = 1.0; } class stopwatch { private: double res; double pc_freq; __int64 start_time; __int64 stop_time; public: stopwatch(double r = resolution::ms) : res(r), pc_freq(0.0), start_time(0), stop_time(0) {} void start() { LARGE_INTEGER li; if( !QueryPerformanceFrequency(&li) ) cerr << "QueryPerformanceFrequency Not Available"; pc_freq = double(li.QuadPart)/res; QueryPerformanceCounter(&li); start_time = li.QuadPart; } void stop() { LARGE_INTEGER li; QueryPerformanceCounter(&li); stop_time = li.QuadPart; } double elapsed() { return (stop_time-start_time)/pc_freq; } }; int main() { stopwatch timer(resolution::us); timer.start(); vector<int> v(2000,1); timer.stop(); cout << endl << timer.elapsed() << " us"; // ~22.58 us }
Mit dieser Genauigkeit kann ich gut Leben.
SeppJ schrieb:
Was hat das mit Threads zu tun? Wenn dein Programm nur 50% CPU-Last bekommt, weil gleichzeitig ein anderes Programm mit gleicher Priorität läuft, dann misst du eine doppelt so große Echtzeit wie das Programm eigentlich bräuchte.
Das Problem habe ich bei QueryPerformanceCounter wohl immer noch. Aber da ich nun im us-Bereich messen kann, bin ich erstmal zufrieden.
Falls einer einen Fehler in der Stopwatch Klasse findet, bitte melden.
Danke euch.
-
Zeitmessung schrieb:
SeppJ schrieb:
Was hat das mit Threads zu tun? Wenn dein Programm nur 50% CPU-Last bekommt, weil gleichzeitig ein anderes Programm mit gleicher Priorität läuft, dann misst du eine doppelt so große Echtzeit wie das Programm eigentlich bräuchte.
Das Problem habe ich bei QueryPerformanceCounter wohl immer noch.
Nein, hast du nicht. Ist dir nicht klar, was CPU-Zeit ist und was im Vergleich dazu deine Armbanduhr anzeigt?
Was hast du überhaupt vor?
-
SeppJ schrieb:
Nein, hast du nicht. Ist dir nicht klar, was CPU-Zeit ist und was im Vergleich dazu deine Armbanduhr anzeigt?
Hmm, ich dachte die CPU-Zeit bezieht sich auf alle Cores?
SeppJ schrieb:
Was hast du überhaupt vor?
Ich habe insgesamt 1000
std::pair
. Ein pair besteht aus einem Namen (std::string) und einem Wert (int). Ein STLContainer soll sich um die Paare kümmern. Der Name dient der Identifikation. Ich kenne alle Namen und mich interessieren die daszugehörigen Werte.Nehme ich
std::vector
so brauch ich für jeden Zugriff auf ein Elementstd::find_if
. Nun will ich messen, wie viel Zeit es mich kostet, wenn ich auf 1, 2, 3, 4, 5... Paare nacheinander zugreife.Nehme ich
std::map
, so ist der Key der Name und der Value der Wert. Für einen Zugriff brauche ich nur noch den operator[]. Ich will jetzt auch hier messen, wie viel Zeit es mich kostet, wenn ich auf 1, 2, 3, 4, 5... Paare nacheinander zugreife.
-
SeppJ schrieb:
Zeitmessung schrieb:
SeppJ schrieb:
Was hat das mit Threads zu tun? Wenn dein Programm nur 50% CPU-Last bekommt, weil gleichzeitig ein anderes Programm mit gleicher Priorität läuft, dann misst du eine doppelt so große Echtzeit wie das Programm eigentlich bräuchte.
Das Problem habe ich bei QueryPerformanceCounter wohl immer noch.
Nein, hast du nicht. Ist dir nicht klar, was CPU-Zeit ist und was im Vergleich dazu deine Armbanduhr anzeigt?
Doch, hat er schon.
QueryPerformanceCounter misst zwar CPU-Zeit, ist aber nicht Thread- bzw. Prozess-affin.Und das von dir erwähnte Problem vermeidet man einfach indem man sein System nicht sonderlich stesst, die Prozesspriorität raufschraubt und den besten Wert von mehreren Messungen nimmt.
Die prozessabhängige CPU Zeit ist unter Windows nach meiner Erfahrung recht ungenau, daher verwende ich die nie.
SeppJ schrieb:
Und ja, wenn dein Programm parallelisiert ist, dann ist Echtzeit vermutlich auch nicht das was du wissen möchtest, schließlich will man ja allgemeine wissen, wie viel CPU-Leistung ein Programm verbraucht hat, damit man einschätzen kann, wie viel Echtzeit es auf einem anderen System braucht.
Och Sepp, ich weiss schon selber was mich interessiert. Und oft genug interessiert mich bloss die Echtzeit die vergeht.
Klar, manchmal auch die Zeit die man in Summe auf allen Cores verbraten hat.
Allerdings kann man die Werte kaum brauchen, da man erfahrungsgeämss nicht sinnvoll hochrechnen kann.
Also die Rechnung "eine Instanz meiner Anwendung braucht für ein Work-Item 1 Sekunde und verbrät dabei 33% der gesamt verfügbaren CPU Leistung, also kann ich mit 3 Instanzen parallel 3 Work-Items pro Sekunde abarbeiten" geht einfach nicht auf. Wie gesagt Erfahrungswert, woran genau das liegt kann ich dir jetzt auch nicht sagen.Deswegen sag ich ja: man muss halt einfach wissen was man wissen will und dann das richtige messen.
-
Nimm um Himmelswillen einen Profiler für Performancemessungen! Besonders, wenn du dich selber so schwer mit der Zeitmessung tust.
Zeitmessung schrieb:
Hmm, ich dachte die CPU-Zeit bezieht sich auf alle Cores?
Nutz doch einfach mal Google, wenn du nicht weißt, was ein Fachbegriff bedeutet.
hustbaer schrieb:
Doch, hat er schon.
QueryPerformanceCounter misst zwar CPU-Zeit, ist aber nicht Thread- bzw. Prozess-affin.Ach, Windows
. Kenne mich da nicht so aus. Gibt es da nichts, was die Threads zusammenzählt? Linux kann das :p .
hustbaer schrieb:
Und das von dir erwähnte Problem vermeidet man einfach indem man sein System nicht sonderlich stesst, die Prozesspriorität raufschraubt und den besten Wert von mehreren Messungen nimmt.
Wenn aber andere Leute auf dem Rechner rechnen? Ach, irgendwie programmier ich in einer anderen Welt als der Windwosdesktopentwickler…
-
@Zeitmessung
Nur um das nochmal klarzustellen:QueryPerformanceCounter
misst die Zeit, genau so wie sie auf der Uhr an der Wand runtertickt.
Eine Messung einer "mittleren" Dauer sollte mitQueryPerformanceCounter
und z.B. der Systemzeit inetwa den selben Wert ergeben (vorausgesetzt die Systemzeit wurde nicht während der Messung verstellt natürlich).Wie viele Cores/Threads/Prozesse/... das System hat und was die alle machen oder nicht machen ist dabei vollkommen egal.
QueryPerformanceCounter
verglichen mit der Systemzeit:
* Kein definierter "Nullpunkt", d.h. man kann auch nicht von einemQueryPerformanceCounter
-Wert auf ein Datum+Zeit hochrechnen
* Schlechtere absolute Genauigkeit (so genau wie der verwendete Hardware-Timer, kann also nicht mit einem Timer mithalten der immer wieder mit externen Quellen wie Time-Servern abgeglichen wird)
* Nicht brauchbar um Messungen über Standby/Hinerbation/... hinweg zu machen
* Viel bessere Auflösung
-
SeppJ schrieb:
hustbaer schrieb:
Doch, hat er schon.
QueryPerformanceCounter misst zwar CPU-Zeit, ist aber nicht Thread- bzw. Prozess-affin.Ach, Windows
. Kenne mich da nicht so aus. Gibt es da nichts, was die Threads zusammenzählt? Linux kann das :p .
Windows kann das auch. Kann man ja sogar im Task-Manager als Spalte dazuklicken.
Wie die Funktion heisst müsste ich selbst nochmal nachgoogeln, ist mir den Aufwand jetzt grad nicht wert.
Aber wie gesagt: die Werte die du da rausbekommst sind nicht für Hochrechnungen geeignet.
(Es sei denn es hätte sich da seit Windows 2000 was getan - mit neueren Windosen hab ich das nichtmehr probiert)hustbaer schrieb:
Und das von dir erwähnte Problem vermeidet man einfach indem man sein System nicht sonderlich stesst, die Prozesspriorität raufschraubt und den besten Wert von mehreren Messungen nimmt.
Wenn aber andere Leute auf dem Rechner rechnen? Ach, irgendwie programmier ich in einer anderen Welt als der Windwosdesktopentwickler…
Wenn andere Leute auf dem Rechner rechnen hat man Pech
Ne, is schon klar, in solchen Situationen ist alles etwas anders. Da geht's mir aber genau so wie dir bei Windows
-
clock::ratio ist ja statisch, und da die erreichbare Genauigkeit oft erst zur Laufzeit bekannt ist kann es schonmal nicht genau stimmen.
Statisch bedeutet nicht, dass sie zur Kompilezeit bekannt sein muss. Der Wert kann auch bei Initialisierung der Runtime gesetzt werden. Ausserdem werden die Laufzeitbibliotheken meist fuer ein System gebaut, so dass der verwendete Timer zur Kompilezeit ebenfalls bekannt ist.
-
knivil schrieb:
clock::ratio ist ja statisch, und da die erreichbare Genauigkeit oft erst zur Laufzeit bekannt ist kann es schonmal nicht genau stimmen.
Statisch bedeutet nicht, dass sie zur Kompilezeit bekannt sein muss. Der Wert kann auch bei Initialisierung der Runtime gesetzt werden.
Statisch im Sinne von compile-time-constant.
Guckst du http://www.cplusplus.com/reference/std/ratio/ratio/
Also nix mit Runtime.Ausserdem werden die Laufzeitbibliotheken meist fuer ein System gebaut, so dass der verwendete Timer zur Kompilezeit ebenfalls bekannt ist.
Weil jedes "System" immer nur genau eine Hardware unterstützt oder wie?
Nene, welche Timer wirklich verfügbar sind wissen Desktop-OS' erst beim hochfahren. Die C++ Implementierung setzt dann einfach einen Wert ein der ausgehend von der bestmöglichen Auflösung nicht allzuviel verschenkt. Wobei "bestmögliche Auflösung" auch durchaus die Auflösung der OS-API sein kann, und ganz ganz weit weg von der effektiven Auflösung der besten aktuellen Implementierung.