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?

8voto

Akanksha Gupta Punkte 219
#include <ctime>
#include <cstdio>
#include <iostream>
#include <chrono>
#include <sys/time.h>
using namespace std;
using namespace std::chrono;

void f1()
{
  high_resolution_clock::time_point t1 = high_resolution_clock::now();
  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  double dif = duration_cast<nanoseconds>( t2 - t1 ).count();
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f2()
{
  timespec ts1,ts2;
  clock_gettime(CLOCK_REALTIME, &ts1);
  clock_gettime(CLOCK_REALTIME, &ts2);
  double dif = double( ts2.tv_nsec - ts1.tv_nsec );
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f3()
{
  struct timeval t1,t0;
  gettimeofday(&t0, 0);
  gettimeofday(&t1, 0);
  double dif = double( (t1.tv_usec-t0.tv_usec)*1000);
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f4()
{
  high_resolution_clock::time_point t1 , t2;
  double diff = 0;
  t1 = high_resolution_clock::now() ;
  for(int i = 1; i <= 10 ; i++)
  {
    t2 = high_resolution_clock::now() ;
    diff+= duration_cast<nanoseconds>( t2 - t1 ).count();
    t1 = t2;
  }
  printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f5()
{
  timespec ts1,ts2;
  double diff = 0;
  clock_gettime(CLOCK_REALTIME, &ts1);
  for(int i = 1; i <= 10 ; i++)
  {
    clock_gettime(CLOCK_REALTIME, &ts2);
    diff+= double( ts2.tv_nsec - ts1.tv_nsec );
    ts1 = ts2;
  }
  printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f6()
{
  struct timeval t1,t2;
  double diff = 0;
  gettimeofday(&t1, 0);
  for(int i = 1; i <= 10 ; i++)
  {
    gettimeofday(&t2, 0);
    diff+= double( (t2.tv_usec-t1.tv_usec)*1000);
    t1 = t2;
  }
  printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

int main()
{
  //  f1();
  //  f2();
  //  f3();
  f6();
  f4();
  f5();
  return 0;
}

5voto

Alexey Polonsky Punkte 1095

C++ std::chrono hat den klaren Vorteil, plattformübergreifend zu sein. Allerdings führt es auch einen erheblichen Overhead im Vergleich zu POSIX clock_gettime() ein. Auf meinem Linux-Rechner werden alle std::chrono::xxx_clock::now() Die Geschmacksrichtungen sind in etwa gleich:

std::chrono::system_clock::now()
std::chrono::steady_clock::now()
std::chrono::high_resolution_clock::now()

Obwohl POSIX clock_gettime(CLOCK_MONOTONIC, &time) sollte gleich sein mit steady_clock::now() aber es ist mehr als 3 mal schneller!

Hier ist mein Test, der Vollständigkeit halber.

#include <stdio.h>
#include <chrono>
#include <ctime>

void print_timediff(const char* prefix, const struct timespec& start, const 
struct timespec& end)
{
    double milliseconds = end.tv_nsec >= start.tv_nsec
                        ? (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3
                        : (start.tv_nsec - end.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec - 1) * 1e3;
    printf("%s: %lf milliseconds\n", prefix, milliseconds);
}

int main()
{
    int i, n = 1000000;
    struct timespec start, end;

    // Test stopwatch
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i) {
        struct timespec dummy;
        clock_gettime(CLOCK_MONOTONIC, &dummy);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("clock_gettime", start, end);

    // Test chrono system_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::system_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::system_clock::now", start, end);

    // Test chrono steady_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::steady_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::steady_clock::now", start, end);

    // Test chrono high_resolution_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::high_resolution_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::high_resolution_clock::now", start, end);

    return 0;
}

Und dies ist die Ausgabe, die ich erhalte, wenn mit gcc7.2 -O3 kompiliert:

clock_gettime: 24.484926 milliseconds
chrono::system_clock::now: 85.142108 milliseconds
chrono::steady_clock::now: 87.295347 milliseconds
chrono::high_resolution_clock::now: 84.437838 milliseconds

3voto

wilhelmtell Punkte 55189

En time(NULL) gibt die Anzahl der seit epoc verstrichenen Sekunden zurück: 1. Januar 1970. Vielleicht wollen Sie die Differenz zwischen zwei Zeitstempeln ermitteln:

size_t start = time(NULL);
doSomthing();
doSomthingLong();

printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start);

3voto

rwp Punkte 1588

Wie bereits von anderen bemerkt, hat die Funktion time() in der C-Standardbibliothek keine bessere Auflösung als eine Sekunde. Die einzige vollständig portable C-Funktion, die eine bessere Auflösung bieten könnte, scheint clock() zu sein, aber diese misst die Prozessorzeit und nicht die Wanduhrzeit. Wenn man sich auf POSIX-Plattformen (z. B. Linux) beschränken möchte, ist die Funktion clock_gettime() eine gute Wahl.

Seit C++11 gibt es viel bessere Zeitmesseinrichtungen verfügbar, die eine bessere Auflösung in einer Form bieten, die über verschiedene Compiler und Betriebssysteme hinweg sehr portabel sein sollte. In ähnlicher Weise bietet die boost::datetime-Bibliothek gute hochauflösende Timing-Klassen, die sehr portabel sein sollten.

Eine Herausforderung bei der Nutzung dieser Möglichkeiten ist die Zeitverzögerung, die durch die Abfrage der Systemuhr entsteht. Aus Experimenten mit clock_gettime(), boost::datetime und std::chrono kann diese Verzögerung leicht eine Sache von Mikrosekunden sein. Wenn Sie also die Dauer eines beliebigen Teils Ihres Codes messen, müssen Sie einen Messfehler in dieser Größenordnung einkalkulieren oder versuchen, diesen Null-Fehler auf irgendeine Weise zu korrigieren. Idealerweise sollten Sie mehrere Messungen der von Ihrer Funktion benötigten Zeit durchführen und den Durchschnitt oder die maximale/minimale Zeit über viele Durchläufe hinweg berechnen.

Um bei all diesen Problemen mit der Portabilität und dem Sammeln von Statistiken zu helfen, habe ich die cxx-rtimers-Bibliothek entwickelt, die auf Github das versucht, eine einfache API für die Zeitmessung von C++-Codeblöcken, die Berechnung von Nullfehlern und die Meldung von Statistiken von mehreren in Ihrem Code eingebetteten Zeitmessern bereitzustellen. Wenn Sie einen C++11-Compiler haben, können Sie einfach #include <rtimers/cxx11.hpp> und verwenden Sie etwas wie:

void expensiveFunction() {
    static rtimers::cxx11::DefaultTimer timer("expensiveFunc");
    auto scopedStartStop = timer.scopedStart();
    // Do something costly...
}

Beim Beenden des Programms erhalten Sie eine Zusammenfassung der Timing-Statistiken, die in std::cerr geschrieben wird:

Timer(expensiveFunc): <t> = 6.65289us, std = 3.91685us, 3.842us <= t <= 63.257us (n=731)

die die mittlere Zeit, die Standardabweichung, die Ober- und Untergrenze sowie die Anzahl der Aufrufe dieser Funktion angibt.

Wenn Sie Linux-spezifische Timing-Funktionen verwenden möchten, können Sie #include <rtimers/posix.hpp> oder wenn Sie die Boost-Bibliotheken, aber einen älteren C++-Compiler haben, können Sie #include <rtimers/boost.hpp> . Es gibt auch Versionen dieser Timer-Klassen, die statistische Zeitinformationen über mehrere Threads hinweg sammeln können. Es gibt auch Methoden, die es Ihnen ermöglichen, den Null-Fehler zu schätzen, der mit zwei unmittelbar aufeinander folgenden Abfragen der Systemuhr verbunden ist.

3voto

cloudrain21 Punkte 581

Unter Linux ist clock_gettime() eine der besten Möglichkeiten. Sie müssen die Echtzeit-Bibliothek (-lrt) linken.

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

#define BILLION  1000000000L;

int main( int argc, char **argv )
  {
    struct timespec start, stop;
    double accum;

    if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    system( argv[1] );

    if( clock_gettime( CLOCK_REALTIME, &stop) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    accum = ( stop.tv_sec - start.tv_sec )
          + ( stop.tv_nsec - start.tv_nsec )
            / BILLION;
    printf( "%lf\n", accum );
    return( EXIT_SUCCESS );
  }

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