Come calcolare una differenza di orario in C ++


94

Qual è il modo migliore per calcolare una differenza di orario in C ++? Sto cronometrando la velocità di esecuzione di un programma, quindi sono interessato ai millisecondi. Meglio ancora, secondi.millisecondi ..

La risposta accettata funziona, ma deve includere ctime o time.h come indicato nei commenti.


Dupe, ma non è possibile collegarsi in questo momento
Robert Gould,

2
Il voto per chiudere è stato troppo poco, troppo tardi. Ho una risposta funzionante. Bel tentativo però. A proposito, non sono riuscito a trovare neanche un collegamento.
Jack BeNimble

È per Windows? quindi prova GetTickCount (API Windows)
aJ.

5
Robert: Fortunatamente, perché il nuovo intervento ha consentito molte altre risposte, una delle quali ho selezionato. Scherzi a parte, metto in dubbio il valore di chiudere un post duplice. E se alcune soluzioni non fossero state menzionate nella prima? Nuove tecnologie sviluppate? Non riesci a trovarlo a causa di intestazioni diverse?
Jack BeNimble

2
@JackBeNimble essendo stato il destinatario di alcuni "dups" che non erano esattamente dups (forse persone che forse leggono rapidamente la domanda e la contrassegnano perché suona simile a un'altra domanda), sono assolutamente d'accordo con il tuo punto ... probabilmente un punto per lo scambio di meta stack: o
code_fodder

Risposte:


122

Vedi std::clock()funzione.

const clock_t begin_time = clock();
// do something
std::cout << float( clock () - begin_time ) /  CLOCKS_PER_SEC;

Se vuoi calcolare il tempo di esecuzione per te stesso (non per l'utente), è meglio farlo in tick dell'orologio (non secondi).

EDIT:
file di intestazione responsabili - <ctime>o<time.h>


4
Tieni presente che anche se clock () restituisce un numero di millisecondi, la precisione di clock () può essere molto peggiore di quella. Prima istanza in Windows la precisione della funzione clock () è qualcosa come 40 ms.
John Dibling,

2
Ho provato questo su Mac 10.7. la mia app esegue un file da 100 mb in 15 secondi, ma il tempo di diff indica 61 secondi. Non molto utile. Penso che il tempo () sia probabilmente migliore.
Miek

5
clock()restituisce il tempo della CPU consumato dal programma. Quindi se il programma viene eseguito in parallelo, il tempo restituito dalla funzione sarebbe il tempo accumulato su tutte le CPU, piuttosto che il tempo trascorso cplusplus.com/reference/ctime/clock
Ameer Jewdaki

3
Questa risposta è fuorviante perché mostra l'ora della CPU, non l'ora effettiva dell'orologio da parete.
Ultravioletti

1
Devo essere d'accordo con Ultraviolet qui, usare il tempo della CPU per misurare la velocità di un programma sembra la cosa sbagliata da fare. OP dovrebbe deselezionarlo come risposta giusta. IMO si dovrebbe usare std :: :: crono steady_clock :: ora (), come descritto da più risposte in questo thread stackoverflow.com/questions/2808398/easily-measure-elapsed-time
Arunsun

37

se stai usando c ++ 11, ecco un semplice wrapper (guarda questo succo ):

#include <iostream>
#include <chrono>

class Timer
{
public:
    Timer() : beg_(clock_::now()) {}
    void reset() { beg_ = clock_::now(); }
    double elapsed() const { 
        return std::chrono::duration_cast<second_>
            (clock_::now() - beg_).count(); }

private:
    typedef std::chrono::high_resolution_clock clock_;
    typedef std::chrono::duration<double, std::ratio<1> > second_;
    std::chrono::time_point<clock_> beg_;
};

O per c ++ 03 su * nix:

#include <iostream>
#include <ctime>

class Timer
{
public:
    Timer() { clock_gettime(CLOCK_REALTIME, &beg_); }

    double elapsed() {
        clock_gettime(CLOCK_REALTIME, &end_);
        return end_.tv_sec - beg_.tv_sec +
            (end_.tv_nsec - beg_.tv_nsec) / 1000000000.;
    }

    void reset() { clock_gettime(CLOCK_REALTIME, &beg_); }

private:
    timespec beg_, end_;
};

Esempio di utilizzo:

int main()
{
    Timer tmr;
    double t = tmr.elapsed();
    std::cout << t << std::endl;

    tmr.reset();
    t = tmr.elapsed();
    std::cout << t << std::endl;
    return 0;
}

2
Un'altra opzione sarebbe quella di utilizzare boost :: chrono invece dello spazio dei nomi C ++ 11 STL std :: chrono. Grazie per il tuo codice.
Didac Perez Parera

Attenzione: questo non funzionerà se l'utente cambia il suo tempo tra Timer()e la chiamata a elapsed()if !std::chrono::high_resolution_clock::is_steady- che è il caso su Linux!
jhasse

30

Prenderei seriamente in considerazione l'uso di Boost, in particolare boost :: posix_time :: ptime e boost :: posix_time :: time_duration (su http://www.boost.org/doc/libs/1_38_0/doc/html/date_time/posix_time .html ).

È multipiattaforma, facile da usare e, secondo la mia esperienza, fornisce il massimo livello di risoluzione temporale fornito da un sistema operativo. Forse anche molto importante; fornisce alcuni operatori IO molto carini.

Per usarlo per calcolare la differenza nell'esecuzione del programma (in microsecondi; probabilmente eccessivo), sarebbe simile a questo [browser scritto, non testato]:

ptime time_start(microsec_clock::local_time());
//... execution goes here ...
ptime time_end(microsec_clock::local_time());
time_duration duration(time_end - time_start);
cout << duration << '\n';

3
Ma boost local_time () non è monotono, quindi non dovrebbe essere usato per misurare gli intervalli di tempo. Non ho trovato un modo per accedere al tempo monotono da Boost.
gatopeich

26

Ho aggiunto questa risposta per chiarire che la risposta accettata mostra il tempo della CPU che potrebbe non essere il tempo desiderato. Perché secondo il riferimento , ci sono il tempo della CPU e il tempo dell'orologio da parete . Il tempo dell'orologio da parete è il tempo che mostra il tempo trascorso effettivo indipendentemente da altre condizioni come la CPU condivisa da altri processi. Ad esempio, ho utilizzato più processori per eseguire un determinato compito e il tempo della CPU era alto 18s, dove in realtà ci sono voluti 2s nel tempo effettivo dell'orologio da parete.

Per ottenere il tempo effettivo che fai,

#include <chrono>

auto t_start = std::chrono::high_resolution_clock::now();
// the work...
auto t_end = std::chrono::high_resolution_clock::now();

double elapsed_time_ms = std::chrono::duration<double, std::milli>(t_end-t_start).count();

2
Non avrei potuto usare std :: chrono senza questa risposta, grazie!
giles

13

boost 1.46.0 e versioni successive include la libreria Chrono :

La classe thread_clock fornisce l'accesso al wall-clock del thread reale, cioè l'orologio del tempo reale della CPU del thread chiamante. L'ora corrente relativa del thread può essere ottenuta chiamando thread_clock :: now ()

#include <boost/chrono/thread_clock.hpp>
{
...
    using namespace boost::chrono;
    thread_clock::time_point start = thread_clock::now();
    ...
    thread_clock::time_point stop = thread_clock::now();  
    std::cout << "duration: " << duration_cast<milliseconds>(stop - start).count() << " ms\n";

7
Inoltre, C ++ 11 ha uno std::chronospazio dei nomi con quasi gli stessi contenuti.
ulidtko

12

In Windows: usa GetTickCount

//GetTickCount defintition
#include <windows.h>
int main()
{

    DWORD dw1 = GetTickCount();

    //Do something 

    DWORD dw2 = GetTickCount();

    cout<<"Time difference is "<<(dw2-dw1)<<" milliSeconds"<<endl;

}

8

Puoi anche usare clock_gettime . Questo metodo può essere utilizzato per misurare:

  1. Orologio in tempo reale a livello di sistema
  2. Orologio monotono dell'intero sistema
  3. Tempo CPU per processo
  4. Per processo Tempo CPU thread

Il codice è il seguente:

#include < time.h >
#include <iostream>
int main(){
  timespec ts_beg, ts_end;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts_beg);
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts_end);
  std::cout << (ts_end.tv_sec - ts_beg.tv_sec) + (ts_end.tv_nsec - ts_beg.tv_nsec) / 1e9 << " sec";
}

"


6

nel caso in cui tu sia su Unix, puoi usare timeper ottenere il tempo di esecuzione:

$ g++ myprog.cpp -o myprog
$ time ./myprog

5

Solo una nota a margine: se stai utilizzando Windows e hai davvero bisogno di precisione, puoi usare QueryPerformanceCounter . Ti dà tempo in (potenzialmente) nano secondi.


5

Per me, il modo più semplice è:

#include <boost/timer.hpp>

boost::timer t;
double duration;

t.restart();
/* DO SOMETHING HERE... */
duration = t.elapsed();

t.restart();
/* DO OTHER STUFF HERE... */
duration = t.elapsed();

usando questo pezzo di codice non devi fare il classico end - start.

Goditi il ​​tuo approccio preferito.


è t.elapsed () in sec o mili-sec?
mkuse

4

Ottieni l'ora di sistema in millisecondi all'inizio e di nuovo alla fine e sottrai.

Per ottenere il numero di millisecondi dal 1970 in POSIX dovresti scrivere:

struct timeval tv;

gettimeofday(&tv, NULL);
return ((((unsigned long long)tv.tv_sec) * 1000) +
        (((unsigned long long)tv.tv_usec) / 1000));

Per ottenere il numero di millisecondi dal 1601 su Windows dovresti scrivere:

SYSTEMTIME systime;
FILETIME filetime;

GetSystemTime(&systime);
if (!SystemTimeToFileTime(&systime, &filetime))
    return 0;

unsigned long long ns_since_1601;
ULARGE_INTEGER* ptr = (ULARGE_INTEGER*)&ns_since_1601;

// copy the result into the ULARGE_INTEGER; this is actually
// copying the result into the ns_since_1601 unsigned long long.
ptr->u.LowPart = filetime.dwLowDateTime;
ptr->u.HighPart = filetime.dwHighDateTime;

// Compute the number of milliseconds since 1601; we have to
// divide by 10,000, since the current value is the number of 100ns
// intervals since 1601, not ms.
return (ns_since_1601 / 10000);

Se ti interessava normalizzare la risposta di Windows in modo che restituisse anche il numero di millisecondi dal 1970, dovresti regolare la tua risposta di 11644473600000 millisecondi. Ma non è necessario se tutto ciò che ti interessa è il tempo trascorso.


4

Se stai usando:

tstart = clock();

// ...do something...

tend = clock();

Quindi avrai bisogno di quanto segue per ottenere il tempo in secondi:

time = (tend - tstart) / (double) CLOCKS_PER_SEC;

0

Questo sembra funzionare bene per Intel Mac 10.7:

#include <time.h>

time_t start = time(NULL);


    //Do your work


time_t end = time(NULL);
std::cout<<"Execution Time: "<< (double)(end-start)<<" Seconds"<<std::endl;
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.