409 Stimmen

Einfaches Messen der verstrichenen Zeit

Ich versuche zu verwenden Zeit() um verschiedene Punkte meines Programms zu messen.

Was ich nicht verstehe, ist, warum die Werte vorher und nachher gleich sind? Mir ist klar, dass dies nicht der beste Weg ist, um ein Profil meines Programms zu erstellen, 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 es 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 msec?

Was ist mit **time taken = 4 45025 Bedeutet das 4 Sekunden und 25 msec?

10 Stimmen

Ich verstehe die Frage nicht. Natürlich sind die Werte unterschiedlich. Dazwischen ist Zeit vergangen, also time() gibt einen anderen Wert zurück.

1 Stimmen

Was meinen Sie mit "Ich verstehe nicht, warum die Werte im Vorher und Nachher unterschiedlich sind"? Sie erhalten die aktuelle Zeit (in Sekunden seit dem 1. Januar 1970) mit time(NULL) ... das zweite Mal, wenn Sie es aufrufen, wird N Sekunden nach dem ersten und damit ... anders sein (es sei denn, was auch immer es ist Sie tun, dauert nicht eine Sekunde zu beenden ... in diesem Fall, es wird das gleiche wie das erste sein).

1 Stimmen

Können Sie uns sagen, was gedruckt wird und wie lange es dauert, wenn Sie es mit einer Stoppuhr oder einer Wanduhr (oder einem Kalender) messen?

564voto

user3762106 Punkte 5009
//***C++11 Style:***
#include <chrono>

std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() << "[ns]" << std::endl;

33 Stimmen

Um dies auszuführen, müssen Sie die #include <chrono> Richtlinie und ich würde die Meldezeit wie folgt ändern: std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl; (und vergessen Sie beim Kompilieren nicht das C++11-Flag: -std=c++11 )

4 Stimmen

@RestlessC0bra Laut der Dokumentation von cppreference "ist diese Uhr nicht auf die Wanduhrzeit bezogen (z.B. kann es die Zeit seit dem letzten Neustart sein) und eignet sich am besten zur Messung von Intervallen."

0 Stimmen

@Antonello - Sie sollten sich std::chrono::duration_cast genauer ansehen, insbesondere std::chrono::seconds, wenn Sie die Dauer in Sekunden zurückgeben möchten.

343voto

Nikos Athanasiou Punkte 26657

0 - Delta

Verwenden Sie eine Deltafunktion zur Berechnung von Zeitdifferenzen:

auto start = std::chrono::steady_clock::now();
std::cout << "Elapsed(ms)=" << since(start).count() << std::endl;

since akzeptiert einen beliebigen Zeitpunkt und erzeugt eine beliebige Dauer (Standard ist Millisekunden). Sie ist definiert als:

template <
    class result_t   = std::chrono::milliseconds,
    class clock_t    = std::chrono::steady_clock,
    class duration_t = std::chrono::milliseconds
>
auto since(std::chrono::time_point<clock_t, duration_t> const& start)
{
    return std::chrono::duration_cast<result_t>(clock_t::now() - start);
}

Demo

1 - Zeitschaltuhr

Verwenden Sie einen Timer, der auf std::chrono :

Timer clock; // Timer<milliseconds, steady_clock>

clock.tick();
/* code you want to measure */
clock.tock();

cout << "Run time = " << clock.duration().count() << " ms\n";

Demo

Timer ist definiert als:

template <class DT = std::chrono::milliseconds,
          class ClockT = std::chrono::steady_clock>
class Timer
{
    using timep_t = typename ClockT::time_point;
    timep_t _start = ClockT::now(), _end = {};

public:
    void tick() { 
        _end = timep_t{}; 
        _start = ClockT::now(); 
    }

    void tock() { _end = ClockT::now(); }

    template <class T = DT> 
    auto duration() const { 
        gsl_Expects(_end != timep_t{} && "toc before reporting"); 
        return std::chrono::duration_cast<T>(_end - _start); 
    }
};

Als Howard Hinnant darauf hingewiesen, verwenden wir eine Dauer für den Verbleib in der chrono Typsystem und führen Operationen wie Mittelwertbildung oder Vergleiche durch (hier bedeutet dies z. B. die Verwendung von std::chrono::milliseconds ). Wenn wir nur IO machen, verwenden wir die count() oder Ticks einer Dauer (z. B. hier Anzahl der Millisekunden).

2 - Instrumentierung

Jede aufrufbare Funktion (Funktion, Funktionsobjekt, Lambda usw.) kann für das Benchmarking instrumentiert werden. Angenommen, Sie haben eine Funktion F aufrufbar mit Argumenten arg1,arg2 führt diese Technik zu:

cout << "F runtime=" << measure<>::duration(F, arg1, arg2).count() << "ms";

<strong>Demo</strong>

measure ist definiert als:

template <class TimeT  = std::chrono::milliseconds
          class ClockT = std::chrono::steady_clock>
struct measure
{
    template<class F, class ...Args>
    static auto duration(F&& func, Args&&... args)
    {
        auto start = ClockT::now();
        std::invoke(std::forward<F>(func), std::forward<Args>(args)...);
        return std::chrono::duration_cast<TimeT>(ClockT::now()-start);
    }
};

Wie in (1) erwähnt, ist die Verwendung der Dauer ohne .count() ist vor allem für Clients nützlich, die eine Reihe von Dauern vor der E/A nachbearbeiten wollen, z. B. für den Durchschnitt:

auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2;
std::cout << "Average run time " << avg.count() << " ms\n";

+ Diese ist der Grund für den weitergeleiteten Funktionsaufruf.

+Der vollständige Code ist zu finden unter aquí

+Mein Versuch, eine Benchmarking-Rahmen basierend auf Chrono wird aufgezeichnet aquí

+Alt démo

2 Stimmen

Nice; Ich habe etwas ähnliches in meinem Code, aber verwenden Sie eine andere Schnittstelle zu der Klasse: Ich habe eine Klasse ( code_timer ), die die Startzeit ( std::chrono::system_clock::now(); ) im Konstruktor, eine Methode code_timer::ellapsed die den Unterschied zwischen einer neuen now() Aufruf und dem Aufruf im Konstruktor, und eine code_timer::reset Methode, die die Startzeit auf einen neuen Wert zurücksetzt now() Ergebnis. Um die Ausführung eines Funktors in meinem Code zu messen, verwende ich eine freie Funktion außerhalb der Klasse. Dies ermöglicht die Messung der Zeit von der Erstellung eines Objekts bis zum Abschluss eines Asynchronisierungsaufrufs.

0 Stimmen

@utnapistim Thnx, ich habe eine Überprüfung auf diesem Code gefragt, können Sie es überprüfen aquí . Wenn Sie die Zeit haben, könnten Sie auch ein bisschen mehr über Ihren Entwurf erzählen, er klingt großartig.

0 Stimmen

Achten Sie auf die Compiler-Optimierung! Ich habe so etwas schon einmal ausprobiert, und der Compiler hat den Aufruf von func weg, da sie keine Nebenwirkungen hatte und der Rückgabewert nicht verwendet wurde.

286voto

#include <ctime>

void f() {
  using namespace std;
  clock_t begin = clock();

  code_to_time();

  clock_t end = clock();
  double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
}

En time() Funktion ist nur auf eine Sekunde genau, aber es gibt CLOCKS_PER_SEC "Uhren" innerhalb einer Sekunde. Dies ist eine einfache, übertragbare Messung, auch wenn sie stark vereinfacht ist.

142 Stimmen

Beachten Sie, dass clock() misst die CPU-Zeit, nicht die tatsächlich verstrichene Zeit (die viel länger sein kann).

14 Stimmen

Bei der Programmierung von parallelem Code für Cluster spiegelt diese Methode nicht die reale Zeit wider...

3 Stimmen

Dies scheint der einfachste Weg zu sein. Würden Sie bitte den Kommentar von @jlstrecker aktualisieren oder ansprechen?

59voto

Akaanthan Ccoder Punkte 2011

Wie ich aus Ihrer Frage ersehen kann, möchten Sie wohl die verstrichene Zeit nach der Ausführung eines bestimmten Codes wissen. Ich vermute, dass Sie gerne die Ergebnisse in Sekunden sehen würden. Wenn ja, versuchen Sie es mit difftime() Funktion wie unten dargestellt. Ich hoffe, damit ist Ihr Problem gelöst.

#include <time.h>
#include <stdio.h>

time_t start,end;
time (&start);
.
.
.
<your code>
.
.
.
time (&end);
double dif = difftime (end,start);
printf ("Elasped time is %.2lf seconds.", dif );

4 Stimmen

Dadurch erhalte ich immer ganzzahlige Sekunden. Ist das so vorgesehen?

14 Stimmen

Time gibt immer nur Sekunden zurück, kann also nicht für Messungen im Sekundenbereich verwendet werden.

31voto

RvdK Punkte 19035

Nur für Windows: (Der Linux-Tag wurde hinzugefügt, nachdem ich diese Antwort veröffentlicht hatte)

Sie können verwenden GetTickCount() um die Anzahl der Millisekunden zu ermitteln, die seit dem Start des Systems verstrichen sind.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

7 Stimmen

Ich verwende es unter Linux. Daher kann ich die Funktion GetTickCount() nicht verwenden.

1 Stimmen

Schon gar nicht mehr ;) Danke für das Aktualisieren des Tags deines Beitrags

0 Stimmen

Es funktioniert und gibt die tatsächliche Zeit an, nicht die CPU-Zeit. Ich habe es getestet, indem ich SleepEx(5000,0) anstelle von //Durchführen einer zeitaufwendigen Operation und Differenz von after y before betrug fast 5 Sekunden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X