Mesurer facilement le temps écoulé


297

J'essaie d'utiliser time () pour mesurer divers points de mon programme.

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

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

doSomthing();
doSomthingLong();

printf("**MyProgram::after time= %ld\n", 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 %ld\n", diff.tv_sec, diff.tv_usec);

Comment lire un résultat de **time taken = 0 26339? Cela signifie-t-il 26 339 nanosecondes = 26,3 ms?

Et **time taken = 4 45025cela signifie-t-il 4 secondes et 25 ms?


10
Je ne comprends pas la question. Bien sûr, les valeurs sont différentes. Le temps s'est écoulé entre les deux, time()renvoie donc une valeur différente.
Thomas

1
Que voulez-vous dire "Je ne comprends pas pourquoi les valeurs de l'avant et de l'après sont différentes"? Vous obtenez l'heure actuelle (en secondes depuis le 1er janvier 1970) en utilisant time(NULL)... la deuxième fois que vous appelez, ce sera N secondes après la première et donc ... différent (à moins que ce que vous faites ne le fasse pas) t prendre une seconde pour terminer ... dans ce cas, ce sera le même que le premier).
Brian Roach

1
Pouvez-vous nous dire ce qu'il imprime et combien de temps cela prend si vous le chronométrez avec un chronomètre ou une horloge murale (ou un calendrier)?
Matt Curtis

4
Désolé, je veux dire que les deux valeurs sont identiques. J'ai mal saisi ma question.
hap497

Réponses:


336
//***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;

10
oui, cela devrait être la réponse
Ferenc Dajka

23
Pour exécuter cela , vous devez ajouter la #include <chrono>directive et je changerais le temps de rapports que: std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;(et ne pas oublier le C ++ 11 drapeau lors de la compilation: -std=c++11)
Antonello

1
Soit dit en passant, cela mesure le temps CPU, pas le temps de l'horloge murale. Droite?
Nikos

4
@ RestlessC0bra Selon les documents sur cppreference, "Cette horloge n'est pas liée à l'heure de l'horloge murale (par exemple, elle peut être la durée depuis le dernier redémarrage), et est la plus appropriée pour mesurer les intervalles."
cylus

1
De quel type de données s'agit-il? Std :: chrono :: duration_cast <std :: chrono :: microsecondes> (fin - début) .count ()
sqp_125

272
#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 time()fonction n'est précise qu'à une seconde près, mais il y a des CLOCKS_PER_SEC"horloges" à l'intérieur d'une seconde. Il s'agit d'une mesure facile et portable, même si elle est trop simplifiée.


129
Sachez que cela clock()mesure le temps CPU, et non le temps réel écoulé (qui peut être beaucoup plus long).
jlstrecker

12
Lors de la programmation de code parallèle pour des clusters, cette méthode ne reflète pas l'heure réelle ...
Nicholas Hamilton

3
Cela semble le plus simple des moyens. Souhaitez-vous mettre à jour ou répondre au commentaire fait @jlstrecker?
Lorah Attkins

5
La solution affichée ci-dessus n'est pas une bonne solution pour de nombreuses raisons. C'est la bonne réponse - stackoverflow.com/questions/2962785/…
Xofo

1
J'ai essayé cette solution, et comme les commentaires l'ont suggéré, ma minuterie a fonctionné beaucoup plus rapidement que le temps réel.
RTbecard

267

Vous pouvez faire abstraction du mécanisme de mesure du temps et faire mesurer le temps d'exécution de chaque appelable avec un code supplémentaire minimal , simplement en étant appelé via une structure de minuterie. De plus, au moment de la compilation, vous pouvez paramétrer le type de synchronisation (millisecondes, nanosecondes, etc.).

Merci à l'examen de Loki Astari et à la suggestion d'utiliser des modèles variadiques. C'est pourquoi l'appel de fonction renvoyé.

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

Demo

Selon le commentaire de Howard Hinnant, il est préférable de ne pas s'échapper du système de chrono jusqu'à ce que nous le devions. Ainsi, la classe ci-dessus pourrait donner à l'utilisateur le choix d'appeler countmanuellement en fournissant une méthode statique supplémentaire (affiché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 qui

"veulent post-traiter un tas de durées avant les E / S (par exemple en moyenne)"


Le code complet peut être trouvé ici . Ma tentative de construire un outil d'analyse comparative basé sur le chrono est enregistrée ici .


Si C ++ 17 std::invokeest disponible, l'appel de l'appelable executionpourrait se faire comme ceci:

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

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


2
Agréable; J'ai quelque chose de similaire dans mon code, mais j'utilise une interface différente de la classe: j'ai une classe ( code_timer) qui prend l'heure de début ( std::chrono::system_clock::now();) dans le constructeur, une méthode code_timer::ellapsedqui mesure la différence entre un nouvel now()appel et celui du constructeur et une code_timer::resetméthode qui réinitialise l'heure de début à un nouveau now()résultat. Pour mesurer l'exécution d'un foncteur dans mon code, j'utilise une fonction libre, en dehors de la classe. Cela permet de mesurer le temps entre la construction d'un objet et la fin d'un appel asynchrone.
utnapistim

7
<nitpick>: N'échappez pas du chronosystème jusqu'à ce que vous deviez (éviter d'utiliser .count()). Laissez le client appeler .count()lorsqu'il est forcé de le faire (par exemple pour les E / S, ce qui est en effet malheureux). Le client peut vouloir post-traiter un tas de durées avant les E / S (par exemple la moyenne) et cela est mieux fait dans le chronosystème.
Howard Hinnant

1
@ user3241228 1. VS2013 ne prend pas en charge les types de retour automatique (juste les types de retour de fin - c'est une fonctionnalité c ++ 14 qui n'est pas encore disponible). 2. Je crois que c'est la raison , mais j'ai demandé aq juste pour être sûr
Nikos Athanasiou

2
Pourquoi ne pas std::forward<F>(func)?
oliora

3
@oliora C'est la même chose. Je préfère std::forward<decltype(func)>(func)parce qu'il peut s'appliquer aux arguments de lambdas ( auto&& func) génériques où il Fn'y a pas de syntaxe et il est facile de résumer dans une macro utilitaire #define fw(arg) std::forward<decltype(arg)>(arg)que je fais dans ma bibliothèque de référence (c'est donc un reste syntaxique sur lequel je n'élabore pas beaucoup dans la réponse)
Nikos Athanasiou

56

Comme je peux le voir dans votre question, il semble que vous souhaitiez connaître 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 secondes. Si c'est le cas, essayez d'utiliser la difftime()fonction comme indiqué ci-dessous. J'espère que ceci résoudra 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 );

4
Cela me donne toujours des secondes entières. Est-ce que c'était supposé d'arriver?
nitrate de sodium

10
le temps ne renverra toujours que des secondes, il ne peut donc pas être utilisé pour des mesures en une seconde.
DeepDeadpool

31

Windows uniquement: (La balise Linux a été ajoutée après avoir 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();

7
Je l'utilise sur linux. Je ne peux donc pas utiliser la fonction GetTickCount ().
hap497

1
déjà tant pis;) Merci d'avoir mis à jour le tag de votre message
RvdK

Cela fonctionne et donne le temps réel, pas le temps CPU. Je l'ai testé en plaçant SleepEx(5000,0)à la place de // Effectuer une opération longue et différente de afteret beforeétait presque 5 secondes.
Ruchir

14

time(NULL)renvoie le nombre de secondes écoulées depuis le 01/01/1970 à 00:00 ( l'Epoch ). La différence entre les deux valeurs est donc le nombre de secondes que votre traitement a 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 fins avec getttimeofday(), qui renvoient l'heure actuelle en secondes, tout comme time()en microsecondes.


13

la fonction time (NULL) renverra le nombre de secondes écoulées depuis le 01/01/1970 à 00:00. Et parce que, cette fonction est appelée à différents moments de votre programme, ce sera toujours différent en C ++


Je ne sais pas pourquoi quelqu'un a voté contre, mais votre réponse n'est pas tout à fait correcte. Pour commencer, il ne renvoie pas la date et l'heure, et ce ne sera pas toujours différent.
Matt Joiner

12
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)

L'utilisation est ci-dessous ::

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

Ceci est similaire au RAII dans sa portée

NOTE ce n'est pas le mien, mais je pensais que c'était pertinent ici


1
comprend manquant
Stepan Yakovenko

9
#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 

3
Bien que votre réponse soit appréciée, nous préférons un préambule contenant une brève description du code. Merci.
Kev

2
Ce n'est pas le temps écoulé, mais le temps processeur.
JonnyJD

8

Les valeurs imprimées par votre deuxième programme sont les secondes et les microsecondes.

0 26339 = 0.026'339 s =   26339 µs
4 45025 = 4.045'025 s = 4045025 µs

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

4

C ++ std :: chrono a clairement l'avantage d'être multiplateforme. Cependant, il introduit également une surcharge importante par rapport à POSIX clock_gettime (). Sur ma boîte Linux, toutes les std::chrono::xxx_clock::now()saveurs fonctionnent à peu près de la même manière:

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 que temps de x3 plus vite!

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
                        ? (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;
}

Et voici la sortie que j'obtiens lors de la compilation 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

3

L' time(NULL)appel de fonction renverra le nombre de secondes écoulées depuis epoc: 1er janvier 1970. Peut-être que vous voulez faire la différence entre deux horodatages:

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

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

3

Comme d'autres l'ont déjà noté, la fonction time () dans la bibliothèque standard C n'a pas une 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 le temps d'horloge murale. Si l'on se contente de se limiter aux plateformes POSIX (par exemple Linux), la fonction clock_gettime () est un bon choix.

Depuis C ++ 11, il existe de bien meilleures fonctionnalités de synchronisation disponibles qui offrent une meilleure résolution sous une forme qui devrait être très portable sur 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.

Un défi dans l'utilisation de l'une de ces fonctionnalités est le délai introduit par l'interrogation de l'horloge système. De l'expérimentation de clock_gettime (), boost :: datetime et std :: chrono, ce délai peut facilement être une question de microsecondes. Ainsi, lorsque vous mesurez la durée d'une partie de votre code, vous devez autoriser une erreur de mesure d'environ cette taille, ou essayer de corriger cette erreur nulle d'une manière ou d'une autre. Idéalement, vous souhaiterez peut-être rassembler plusieurs mesures du temps pris par votre fonction et calculer le temps moyen ou maximum / minimum pris sur de nombreuses exécutions.

Pour aider avec tous ces problèmes de portabilité et de collecte de statistiques, j'ai développé la bibliothèque cxx-rtimers disponible sur Github qui essaie de fournir une API simple pour chronométrer des blocs de code C ++, calculer zéro erreur et rapporter les statistiques de plusieurs temporisateurs intégrés dans votre code. Si vous avez un compilateur C ++ 11, vous #include <rtimers/cxx11.hpp>utilisez simplement 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 synchronisation écrites dans std :: cerr, telles 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 souhaitez 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 temporisation qui peuvent collecter des informations de synchronisation statistiques sur plusieurs threads. Il existe également des méthodes qui vous permettent d'estimer l'erreur zéro associée à deux requêtes immédiatement consécutives de l'horloge système.


2

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


2

D'après ce que l'on voit, tv_sec stocke les secondes écoulées tandis que tv_usec stockait les microsecondes écoulées séparément. Et ce ne sont pas les conversions les uns 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

Sous linux, clock_gettime () est l'un des bons choix. Vous devez lier la bibliothèque en 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

J'avais besoin de mesurer le temps d'exécution de fonctions individuelles au sein d'une bibliothèque. Je ne voulais pas avoir à encapsuler chaque appel de chaque fonction avec une fonction de mesure du temps car c'est laid et approfondit la pile d'appels. Je ne voulais pas non plus mettre le code de la minuterie en haut et en bas de chaque fonction car cela gâche quand la fonction peut quitter tôt ou lever des exceptions par exemple. Donc, ce que j'ai fini par faire, c'était de créer une minuterie qui utilise sa propre durée de vie pour mesurer le temps.

De cette façon, je peux mesurer le temps passé par un bloc de code en instanciant simplement l'un de ces objets au début du bloc de code en question (fonction ou toute étendue vraiment), puis en permettant au destructeur d'instances de mesurer le temps écoulé depuis construction lorsque l'instance sort du champ d'application. Vous pouvez trouver l'exemple complet ici mais la structure est extrêmement simple:

template <typename clock_t = std::chrono::steady_clock>
struct scoped_timer {
  using duration_t = typename clock_t::duration;
  const std::function<void(const duration_t&)> callback;
  const std::chrono::time_point<clock_t> start;

  scoped_timer(const std::function<void(const duration_t&)>& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  scoped_timer(std::function<void(const duration_t&)>&& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  ~scoped_timer() { callback(clock_t::now() - start); }
};

La structure vous rappellera sur le foncteur fourni lorsqu'il sortira du champ d'application afin que vous puissiez faire quelque chose avec les informations de synchronisation (les imprimer ou les stocker ou autre). Si vous avez besoin de faire quelque chose d'encore plus complexe, vous pouvez même utiliser std::bindavec std::placeholderspour rappeler des fonctions avec plus d'arguments.

Voici un exemple rapide de son utilisation:

void test(bool should_throw) {
  scoped_timer<> t([](const scoped_timer<>::duration_t& elapsed) {
    auto e = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(elapsed).count();
    std::cout << "took " << e << "ms" << std::endl;
  });

  std::this_thread::sleep_for(std::chrono::seconds(1));

  if (should_throw)
    throw nullptr;

  std::this_thread::sleep_for(std::chrono::seconds(1));
}

Si vous voulez être plus délibéré, vous pouvez également utiliser newet deletepour démarrer et arrêter explicitement le minuteur sans compter sur la portée pour le faire pour vous.


1

Ce sont les mêmes parce que votre fonction doSomething se produit plus rapidement que la granularité de la minuterie. Essayer:

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

La raison pour laquelle les deux valeurs sont identiques est que votre longue procédure ne prend pas autant de temps - moins d'une seconde. Vous pouvez essayer d'ajouter simplement une longue boucle (pour (int i = 0; i <100000000; i ++);) à la fin de la fonction pour vous assurer que c'est bien le problème, alors nous pouvons y aller ...

Si ce qui précède s'avère vrai, vous devrez 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 plus précisément. Je suis sûr qu'il existe une fonction similaire à GetTickCount () sous Linux, il vous suffit de la trouver.


1

J'utilise généralement les éléments suivants:

#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 flottant de secondes comme durée.


1
Sur ce typewitch : high_resolution_clockest typiquement un typedef pour soit system_clockou steady_clock. Donc, pour tracer que std::conditionalsi la is_steadypartie est vraie, vous choisissez alors high_resolution_clockqui est (un typedef) steady_clock. Si c'est faux, vous choisissez à steady_clocknouveau. Utilisez juste steady_clockdepuis le début ...
Nikos Athanasiou

@ nikos-athanasiou Je suis entièrement d'accord avec le commentaire de 5gon12eder selon lequel le cas "typique" n'est pas requis par la norme, donc certains STL peuvent être implémentés d'une manière différente. Je préfère que mon code soit plus générique et non lié aux détails d'implémentation.
oliora

Il n'est pas nécessaire , mais explicitement dans 20.12.7.3 : high_resolution_clock may be a synonym for system_clock or steady_clock. La raison en est la suivante: high_resolution_clockreprésente les horloges avec la période de tick la plus courte, donc quelle que soit la mise en œuvre, elle a deux choix, stable ou non. Quel que soit le choix que nous faisons, dire que l'implémentation sera différente des deux autres horloges revient à dire que nous avons une meilleure implémentation pour une horloge stable (ou non) que nous choisissons de ne pas utiliser (pour des horloges stables ou non). Savoir comment est bon, savoir pourquoi est meilleur
Nikos Athanasiou

@ nikos-athanasiou Je préférerais être sûr à 100% surtout quand cela ne me coûte pas de temps d'exécution et de temps de compilation indétectable. Vous pouvez vous fier au «peut» et aux hypothèses si vous le souhaitez.
oliora

au contraire mon ami, c'est toi qui compte sur "may", mais qui te va. Si vous voulez être sûr à 100% et continuer à écrire ceci, vous devriez également trouver un moyen, pour vous et les utilisateurs de votre code, d'éviter de mélanger de manière non portative des points temporels d'horloges différentes (si jamais ce type de commutateur acquiert un sens, il se comportera différemment sur différentes plateformes). S'amuser!
Nikos Athanasiou

0

En réponse aux trois questions spécifiques d' OP .

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

La première question et l'exemple de code montre que time()la résolution est de 1 seconde, la réponse doit donc être que les deux fonctions s'exécutent en moins de 1 seconde. Mais parfois, il informera (apparemment de manière illogique) 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 la deuxième question demande: "Comment lire un résultat **time taken = 0 26339? Cela signifie-t-il 26 339 nanosecondes = 26,3 ms?"

Ma deuxième réponse est que le temps pris est de 0 seconde et 26339 microsecondes, soit 0,026339 seconde, ce qui confirme le premier exemple s'exécutant en moins de 1 seconde.

La troisième question demande: "Qu'en est-il **time taken = 4 45025, cela signifie-t-il 4 secondes et 25 ms?"

Ma troisième réponse est que le temps nécessaire est de 4 secondes et 45025 microsecondes, soit 4,045025 secondes, ce qui montre que OP a modifié les tâches effectuées par les deux fonctions qu'il avait précédemment chronométrées.


0
#include <ctime>
#include <functional>

using namespace std;

void f() {
  clock_t begin = clock();

  // ...code to measure time...

  clock_t end = clock();

  function<double(double, double)> convtime = [](clock_t begin, clock_t end)
  {
     return double(end - begin) / CLOCKS_PER_SEC;
  };

  printf("Elapsed time: %.2g sec\n", convtime(begin, end));

}

Exemple similaire à celui disponible ici, uniquement avec une fonction de conversion supplémentaire + impression.


0

J'ai créé une classe pour mesurer automatiquement le temps écoulé, veuillez vérifier le code (c ++ 11) dans ce lien: https://github.com/sonnt174/Common/blob/master/time_measure.h

Exemple d'utilisation de la classe TimeMeasure:

void test_time_measure(std::vector<int> arr) {
  TimeMeasure<chrono::microseconds> time_mea;  // create time measure obj
  std::sort(begin(arr), end(arr));
}

J'aime votre déclaration imprimée avec les unités. Que faudrait-il pour porter votre code sur gcc et clang? ( wandbox.org )
Howard Hinnant

1
@HowardHinnant: merci pour l'adressage, j'ai également mis à jour le code pour gcc et clang.
Sirn Nguyen Truong

0

Matlab parfumé!

ticdémarre un chronomètre pour mesurer les performances. La fonction enregistre l'heure interne à l'exécution de la commande tic. Affichez le temps écoulé avec la tocfonction.

#include <iostream>
#include <ctime>
#include <thread>
using namespace std;

clock_t START_TIMER;

clock_t tic()
{
    return START_TIMER = clock();
}

void toc(clock_t start = START_TIMER)
{
    cout
        << "Elapsed time: "
        << (clock() - start) / (double)CLOCKS_PER_SEC << "s"
        << endl;
}

int main()
{
    tic();
    this_thread::sleep_for(2s);
    toc();

    return 0;
}

-4

Vous pouvez utiliser la 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, la prise, le son, les graphiques, etc. Il est si facile à utiliser et hautement recommandé.

Ceci est un exemple pour cette question.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.