Misura facilmente il tempo trascorso


297

Sto cercando di usare time () per misurare vari punti del mio programma.

Quello che non capisco è perché i valori nel prima e nel dopo sono gli stessi? Capisco che questo non è il modo migliore per profilare il mio programma, voglio solo vedere quanto tempo impiega qualcosa.

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

doSomthing();
doSomthingLong();

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

Ho provato:

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

Come posso leggere un risultato di **time taken = 0 26339? Significa 26.339 nanosecondi = 26.3 msec?

Che dire **time taken = 4 45025, significa 4 secondi e 25 msec?


10
Non capisco la domanda. Naturalmente i valori sono diversi. Il tempo è passato in mezzo, quindi time()restituisce un valore diverso.
Thomas,

1
Cosa intendi con "Non capisco perché i valori nel prima e nel dopo sono diversi"? Stai ricevendo l'ora corrente (in secondi dal 1 ° gennaio 1970) usando time(NULL)... la seconda volta che chiami sarà N secondi dopo il primo e quindi ... diverso (a meno che qualunque cosa tu stia facendo non lo fa ci vorrà un secondo per completare ... nel qual caso, sarà lo stesso del primo).
Brian Roach,

1
Puoi dirci cosa stampa e quanto tempo impieghi se cronometri con un cronometro o un orologio da parete (o un calendario)?
Matt Curtis,

4
Siamo spiacenti, intendo che entrambi i valori sono gli stessi. Ho sbagliato a digitare la mia domanda.
hap497,

Risposte:


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
sì, questa dovrebbe essere la risposta
Ferenc Dajka,

23
Per eseguire questo si deve aggiungere la #include <chrono>direttiva e vorrei cambiare il tempo sulla presentazione dei risultati: std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;(e non dimenticare il C ++ 11 bandiera durante la compilazione: -std=c++11)
Antonello

1
A proposito, questo misura il tempo della CPU, non l'ora del wall clock. Destra?
Nikos,

4
@ RestlessC0bra Secondo i documenti su cppreference, "Questo orologio non è correlato al tempo dell'orologio da parete (ad esempio, può essere il tempo dall'ultimo riavvio) ed è più adatto per misurare gli intervalli".
Ciclo

1
Che tipo di dati è questo? Std :: chrono :: duration_cast <std :: chrono :: microsecondi> (fine - inizio) .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()funzione è precisa solo entro un secondo, ma ci sono CLOCKS_PER_SEC"orologi" entro un secondo. Questa è una misura semplice e portatile, anche se è troppo semplificata.


129
Tenere presente che clock()misura il tempo della CPU, non il tempo effettivo trascorso (che potrebbe essere molto maggiore).
jlstrecker,

12
Quando si programma il codice parallelo per i cluster, questo metodo non riflette l'ora del mondo reale ...
Nicholas Hamilton,

3
Questo sembra il modo più semplice. Ti andrebbe di aggiornare o rispondere al commento fatto da @jlstrecker?
Lorah Attkins,

5
La soluzione pubblicata sopra non è una buona soluzione per molte ragioni. Questa è la risposta corretta - stackoverflow.com/questions/2962785/...
Xofo

1
Ho provato questa soluzione e, come suggerito dai commenti, il mio timer ha funzionato molto più velocemente del tempo reale.
RTbecard

267

È possibile sottrarre il meccanismo di misurazione del tempo e misurare il tempo di esecuzione di ciascun callable con un codice aggiuntivo minimo , semplicemente chiamando tramite una struttura timer. Inoltre, al momento della compilazione è possibile parametrizzare il tipo di temporizzazione (millisecondi, nanosecondi ecc.).

Grazie alla recensione di Loki Astari e al suggerimento di utilizzare modelli variadici. Questo è il motivo per cui la chiamata di funzione inoltrata.

#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

Secondo il commento di Howard Hinnant è meglio non fuggire dal sistema crono fino a quando non sarà necessario. Quindi la classe sopra potrebbe dare all'utente la possibilità di chiamare countmanualmente fornendo un metodo statico aggiuntivo (mostrato in 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;

ed essere molto utile per i clienti che

"desidera post-elaborazione un sacco di durate prima dell'I / O (ad es. media)"


Il codice completo è disponibile qui . Il mio tentativo di creare uno strumento di benchmarking basato su chrono è registrato qui .


Se std::invokeè disponibile C ++ 17 , l'invocazione della chiamata in executionpotrebbe essere fatta in questo modo:

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

per fornire callable che sono puntatori a funzioni membro.


2
Bello; Ho qualcosa di simile nel mio codice, ma uso un'interfaccia diversa dalla classe: ho una classe ( code_timer) che impiega l'ora di inizio ( std::chrono::system_clock::now();) nel costruttore, un metodo code_timer::ellapsedche misura la differenza tra una nuova now()chiamata e quella nel costruttore e un code_timer::resetmetodo che reimposta l'ora di inizio su un nuovo now()risultato. Per misurare l'esecuzione di un functor nel mio codice, utilizzo una funzione gratuita, al di fuori della classe. Ciò consente di misurare il tempo dalla costruzione di un oggetto, alla fine di una chiamata asincrona.
utnapistim

7
<nitpick>: non uscire dal chronosistema fino a quando non è necessario (evitare l'uso di .count()). Lascia che il client chiami .count()quando è costretto a (diciamo per I / O, che è davvero sfortunato). Il cliente potrebbe voler postelaborare un certo numero di durate prima dell'I / O (ad es. Media) e ciò è meglio fare all'interno del chronosistema.
Howard Hinnant,

1
@ user3241228 1. VS2013 non supporta i tipi di ritorno automatico (solo i tipi di ritorno finali - è una funzione c ++ 14 non ancora disponibile). 2. Credo che questo sia il motivo, ma ho chiesto aq solo per essere sicuro
Nikos Athanasiou,

2
Perché no std::forward<F>(func)?
Oliora,

3
@oliora È la stessa cosa. Preferisco std::forward<decltype(func)>(func)perché può applicarsi agli argomenti di lambdas generici ( auto&& func) dove Fnon è sintatticamente presente ed è facile astrarre in una macro di utilità #define fw(arg) std::forward<decltype(arg)>(arg)che faccio nella mia libreria di benchmark (quindi è una sintattica rimasta su cui non elaboro molto in la risposta)
Nikos Athanasiou,

56

Come posso vedere dalla tua domanda, sembra che tu voglia conoscere il tempo trascorso dopo l'esecuzione di un pezzo di codice. Immagino che saresti a tuo agio nel vedere i risultati in secondi. In tal caso, prova a utilizzare la difftime()funzione come mostrato di seguito. Spero che questo risolva il tuo problema.

#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
Questo mi dà sempre secondi interi. Dovrebbe succedere?
nitrato di sodio

10
il tempo restituirà sempre solo secondi, quindi non può essere utilizzato per misurazioni seconde.
DeepDeadpool,

31

Solo Windows: (il tag Linux è stato aggiunto dopo aver pubblicato questa risposta)

È possibile utilizzare GetTickCount () per ottenere il numero di millisecondi trascorsi dall'avvio del sistema.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

7
Lo sto usando su Linux. Quindi non posso usare la funzione GetTickCount ().
hap497,

1
già non importa;) Grazie per aver aggiornato il tag del tuo post
RvdK

Funziona e dà il tempo reale, non il tempo della CPU. L'ho provato mettendo SleepEx(5000,0)al posto di // Eseguire un'operazione che richiede tempo e la differenza di aftered beforeera quasi 5 sec.
Ruchir,

14

time(NULL)restituisce il numero di secondi trascorsi dall'01 / 01/1970 alle 00:00 ( l'epoca ). Quindi la differenza tra i due valori è il numero di secondi necessari per l'elaborazione.

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

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

Puoi ottenere risultati più fini con getttimeofday(), che restituiscono l'ora corrente in secondi, così come time()anche in microsecondi.


13

la funzione tempo (NULL) restituirà il numero di secondi trascorsi dall'01 / 01/1970 alle 00:00. E poiché quella funzione viene chiamata in momenti diversi nel tuo programma, sarà sempre diverso in C ++


Non so perché qualcuno abbia effettuato il downgrade, ma la tua risposta non è del tutto corretta. Per cominciare non restituisce l'ora della data e non sarà sempre diverso.
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'uso è sotto ::

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

Questo è simile all'ambito RAII

NOTA questo non è mio, ma ho pensato che fosse rilevante qui


1
include mancante
Stepan Yakovenko il

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
Sebbene la tua risposta sia apprezzata, preferiamo un preambolo contenente una breve descrizione del codice. Grazie.
Kev

2
Questo non è il tempo trascorso, ma il tempo del processore.
JonnyJD,

8

I valori stampati dal secondo programma sono secondi e microsecondi.

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 ha un chiaro vantaggio di essere multipiattaforma. Tuttavia, introduce anche un overhead significativo rispetto a POSIX clock_gettime (). Sulla mia scatola di Linux tutte le std::chrono::xxx_clock::now()versioni hanno approssimativamente le stesse prestazioni:

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

Sebbene POSIX clock_gettime(CLOCK_MONOTONIC, &time)dovrebbe essere lo stesso di steady_clock::now()ma è più di x3 volte più veloce!

Ecco il mio test, per completezza.

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

E questo è l'output che ottengo quando compilato con 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

La time(NULL)chiamata di funzione restituirà il numero di secondi trascorsi dall'epoc: 1 gennaio 1970. Forse ciò che intendi fare è prendere la differenza tra due timestamp:

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

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

3

Come altri hanno già notato, la funzione time () nella libreria standard C non ha una risoluzione migliore di un secondo. L'unica funzione C completamente portatile che può fornire una migliore risoluzione sembra essere clock (), ma che misura il tempo del processore piuttosto che il tempo di wallclock. Se uno è contento di limitarsi alle piattaforme POSIX (ad es. Linux), allora la funzione clock_gettime () è una buona scelta.

A partire da C ++ 11, sono disponibili strutture di timing molto migliori che offrono una migliore risoluzione in una forma che dovrebbe essere molto portabile su diversi compilatori e sistemi operativi. Allo stesso modo, la libreria boost :: datetime offre buone classi di temporizzazione ad alta risoluzione che dovrebbero essere altamente portabili.

Una sfida nell'uso di una di queste strutture è il ritardo introdotto dall'interrogazione dell'orologio di sistema. Dalla sperimentazione di clock_gettime (), boost :: datetime e std :: chrono, questo ritardo può facilmente essere una questione di microsecondi. Pertanto, quando si misura la durata di qualsiasi parte del codice, è necessario consentire che si verifichi un errore di misurazione di queste dimensioni o provare in qualche modo a correggere l'errore zero. Idealmente, potresti voler raccogliere più misurazioni del tempo impiegato dalla tua funzione e calcolare il tempo medio o massimo / minimo impiegato in molte sessioni.

Per aiutare con tutti questi problemi di portabilità e raccolta di statistiche, ho sviluppato la libreria cxx-rtimers disponibile su Github che cerca di fornire una semplice API per i blocchi di temporizzazione del codice C ++, calcolare zero errori e riportare statistiche da più timer incorporati nel tuo codice. Se hai un compilatore C ++ 11, devi semplicemente #include <rtimers/cxx11.hpp>usare qualcosa come:

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

All'uscita dal programma, otterrai un riepilogo delle statistiche di temporizzazione scritto su std :: cerr come:

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

che mostra il tempo medio, la sua deviazione standard, i limiti superiore e inferiore e il numero di volte in cui è stata chiamata questa funzione.

Se vuoi usare funzioni di temporizzazione specifiche di Linux, puoi #include <rtimers/posix.hpp>, o se hai le librerie Boost ma un compilatore C ++ più vecchio, puoi farlo #include <rtimers/boost.hpp>. Esistono anche versioni di queste classi di timer che possono raccogliere informazioni temporali statistiche su più thread. Esistono anche metodi che consentono di stimare l'errore zero associato a due query immediatamente consecutive dell'orologio di sistema.


2

Internamente la funzione accederà all'orologio del sistema, motivo per cui restituisce valori diversi ogni volta che lo chiami. In generale con linguaggi non funzionali ci possono essere molti effetti collaterali e stati nascosti nelle funzioni che non si possono vedere semplicemente guardando il nome e gli argomenti della funzione.


2

Da quanto si vede, tv_sec memorizza i secondi trascorsi mentre tv_usec memorizzava i microsecondi trascorsi separatamente. E non sono le conversioni reciproche. Quindi, devono essere cambiati nell'unità corretta e aggiunti per ottenere il tempo totale trascorso.

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

Su Linux, clock_gettime () è una delle buone scelte. È necessario collegare la libreria in tempo reale (-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

Avevo bisogno di misurare i tempi di esecuzione delle singole funzioni all'interno di una libreria. Non volevo dover avvolgere ogni chiamata di ogni funzione con una funzione di misurazione del tempo perché è brutta e approfondisce lo stack di chiamate. Inoltre, non volevo mettere il codice timer all'inizio e alla fine di ogni funzione perché crea un casino quando la funzione può uscire anticipatamente o generare eccezioni, ad esempio. Quindi quello che ho finito è stato creare un timer che utilizza la propria vita per misurare il tempo.

In questo modo posso misurare il wall-time che un blocco di codice ha preso semplicemente istanziando uno di questi oggetti all'inizio del blocco di codice in questione (funzione o qualsiasi ambito realmente) e quindi permettendo al distruttore di istanze di misurare il tempo trascorso da costruzione quando l'istanza esce dal campo di applicazione. Puoi trovare l'esempio completo qui ma la struttura è estremamente semplice:

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 struttura ti richiamerà sul funzione fornita quando esce dal campo di applicazione in modo da poter fare qualcosa con le informazioni di temporizzazione (stamparlo o memorizzarlo o altro). Se avete bisogno di fare qualcosa di ancora più complesso si potrebbe anche usare std::bindconstd::placeholders per callback funzioni con più argomenti.

Ecco un breve esempio di utilizzo:

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

Se vuoi essere più deliberato, puoi anche usare newe deleteavviare e arrestare esplicitamente il timer senza fare affidamento sull'ambito per farlo.


1

Sono gli stessi perché la tua funzione doSomething è più rapida della granularità del timer. Provare:

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

Il motivo per cui entrambi i valori sono gli stessi è dovuto alla lunga procedura non richiede così tanto tempo - meno di un secondo. Puoi provare ad aggiungere un ciclo lungo (per (int i = 0; i <100000000; i ++);) alla fine della funzione per assicurarti che questo sia il problema, quindi possiamo andare da lì ...

Nel caso in cui quanto sopra risulti essere vero, dovrai trovare una diversa funzione di sistema (ho capito che lavori su Linux, quindi non posso aiutarti con il nome della funzione) per misurare il tempo in modo più accurato. Sono sicuro che esiste una funzione simile a GetTickCount () in Linux, devi solo trovarla.


1

Di solito uso quanto segue:

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

È lo stesso proposto da @ nikos-athanasiou, tranne per il fatto che evito l'uso di un orologio non costante e utilizzo un numero variabile di secondi come durata.


1
Su questo switch di tipi : in genere high_resolution_clockè un typedef per uno system_clocko steady_clock. Quindi, per rintracciare che std::conditionalse la is_steadyparte è vera, allora scegli high_resolution_clockquale è (un typedef in) il steady_clock. Se è falso, scegli di steady_clocknuovo. Basta usare steady_clockdall'inizio ...
Nikos Athanasiou il

@ nikos-athanasiou Concordo pienamente con il commento di 5gon12eder che il caso "tipico" non è richiesto dallo standard, quindi alcuni STL potrebbero essere implementati in modo diverso. Preferisco che il mio codice sia più generico e non correlato ai dettagli di implementazione.
Oliora,

Non è richiesto, ma esplicitamente affermato nel 20.12.7.3 : high_resolution_clock may be a synonym for system_clock or steady_clock. Il motivo è questo: high_resolution_clockrappresenta gli orologi con il più breve periodo di tick, quindi qualunque sia l'implementazione, ha due scelte, sia costante che no. Qualunque scelta facciamo, dire che l'implementazione differirà dagli altri due orologi è come dire che abbiamo un'implementazione migliore per un orologio stabile (o no) che scegliamo di non usare (per orologi fissi o meno). Sapere quanto va bene, sapere perché è meglio
Nikos Athanasiou,

@ nikos-athanasiou Preferirei essere sicuro al 100%, specialmente quando questo non mi costava alcun tempo di esecuzione e sovraccarico del tempo di compilazione non rilevabile. Se lo desideri, puoi fare affidamento su "may" e su assunzioni.
Oliora,

au contraire amico mio, sei tu che fai affidamento su "may", ma per te. Se vuoi essere sicuro al 100% e continuare a scrivere questo, dovresti anche trovare un modo, per te e gli utenti del tuo codice, per evitare di mescolare in modo non portabile i punti temporali di diversi orologi (se mai questo interruttore di tipo acquisisce un significato, si comporterà diversamente su piattaforme diverse). Divertiti!
Nikos Athanasiou,

0

In risposta alle tre domande specifiche dell'OP .

"Quello che non capisco è perché i valori nel prima e nel dopo sono gli stessi? "

La prima domanda e il codice di esempio mostrano che time()ha una risoluzione di 1 secondo, quindi la risposta deve essere che le due funzioni vengono eseguite in meno di 1 secondo. Ma a volte informerà (apparentemente illogicamente) 1 secondo se i due segni del timer si trovano a cavallo di un limite di un secondo.

L'esempio seguente usa ciò gettimeofday()che riempie questa struttura

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

e la seconda domanda chiede: "Come posso leggere un risultato di **time taken = 0 26339? Significa 26.339 nanosecondi = 26.3 msec?"

La mia seconda risposta è che il tempo impiegato è 0 secondi e 26339 microsecondi, ovvero 0,026339 secondi, che conferma il primo esempio eseguito in meno di 1 secondo.

La terza domanda si pone: "Che dire **time taken = 4 45025, significa 4 secondi e 25 msec?"

La mia terza risposta è che il tempo impiegato è di 4 secondi e 45025 microsecondi, ovvero 4,045025 secondi, il che dimostra che OP ha modificato le attività svolte dalle due funzioni che aveva precedentemente cronometrato.


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

}

Esempio simile a quello disponibile qui, solo con funzione di conversione aggiuntiva + stampa.


0

Ho creato una classe per misurare automaticamente il tempo trascorso, controlla il codice (c ++ 11) in questo link: https://github.com/sonnt174/Common/blob/master/time_measure.h

Esempio di utilizzo della 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));
}

Mi piace la tua dichiarazione di stampa con le unità. Cosa ci vorrebbe per portare il tuo codice su gcc e clang? ( wandbox.org )
Howard Hinnant, il

1
@HowardHinnant: grazie per l'indirizzamento, ho aggiornato anche il codice per gcc e clang.
Sirn Nguyen Truong,

0

Matlab aromatizzato!

ticavvia un cronometro per misurare le prestazioni. La funzione registra il tempo interno all'esecuzione del comando tic. Visualizza il tempo trascorso con la tocfunzione.

#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

È possibile utilizzare la libreria SFML , che è Libreria multimediale semplice e veloce. Comprende molte classi utili e ben definite come Clock, Socket, Sound, Graphics, ecc. È così facile da usare e altamente raccomandato.

Questo è un esempio per questa domanda.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.