Jak obliczyć różnicę czasu w C ++

96

Jaki jest najlepszy sposób obliczenia różnicy czasu w C ++? Odliczam czas wykonywania programu, więc interesują mnie milisekundy. Jeszcze lepiej, sekundy. Milisekundy ...

Zaakceptowana odpowiedź działa, ale musi zawierać ctime lub time.h, jak zaznaczono w komentarzach.

Jack BeNimble
źródło
Dupe, ale nie można teraz połączyć
Robert Gould
2
Głosowanie za zamknięciem było za mało i za późno. Mam działającą odpowiedź. Niezła próba. Przy okazji, nie mogłem też znaleźć linku.
Jack BeNimble
Służy do okien? następnie wypróbuj GetTickCount (Windows API)
aJ.
5
Robert: Na szczęście, ponieważ nowy wpis pozwolił na kilka dodatkowych odpowiedzi, z których jedną wybrałem. Poważnie, kwestionuję wartość zamknięcia postu dup. A co by było, gdyby niektóre rozwiązania nie zostały wymienione w pierwszym? Opracowano nowe technologie? Nie możesz go znaleźć z powodu różnych nagłówków?
Jack BeNimble
2
@JackBeNimble był odbiorcą kilku „dupków”, które nie były dokładnie frajerami (być może ludzie, którzy być może szybko przeczytali pytanie i zaznaczyli je, ponieważ brzmi podobnie do innego pytania), zdecydowanie zgadzam się z twoim punktem ... prawdopodobnie punkt do wymiany meta stosu: o
code_fodder

Odpowiedzi:

124

Zobacz std::clock()funkcję.

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

Jeśli chcesz obliczyć czas wykonania dla siebie (nie dla użytkownika), lepiej zrobić to w taktach zegara (a nie sekundach).

EDYCJA:
odpowiedzialne pliki nagłówkowe - <ctime>lub<time.h>

bayda
źródło
4
Należy pamiętać, że chociaż funkcja clock () zwraca liczbę milisekund, precyzja metody clock () może być znacznie gorsza. Instancja firmy Windows w systemie Windows precyzja działania funkcji clock () wynosi około 40 ms.
John Dibling
2
Wypróbowałem to na Macu 10.7. Moja aplikacja wykonuje plik 100 MB w 15 sekund, ale czas porównania wynosi 61 sekund. Niewiele przydatne. Myślę, że czas () jest prawdopodobnie lepszy.
Miek
6
clock()zwraca czas procesora zużyty przez program. Więc jeśli program jest uruchamiany równolegle, czas zwracany przez funkcję byłby
sumą
3
Ta odpowiedź jest myląca, ponieważ pokazuje czas procesora, a nie rzeczywisty czas zegara ściennego.
Ultrafiolet
1
Muszę się zgodzić z Ultravioletem, używanie czasu procesora do pomiaru szybkości programu wydaje się być niewłaściwą rzeczą. OP powinien odznaczyć to jako właściwą odpowiedź. IMO powinieneś użyć std :: chrono :: steady_clock :: now () zgodnie z opisem w wielu odpowiedziach w następującym wątku stackoverflow.com/questions/2808398/easily-measure-elapsed-time
arunsun
37

jeśli używasz c ++ 11, oto prosty wrapper (zobacz ten opis ):

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

Lub dla c ++ 03 na * 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_;
};

Przykład użycia:

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;
}
gongzhitaao
źródło
2
Inną opcją byłoby użycie boost :: chrono zamiast przestrzeni nazw C ++ 11 STL std :: chrono. Dziękuję za Twój kod.
Didac Perez Parera
Ostrożnie: to nie zadziała, jeśli użytkownik zmieni swój czas między Timer()a wywołaniem elapsed()if !std::chrono::high_resolution_clock::is_steady- co ma miejsce w systemie Linux!
jhasse
30

Poważnie rozważyłbym użycie Boost, szczególnie boost :: posix_time :: ptime i boost :: posix_time :: time_duration (na http://www.boost.org/doc/libs/1_38_0/doc/html/date_time/posix_time .html ).

Jest wieloplatformowy, łatwy w użyciu i z mojego doświadczenia wynika, że ​​zapewnia najwyższy poziom rozdzielczości czasowej, jaki zapewnia system operacyjny. Być może również bardzo ważne; zapewnia kilka bardzo fajnych operatorów IO.

Aby użyć go do obliczenia różnicy w wykonywaniu programu (do mikrosekund; prawdopodobnie przesada), wyglądałoby to mniej więcej tak [napisana przeglądarka, nie testowana]:

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';
Jeremy CD
źródło
3
Ale funkcja boost local_time () nie jest monotoniczna, więc nie powinna być używana do mierzenia upływów czasu. Nie znalazłem sposobu na dostęp do monotonicznego czasu z Boost.
gatopeich
28

Dodałem tę odpowiedź, aby wyjaśnić, że zaakceptowana odpowiedź pokazuje czas procesora, który może nie być czasem, którego chcesz. Ponieważ zgodnie z odniesieniem istnieje czas procesora i zegar ścienny . Czas zegara ściennego to czas, który pokazuje rzeczywisty czas, który upłynął, niezależnie od innych warunków, takich jak procesor współdzielony przez inne procesy. Na przykład użyłem wielu procesorów do wykonania określonego zadania, a czas procesora wynosił 18 sekund, podczas gdy w rzeczywistości zajmował 2 sekundy .

Aby uzyskać faktyczny czas,

#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();
Ultrafioletowy
źródło
2
Nie byłbym w stanie użyć std :: chrono bez tej odpowiedzi, dzięki!
giles
13

boost 1.46.0 i nowsze zawierają bibliotekę Chrono :

Klasa thread_clock zapewnia dostęp do rzeczywistego zegara ściennego wątku, tj. rzeczywistego zegara czasu procesora wątku wywołującego. Względny aktualny czas wątku można uzyskać, wywołując funkcję 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";
Gabi Davar
źródło
7
Ponadto C ++ 11 ma std::chronoprzestrzeń nazw z prawie taką samą zawartością.
ulidtko
12

W systemie Windows: użyj GetTickCount

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

    DWORD dw1 = GetTickCount();

    //Do something 

    DWORD dw2 = GetTickCount();

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

}
aJ.
źródło
8

Możesz także użyć clock_gettime . Ta metoda może służyć do pomiaru:

  1. Systemowy zegar czasu rzeczywistego
  2. Systemowy zegar monotoniczny
  3. Czas procesora na proces
  4. Czas procesora na proces wątku

Kod jest następujący:

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

`

Richard
źródło
6

na wypadek gdybyś korzystał z Uniksa, możesz użyć, timeaby uzyskać czas wykonania:

$ g++ myprog.cpp -o myprog
$ time ./myprog
fengshaun
źródło
5

Na marginesie: jeśli pracujesz w systemie Windows i naprawdę potrzebujesz precyzji, możesz użyć QueryPerformanceCounter . Daje czas w (potencjalnie) nano sekundach.

v3.
źródło
5

Dla mnie najłatwiejszy sposób to:

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

używając tego fragmentu kodu, nie musisz robić klasycznej end - start.

Ciesz się ulubionym podejściem.

user1823890
źródło
czy t.elapsed () w sekundach czy mili-sec?
mkuse
4

Uzyskaj czas systemowy w milisekundach na początku i ponownie na końcu i odejmij.

Aby uzyskać liczbę milisekund od 1970 roku w POSIX, należy napisać:

struct timeval tv;

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

Aby uzyskać liczbę milisekund od 1601 w systemie Windows, napisz:

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

Gdybyś chciał znormalizować odpowiedź systemu Windows, tak aby zwracała również liczbę milisekund od 1970 r., Musiałbyś dostosować swoją odpowiedź o 11644473600000 milisekund. Ale nie jest to konieczne, jeśli zależy Ci tylko na czasie, który upłynął.

Jared Oberhaus
źródło
4

Jeśli używasz:

tstart = clock();

// ...do something...

tend = clock();

Następnie będziesz potrzebować następujących elementów, aby uzyskać czas w sekundach:

time = (tend - tstart) / (double) CLOCKS_PER_SEC;
Robert White
źródło
0

Wydaje się, że działa dobrze w przypadku komputera 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;
Miek
źródło