Mesurer facilement le temps écoulé

je suis en train d'utiliser time() pour mesurer les différents points de mon programme.

Ce que je ne comprends pas, c'est pourquoi les valeurs avant et après sont les mêmes? Je comprends que ce n'est pas la meilleure façon de profiler mon programme, je veux juste voir combien de temps ça prend.

printf("**MyProgram::before time= %ldn", time(NULL));

doSomthing();
doSomthingLong();

printf("**MyProgram::after time= %ldn", time(NULL));

j'ai essayé:

struct timeval diff, startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

timersub(&endTV, &startTV, &diff);

printf("**time taken = %ld %ldn", diff.tv_sec, diff.tv_usec);

Comment lire un résultat de **time taken = 0 26339 ? Est-ce que ça veut dire 26.339 nanosecondes = 26.3 ms?

et **time taken = 4 45025 , ça veut dire 4 secondes et 25 msec?

239
demandé sur hap497 2010-05-11 10:04:29

22 réponses

#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;
}

la fonction time() n'est précise qu'à une seconde près, mais il y a CLOCKS_PER_SEC "horloges" dans une seconde. Il s'agit d'une mesure facile et portable, même si elle est trop simplifiée.

240
répondu 2013-08-28 10:12:20

Vous pouvez résumé de la mesure du temps d'mécanisme de et ont chacun appelable du temps d'exécution mesuré avec supplémentaire minimal code , tout en étant appelé par le biais d'une minuterie de la structure. De plus, au moment de la compilation, vous pouvez paramétrer le type de timing (millisecondes, nanosecondes etc).

merci à la revue Loki Astari et la suggestion d'utiliser des gabarits variadiques. Ce est pourquoi l'envoyé de l'appel de fonction.

#include <iostream>
#include <chrono>

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

int main() {
    std::cout << measure<>::execution(functor(dummy)) << std::endl;
}

Démo

selon le commentaire de Howard Hinnant il est préférable de ne pas s'échapper du système chrono jusqu'à ce que nous devons. Si la classe ci-dessus pourrait donner à l'utilisateur le choix d'appeler count manuellement en fournissant une méthode statique supplémentaire (indiquée en C++14)

template<typename F, typename ...Args>
static auto duration(F&& func, Args&&... args)
{
    auto start = std::chrono::steady_clock::now();
    std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
    return std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now()-start);
} 

// call .count() manually later when needed (eg IO)
auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2.0;

et être le plus utile pour les clients que

"voulez de post-traiter un tas de durées avant I/O (p. ex. moyenne)"


le code complet peut être trouvé ici . Ma tentative de construire un outil de benchmarking basé sur chrono est enregistré ici .


si C++17 std::invoke est disponible, l'invocation du callable dans execution pourrait être faite comme ceci:

invoke(forward<decltype(func)>(func), forward<Args>(args)...);

pour fournir des callables qui sont des pointeurs vers les fonctions des membres.

231
répondu Nikos Athanasiou 2017-05-23 12:34:48
//***C++11 Style:***
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() <<std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() <<std::endl;
198
répondu user3762106 2015-12-08 16:57:59

Comme je peux le voir dans votre question, il semble que vous voulez savoir le temps écoulé après l'exécution d'un morceau de code. Je suppose que vous seriez à l'aise de voir les résultats en seconde(s). Si c'est le cas, essayez d'utiliser la fonction difftime() comme indiqué ci-dessous. Espérons que cela résout votre problème.

#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 );
54
répondu AKN 2016-04-11 23:45:22

Windows only: (la balise Linux a été ajoutée après que j'ai posté cette réponse)

vous pouvez utiliser GetTickCount () pour obtenir le nombre de millisecondes qui se sont écoulées depuis le démarrage du système.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();
28
répondu RvdK 2013-06-10 11:11:52

time(NULL) renvoie le nombre de secondes écoulées depuis le 01/01/1970 à 00:00 ( l'Époque ). Donc, la différence entre les deux valeurs est le nombre de secondes de votre traitement pris.

int t0 = time(NULL);
doSomthing();
doSomthingLong();
int t1 = time(NULL);

printf ("time = %d secs\n", t1 - t0);

vous pouvez obtenir des résultats plus précis avec getttimeofday() , qui renvoient le temps courant en secondes, comme time() le fait et aussi en microsecondes.

12
répondu philant 2010-05-11 06:18:10

la fonction Time (NULL) retournera le nombre de secondes écoulées depuis le 01/01/1970 à 00:00. Et parce que, cette fonction est appelée à un moment différent dans votre programme, elle sera toujours différente de Temps en C++

12
répondu vodkhang 2010-06-02 14:43:38
#include<time.h> // for clock
#include<math.h> // for fmod
#include<cstdlib> //for system
#include <stdio.h> //for delay

using namespace std;

int main()
{


   clock_t t1,t2;

   t1=clock(); // first time capture

   // Now your time spanning loop or code goes here
   // i am first trying to display time elapsed every time loop runs

   int ddays=0; // d prefix is just to say that this variable will be used for display
   int dhh=0;
   int dmm=0;
   int dss=0;

   int loopcount = 1000 ; // just for demo your loop will be different of course

   for(float count=1;count<loopcount;count++)
   {

     t2=clock(); // we get the time now

     float difference= (((float)t2)-((float)t1)); // gives the time elapsed since t1 in milliseconds

    // now get the time elapsed in seconds

    float seconds = difference/1000; // float value of seconds
    if (seconds<(60*60*24)) // a day is not over
    {
        dss = fmod(seconds,60); // the remainder is seconds to be displayed
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the remainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= hours;  // the hours to be displayed
        ddays=0;
    }
    else // we have reached the counting of days
    {
        float days = seconds/(24*60*60);
        ddays = (int)(days);
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the rmainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= fmod (hours,24);  // the hours to be displayed

    }

    cout<<"Count Is : "<<count<<"Time Elapsed : "<<ddays<<" Days "<<dhh<<" hrs "<<dmm<<" mins "<<dss<<" secs";


    // the actual working code here,I have just put a delay function
    delay(1000);
    system("cls");

 } // end for loop

}// end of main 
9
répondu Eskay 2012-09-15 14:07:28

les valeurs imprimées par votre second programme sont des secondes, et des microsecondes.

0 26339 = 0.026'339 s =   26339 µs
4 45025 = 4.045'025 s = 4045025 µs
8
répondu Didier Trosset 2012-09-16 18:36:34
struct profiler
{
    std::string name;
    std::chrono::high_resolution_clock::time_point p;
    profiler(std::string const &n) :
        name(n), p(std::chrono::high_resolution_clock::now()) { }
    ~profiler()
    {
        using dura = std::chrono::duration<double>;
        auto d = std::chrono::high_resolution_clock::now() - p;
        std::cout << name << ": "
            << std::chrono::duration_cast<dura>(d).count()
            << std::endl;
    }
};

#define PROFILE_BLOCK(pbn) profiler _pfinstance(pbn)

utilisation est ci-dessous::

{
    PROFILE_BLOCK("Some time");
    // your code or function
}

ce champ d'application est similaire à celui de la Rai I

notez que ce n'est pas le mien, mais j'ai pensé que c'était pertinent ici

8
répondu 2016-06-03 06:46:21
#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;
}
7
répondu Akanksha Gupta 2016-12-03 12:28:12

en interne, la fonction accédera à l'horloge du système, c'est pourquoi elle renvoie des valeurs différentes chaque fois que vous l'appelez. En général, avec les langages non fonctionnels, il peut y avoir beaucoup d'effets secondaires et d'États cachés dans les fonctions que vous ne pouvez pas voir simplement en regardant le nom et les arguments de la fonction.

2
répondu Mike Weller 2010-05-11 06:17:18

l'appel de fonction time(NULL) retournera le nombre de secondes écoulées depuis epoc: 1er janvier 1970. Peut-être voulez-vous faire la différence entre deux repères temporels:

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

printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start);
2
répondu wilhelmtell 2010-05-11 06:29:25

de ce qui est voir, tv_sec stocke les secondes écoulées tandis que tv_usec stocke les microsecondes écoulées séparément. Et ce ne sont pas des conversions les unes des autres. Par conséquent, ils doivent être changés en unité appropriée et ajoutés pour obtenir le temps total écoulé.

struct timeval startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

printf("**time taken in microseconds = %ld\n",
    (endTV.tv_sec * 1e6 + endTV.tv_usec - (startTV.tv_sec * 1e6 + startTV.tv_usec))
    );
2
répondu Safar Ligal 2015-01-26 09:50:30

Sur linux, clock_gettime() est l'un des bons choix. Vous devez relier la bibliothèque temps réel(-lrt).

#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 );
  }
2
répondu cloudrain21 2015-09-22 21:44:32

comme d'autres l'ont déjà noté, la fonction time() de la bibliothèque standard C n'a pas de résolution meilleure qu'une seconde. La seule fonction c entièrement portable qui peut fournir une meilleure résolution semble être clock(), mais qui mesure le temps processeur plutôt que wallclock time. Si l'on se contente de se limiter aux plates-formes POSIX (par exemple Linux), alors la fonction clock_gettime() est un bon choix.

depuis C++11, Il ya beaucoup mieux installations disponibles qui offrent une meilleure résolution sous une forme qui devrait être très portable à travers différents compilateurs et systèmes d'exploitation. De même, la bibliothèque boost::datetime fournit de bonnes classes de synchronisation à haute résolution qui devraient être hautement portables.

l'un des défis que pose l'utilisation de l'une ou l'autre de ces installations est le délai introduit par la vérification de l'horloge du système. D'expérimenter avec clock_gettime (), boost:: datetime et std:: chrono, ce délai peut facilement être une question de microsecondes. Ainsi, lorsque vous mesurez la durée de n'importe quelle partie de votre code, vous devez tenir compte de l'existence d'une erreur de mesure d'environ cette taille, ou essayer de corriger cette erreur zéro d'une façon ou d'une autre. Idéalement, vous pourriez vouloir recueillir de multiples mesures du temps pris par votre fonction, et de calculer la moyenne, ou le temps maximum/minimum pris à travers de nombreux passages.

pour aider avec toutes ces portabilité et la collecte de statistiques questions, j'ai été le développement de la cxx-rtimers bibliothèque disponible sur Github qui tente de fournir une API simple pour le calendrier des blocs de code C++, informatique zéro des erreurs, et des rapports statistiques à partir de plusieurs minuteries intégrées dans votre code. Si vous avez un compilateur C++11, Vous avez simplement #include <rtimers/cxx11.hpp> , et utilisez quelque chose comme:

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

à la sortie du programme, vous obtiendrez un résumé des statistiques de temps écrit à std:: cerr tel que:

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

qui montre le temps moyen, son écart-type, les limites supérieure et inférieure, et le nombre de fois que cette fonction a été appelée.

si vous voulez utiliser des fonctions de synchronisation spécifiques à Linux, vous pouvez #include <rtimers/posix.hpp> , ou si vous avez les bibliothèques Boost mais un ancien compilateur C++, vous pouvez #include <rtimers/boost.hpp> . Il existe également des versions de ces classes de minuterie qui peuvent recueillir des informations statistiques sur le temps à partir de plusieurs fils. Il y a également d'autres méthodes permet d'estimer l'erreur zéro associée à deux requêtes consécutives de l'horloge du système.

2
répondu rwp 2018-02-10 09:45:31

ce sont les mêmes parce que votre fonction doSomething arrive plus vite que la granularité du minuteur. Essayez:

printf ("**MyProgram::before time= %ld\n", time(NULL));

for(i = 0; i < 1000; ++i) {
    doSomthing();
    doSomthingLong();
}

printf ("**MyProgram::after time= %ld\n", time(NULL));
1
répondu kibibu 2010-05-11 06:28:07

la raison pour laquelle les deux valeurs sont les mêmes est que votre longue procédure ne prend pas que longtemps - moins d'une seconde. Vous pouvez essayer juste d'ajouter une longue boucle (pour (int i = 0; i < 100000000; I++) ; ) à la fin de la fonction pour s'assurer que c'est le problème, alors nous pouvons partir de là...

dans le cas où ce qui précède s'avère être vrai, vous aurez besoin de trouver une fonction système différente (je comprends que vous travaillez sur linux, donc je ne peux pas vous aider avec le nom de la fonction) pour mesurer le temps avec plus de précision. Je suis sûr qu'il y a une fonction similaire à GetTickCount() dans linux, vous avez juste besoin de la trouver.

1
répondu David Božjak 2010-05-11 06:35:59

j'utilise habituellement ce qui suit:

#include <chrono>
#include <type_traits>

using perf_clock = std::conditional<
    std::chrono::high_resolution_clock::is_steady,
    std::chrono::high_resolution_clock,
    std::chrono::steady_clock
>::type;

using floating_seconds = std::chrono::duration<double>;

template<class F, class... Args>
floating_seconds run_test(Func&& func, Args&&... args)
{
   const auto t0 = perf_clock::now();
   std::forward<Func>(func)(std::forward<Args>(args)...);
   return floating_seconds(perf_clock::now() - t0);
} 

c'est la même chose que @nikos-athanasiou a proposé sauf que j'évite d'utiliser une horloge non stable et utilise un nombre de secondes flottant comme Durée.

1
répondu oliora 2016-03-01 21:24:42

c++ std::chrono a un avantage évident d'être multiplateforme. Cependant, il introduit également un frais généraux significatif par rapport à POSIX clock_gettime(). Sur ma Linux box tous les std::chrono::xxx_clock::now() saveurs effectuer à peu près la même chose:

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

bien que POSIX clock_gettime(CLOCK_MONOTONIC, &time) devrait être identique à steady_clock::now() mais il est plus de x3 fois plus rapide!

Voici mon test, pour être complet.

#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) / 1e6 + (end.tv_sec - start.tv_sec) * 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;
}

et c'est la sortie I obtenez lorsque compilé avec gcc7.2-O3:

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
1
répondu Alexey Polonsky 2018-03-12 13:02:58

En réponse à des OP trois questions spécifiques.

"Ce que je ne comprends pas, c'est pourquoi les valeurs avant et après sont les mêmes? "

la première question et le code d'exemple montre que time() a une résolution de 1 seconde, donc la réponse doit être que les deux fonctions s'exécutent en moins d'une seconde. mais de temps en temps (apparemment illogique) informer 1 seconde si les deux marques de minuterie chevauchent une limite d'une seconde.

L'exemple suivant utilise gettimeofday() qui remplit cette structure

struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};

et le seconde question , demande: "Comment puis-je lire la suite de **time taken = 0 26339 ? Est-ce que ça veut dire 26.339 nanosecondes = 26.3 msec?"

ma deuxième réponse est le temps pris est 0 secondes et 26339 microsecondes, soit 0,026339 secondes, ce qui confirme le premier exemple exécuté en moins d'une seconde.

la troisième question demande: " Qu'en est-il de **time taken = 4 45025 , est-ce que cela signifie 4 secondes et 25 msec?"

ma troisième réponse est le temps pris est de 4 secondes et 45025 microsecondes, soit 4.045025 secondes, ce qui montre que L'OP a modifié les tâches effectuées par les deux fonctions qu'il avait programmé.

0
répondu Weather Vane 2015-01-27 09:34:27

vous pouvez utiliser bibliothèque SFML , qui est une bibliothèque multimédia Simple et rapide. Il comprend de nombreuses classes utiles et bien définies comme L'horloge, Socket, son, graphiques, etc. Il est si facile à utiliser et fortement recommandé.

ceci est un exemple pour cette question.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
-4
répondu cloudrain21 2015-09-23 02:26:02