Ich versuche, time () zu verwenden, um verschiedene Punkte meines Programms zu messen.
Was ich nicht verstehe ist, warum die Werte im Vorher und Nachher gleich sind? Ich verstehe, dass dies nicht der beste Weg ist, mein Programm zu profilieren. Ich möchte nur sehen, wie lange etwas dauert.
printf("**MyProgram::before time= %ld\n", time(NULL));
doSomthing();
doSomthingLong();
printf("**MyProgram::after time= %ld\n", time(NULL));
Ich habe versucht:
struct timeval diff, startTV, endTV;
gettimeofday(&startTV, NULL);
doSomething();
doSomethingLong();
gettimeofday(&endTV, NULL);
timersub(&endTV, &startTV, &diff);
printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);
Wie lese ich ein Ergebnis von **time taken = 0 26339
? Bedeutet das 26.339 Nanosekunden = 26,3 ms?
Was ist mit **time taken = 4 45025
4 Sekunden und 25 ms?
time()
gibt also einen anderen Wert zurück.time(NULL)
... das zweite Mal, wenn Sie sie aufrufen, sind N Sekunden nach dem ersten und somit ... anders (es sei denn, was auch immer Sie tun, tut es nicht. ' Es dauert keine Sekunde, bis der Vorgang abgeschlossen ist. In diesem Fall ist er derselbe wie der erste.Antworten:
quelle
#include <chrono>
Richtlinie und ich würde die Meldezeit ändern:std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;
(und nicht zu vergessen die C ++ 11 - Flag beim Kompilieren:-std=c++11
)Die
time()
Funktion ist nur auf eine Sekunde genau, aber es gibtCLOCKS_PER_SEC
"Uhren" innerhalb einer Sekunde. Dies ist eine einfache, tragbare Messung, obwohl sie zu stark vereinfacht ist.quelle
clock()
die CPU-Zeit gemessen wird und nicht die tatsächlich verstrichene Zeit (die viel größer sein kann).Sie können den Zeitmessmechanismus abstrahieren und die Laufzeit jedes aufrufbaren Objekts mit minimalem zusätzlichen Code messen lassen , indem Sie einfach über eine Timer-Struktur aufgerufen werden. Außerdem können Sie zur Kompilierungszeit den Timing-Typ (Millisekunden, Nanosekunden usw.) parametrisieren .
Dank der Bewertung von Loki Astari und dem Vorschlag, verschiedene Vorlagen zu verwenden. Dies ist , warum der weitergeleitet Funktionsaufruf.
Demo
Nach dem Kommentar von Howard Hinnant ist es am besten, nicht aus dem Chronosystem herauszukommen, bis wir müssen. Die obige Klasse kann dem Benutzer also die Möglichkeit geben,
count
manuellaufzurufen,indem eine zusätzliche statische Methode bereitgestellt wird (siehe C ++ 14).und am nützlichsten für Kunden sein, die
Den vollständigen Code finden Sie hier . Mein Versuch, ein auf Chrono basierendes Benchmarking-Tool zu erstellen, wird aufgezeichnet hier.
Wenn C ++ 17
std::invoke
verfügbar ist, kann der Aufruf des aufrufbaren Inexecution
folgendermaßen erfolgen:um Callables bereitzustellen, die Zeiger auf Mitgliedsfunktionen sind.
quelle
code_timer
), die die Startzeit (std::chrono::system_clock::now();
) im Konstruktor benötigt, eine Methodecode_timer::ellapsed
, die den Unterschied zwischen einem neuennow()
Aufruf und dem im Konstruktor misst und einecode_timer::reset
Methode, die die Startzeit auf ein neuesnow()
Ergebnis zurücksetzt . Um die Ausführung eines Funktors in meinem Code zu messen, verwende ich eine kostenlose Funktion außerhalb der Klasse. Dies ermöglicht die Messung der Zeit vom Aufbau eines Objekts bis zum Ende eines asynchronen Aufrufs.chrono
System erst, wenn Sie es müssen (vermeiden Sie die Verwendung von.count()
). Lassen Sie den Client anrufen,.count()
wenn er dazu gezwungen wird (z. B. für E / A, was in der Tat unglücklich ist). Der Client möchte möglicherweise eine Reihe von Zeiträumen vor der E / A nachbearbeiten (z. B. Durchschnitt). Dies geschieht am besten innerhalb deschrono
Systems.std::forward<F>(func)
?std::forward<decltype(func)>(func)
weil es für Argumente von generischen Lambdas (auto&& func
) gelten kann, bei denenF
es nicht syntaktisch vorhanden ist und die in einem Dienstprogrammmakro,#define fw(arg) std::forward<decltype(arg)>(arg)
das ich in meiner Benchmark-Bibliothek verwende , leicht zu abstrahieren sind (es handelt sich also um eine syntaktische Überbleibsel, auf die ich nicht viel eingehen möchte die Antwort)Wie ich aus Ihrer Frage ersehen kann, möchten Sie anscheinend die verstrichene Zeit nach der Ausführung eines Codeteils wissen. Ich denke, Sie würden sich wohl fühlen, wenn Sie die Ergebnisse in Sekunden sehen würden. Versuchen Sie in diesem Fall
difftime()
, die unten gezeigte Funktion zu verwenden. Hoffe das löst dein Problem.quelle
Nur Windows: (Das Linux-Tag wurde hinzugefügt, nachdem ich diese Antwort gepostet habe.)
Mit GetTickCount () können Sie die Anzahl der Millisekunden abrufen , die seit dem Start des Systems vergangen sind.
quelle
SleepEx(5000,0)
anstelle von // Perform zeitaufwendiger Vorgang und Differenz vonafter
undbefore
waren fast 5 Sekunden.time(NULL)
Gibt die Anzahl der Sekunden zurück, die seit dem 01.01.1970 um 00:00 Uhr ( Epoche ) vergangen sind . Der Unterschied zwischen den beiden Werten ist also die Anzahl der Sekunden, die Ihre Verarbeitung benötigt hat.Mit können Sie feinere Ergebnisse erzielen
getttimeofday()
, die die aktuelle Zeit in Sekundentime()
und auch in Mikrosekunden zurückgeben.quelle
Die Zeitfunktion (NULL) gibt die Anzahl der Sekunden zurück, die seit dem 01.01.1970 um 00:00 Uhr vergangen sind. Und weil diese Funktion in Ihrem Programm zu unterschiedlichen Zeiten aufgerufen wird, ist sie in C ++ immer zu unterschiedlichen Zeiten
quelle
Verwendung ist unten ::
Dies ist ähnlich wie RAII im Umfang
HINWEIS: Dies ist nicht meins, aber ich dachte, dass es hier relevant ist
quelle
quelle
Die von Ihrem zweiten Programm gedruckten Werte sind Sekunden und Mikrosekunden.
quelle
quelle
C ++ std :: chrono hat den klaren Vorteil, plattformübergreifend zu sein. Es führt jedoch auch zu einem erheblichen Overhead im Vergleich zu POSIX clock_gettime (). Auf meiner Linux-Box
std::chrono::xxx_clock::now()
funktionieren alle Geschmacksrichtungen ungefähr gleich:Obwohl POSIX
clock_gettime(CLOCK_MONOTONIC, &time)
das gleiche sein sollte wiesteady_clock::now()
, ist es mehr als x3 mal schneller!Hier ist mein Test der Vollständigkeit halber.
Und dies ist die Ausgabe, die ich beim Kompilieren mit gcc7.2 -O3 erhalte:
quelle
Der
time(NULL)
Funktionsaufruf gibt die Anzahl der Sekunden zurück, die seit dem Epoc: 1. Januar 1970 vergangen sind. Vielleicht möchten Sie die Differenz zwischen zwei Zeitstempeln ermitteln:quelle
Wie andere bereits bemerkt haben, hat die time () - Funktion in der C-Standardbibliothek keine bessere Auflösung als eine Sekunde. Die einzige vollständig tragbare C-Funktion, die möglicherweise eine bessere Auflösung bietet, scheint clock () zu sein, misst jedoch eher die Prozessorzeit als die Wanduhrzeit. Wenn man sich damit zufrieden gibt, sich auf POSIX-Plattformen (z. B. Linux) zu beschränken, ist die Funktion clock_gettime () eine gute Wahl.
Seit C ++ 11 gibt es viel bessere Timing-Möglichkeiten Verfügung, die eine bessere Auflösung in einer Form bieten, die für verschiedene Compiler und Betriebssysteme sehr portabel sein sollte. In ähnlicher Weise bietet die boost :: datetime-Bibliothek gute hochauflösende Timing-Klassen, die hoch portabel sein sollten.
Eine Herausforderung bei der Verwendung einer dieser Einrichtungen ist die Zeitverzögerung, die durch die Abfrage der Systemuhr eingeführt wird. Durch das Experimentieren mit clock_gettime (), boost :: datetime und std :: chrono kann diese Verzögerung leicht eine Frage von Mikrosekunden sein. Wenn Sie also die Dauer eines Teils Ihres Codes messen, müssen Sie einen Messfehler von etwa dieser Größe berücksichtigen oder versuchen, diesen Nullfehler auf irgendeine Weise zu korrigieren. Im Idealfall möchten Sie möglicherweise mehrere Messungen der von Ihrer Funktion benötigten Zeit erfassen und die durchschnittliche oder maximale / minimale Zeit berechnen, die für viele Läufe benötigt wird.
Um all diese Probleme mit der Portabilität und dem Sammeln von Statistiken zu lösen, habe ich die auf Github verfügbare cxx-rtimers-Bibliothek entwickelt, die versucht, eine einfache API für Timing-Blöcke von C ++ - Code bereitzustellen, null Fehler zu berechnen und Statistiken von mehreren eingebetteten Timern zu melden in Ihrem Code. Wenn Sie einen C ++ 11-Compiler haben, verwenden Sie einfach
#include <rtimers/cxx11.hpp>
Folgendes:Beim Beenden des Programms erhalten Sie eine Zusammenfassung der in std :: cerr geschriebenen Timing-Statistiken wie:
Dies zeigt die mittlere Zeit, ihre Standardabweichung, die oberen und unteren Grenzen und die Häufigkeit, mit der diese Funktion aufgerufen wurde.
Wenn Sie Linux-spezifische Timing-Funktionen verwenden möchten, können Sie dies
#include <rtimers/posix.hpp>
, oder wenn Sie die Boost-Bibliotheken, aber einen älteren C ++ - Compiler haben, können Sie dies#include <rtimers/boost.hpp>
. Es gibt auch Versionen dieser Timer-Klassen, die statistische Timing-Informationen aus mehreren Threads erfassen können. Es gibt auch Methoden, mit denen Sie den Nullfehler schätzen können, der mit zwei unmittelbar aufeinanderfolgenden Abfragen der Systemuhr verbunden ist.quelle
Intern greift die Funktion auf die Uhr des Systems zu, weshalb sie bei jedem Aufruf unterschiedliche Werte zurückgibt. Im Allgemeinen kann es bei nicht funktionierenden Sprachen zu vielen Nebenwirkungen und versteckten Zuständen in Funktionen kommen, die Sie nicht sehen können, wenn Sie nur den Namen und die Argumente der Funktion betrachten.
quelle
Nach dem, was zu sehen ist, speichert tv_sec die verstrichenen Sekunden, während tv_usec die verstrichenen Mikrosekunden separat speichert. Und sie sind nicht die Bekehrungen voneinander. Daher müssen sie in die richtige Einheit geändert und hinzugefügt werden, um die verstrichene Gesamtzeit zu erhalten.
quelle
Unter Linux ist clock_gettime () eine der guten Entscheidungen. Sie müssen die Echtzeitbibliothek (-lrt) verknüpfen.
quelle
Ich musste die Ausführungszeit einzelner Funktionen innerhalb einer Bibliothek messen. Ich wollte nicht jeden Aufruf jeder Funktion mit einer Zeitmessfunktion abschließen müssen, da dies hässlich ist und den Aufrufstapel vertieft. Ich wollte auch nicht den Timer-Code oben und unten in jede Funktion einfügen, da dies zu Problemen führt, wenn die Funktion vorzeitig beendet oder beispielsweise Ausnahmen ausgelöst werden kann. Am Ende habe ich also einen Timer erstellt, der seine eigene Lebensdauer verwendet, um die Zeit zu messen.
Auf diese Weise kann ich die Wandzeit messen, die ein Codeblock benötigt, indem ich nur eines dieser Objekte am Anfang des betreffenden Codeblocks (Funktion oder ein beliebiger Bereich) instanziiere und dann dem Instruktordestruktor erlaube, die seitdem verstrichene Zeit zu messen Konstruktion, wenn die Instanz den Gültigkeitsbereich verlässt. Das vollständige Beispiel finden Sie hier, aber die Struktur ist äußerst einfach:
Die Struktur ruft Sie auf dem bereitgestellten Funktor zurück, wenn dieser außerhalb des Gültigkeitsbereichs liegt, damit Sie etwas mit den Zeitinformationen tun können (drucken oder speichern oder was auch immer). Wenn Sie etwas noch komplexer tun müssen , könnten Sie sogar verwenden
std::bind
mitstd::placeholders
Funktionen Rückruf mit mehreren Argumenten.Hier ist ein kurzes Beispiel für die Verwendung:
Wenn Sie bewusster sein möchten, können Sie den Timer auch verwenden
new
unddelete
explizit starten und stoppen, ohne sich auf das Scoping verlassen zu müssen, um dies für Sie zu tun.quelle
Sie sind dieselben, weil Ihre doSomething-Funktion schneller abläuft als die Granularität des Timers. Versuchen:
quelle
Der Grund, warum beide Werte gleich sind, liegt in Ihrer langen Prozedur nicht so dauert - weniger als eine Sekunde. Sie können versuchen, am Ende der Funktion einfach eine lange Schleife (für (int i = 0; i <100000000; i ++);) hinzuzufügen, um sicherzustellen, dass dies das Problem ist. Dann können wir fortfahren ...
Falls sich herausstellt, dass das oben Gesagte zutrifft, müssen Sie eine andere Systemfunktion finden (ich verstehe, dass Sie unter Linux arbeiten, daher kann ich Ihnen mit dem Funktionsnamen nicht helfen), um die Zeit genauer zu messen. Ich bin mir sicher, dass es unter Linux eine ähnliche Funktion wie GetTickCount () gibt. Sie müssen sie nur finden.
quelle
Ich benutze normalerweise Folgendes:
Es ist dasselbe wie @ nikos-athanasiou vorgeschlagen, außer dass ich die Verwendung einer instationären Uhr vermeide und eine schwebende Anzahl von Sekunden als Dauer verwende.
quelle
high_resolution_clock
ein Typedef für entwedersystem_clock
odersteady_clock
. Um zu verfolgen, dass,std::conditional
wenn dasis_steady
Teil wahr ist, Sie das auswählen,high_resolution_clock
was (ein typedef zu) das iststeady_clock
. Wenn es falsch ist, wählen Sie dassteady_clock
erneut aus. Verwenden Sie einfachsteady_clock
von Anfang an ...high_resolution_clock may be a synonym for system_clock or steady_clock
. Der Grund ist folgender:high_resolution_clock
Stellt Uhren mit der kürzesten Tick-Periode dar. Unabhängig von der Implementierung gibt es also zwei Möglichkeiten, ob sie stabil sind oder nicht. Unabhängig davon, welche Wahl wir treffen, ist die Aussage, dass sich die Implementierung von den beiden anderen Uhren unterscheidet, gleichbedeutend mit der Aussage, dass wir eine bessere Implementierung für eine stabile (oder nicht stabile) Uhr haben, die wir nicht verwenden (für stabile oder nicht stabile Uhren). Wissen, wie gut ist, wissen, warum es besser istAls Antwort auf die drei spezifischen Fragen von OP .
"Was ich nicht verstehe ist, warum die Werte im Vorher und Nachher gleich sind? "
Die erste Frage und der Beispielcode zeigen, dass
time()
sie eine Auflösung von 1 Sekunde haben. Die Antwort muss also sein, dass die beiden Funktionen in weniger als 1 Sekunde ausgeführt werden. Aber gelegentlich wird es (anscheinend unlogisch) 1 Sekunde informieren, wenn die beiden Timer-Markierungen eine Grenze von einer Sekunde überschreiten.Das nächste Beispiel verwendet
gettimeofday()
, das diese Struktur ausfülltund die zweite Frage lautet : "Wie lese ich ein Ergebnis von
**time taken = 0 26339
? Bedeutet das 26.339 Nanosekunden = 26,3 ms?"Meine zweite Antwort lautet: Die benötigte Zeit beträgt 0 Sekunden und 26339 Mikrosekunden, dh 0,026339 Sekunden. Dies bestätigt das erste Beispiel, das in weniger als 1 Sekunde ausgeführt wird.
Die dritte Frage lautet : "Was
**time taken = 4 45025
bedeutet das, bedeutet das 4 Sekunden und 25 ms?"Meine dritte Antwort lautet: Die benötigte Zeit beträgt 4 Sekunden und 45025 Mikrosekunden, dh 4,045025 Sekunden. Dies zeigt, dass OP die Aufgaben der beiden Funktionen geändert hat, die er zuvor zeitlich festgelegt hat.
quelle
Ähnliches Beispiel wie hier, nur mit zusätzlicher Konvertierungsfunktion + Ausdruck.
quelle
Ich habe eine Klasse erstellt, um die verstrichene Zeit automatisch zu messen. Überprüfen Sie den Code (c ++ 11) in diesem Link: https://github.com/sonnt174/Common/blob/master/time_measure.h
Beispiel für die Verwendung der Klasse TimeMeasure:
quelle
Matlab
mit ...-Geschmack!tic
Startet einen Stoppuhr-Timer, um die Leistung zu messen. Die Funktion zeichnet die interne Zeit bei der Ausführung des Befehls tic auf. Zeigen Sie die verstrichene Zeit mit dertoc
Funktion an.quelle
Sie können die SFML-Bibliothek verwenden , bei der es sich um eine einfache und schnelle Multimedia-Bibliothek handelt. Es enthält viele nützliche und genau definierte Klassen wie Clock, Socket, Sound, Graphics usw. Es ist so einfach zu bedienen und sehr zu empfehlen.
Dies ist ein Beispiel für diese Frage.
quelle