Como calcular a diferença de tempo em C ++

94

Qual é a melhor maneira de calcular a diferença de tempo em C ++? Estou cronometrando a velocidade de execução de um programa, então estou interessado em milissegundos. Melhor ainda, segundos.milissegundos ..

A resposta aceita funciona, mas precisa incluir ctime ou time.h conforme observado nos comentários.

Jack BeNimble
fonte
Dupe, mas não consigo vincular agora
Robert Gould,
2
A votação para fechar foi muito pequena, muito tarde. Eu tenho uma resposta que funciona. Boa tentativa. Aliás, também não consegui encontrar um link.
Jack BeNimble,
É para windows? em seguida, tente GetTickCount (API do Windows)
aJ.
5
Robert: Felizmente, porque a nova postagem permitiu várias outras respostas, uma das quais eu selecionei. Sério, eu questiono o valor de fechar um post duplicado. E se algumas soluções não foram mencionadas na primeira? Novas tecnologias desenvolvidas? Não consegue encontrar por causa de títulos diferentes?
Jack BeNimble,
2
@JackBeNimble tendo recebido alguns "dups" que não eram exatamente dups (talvez pessoas que talvez leiam rapidamente a pergunta e a marquem porque soa semelhante a outra pergunta), concordo totalmente com seu ponto ... provavelmente um ponto para troca de pilha meta: o
code_fodder

Respostas:

122

Veja a std::clock()função.

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

Se você quiser calcular o tempo de execução para si mesmo (não para o usuário), é melhor fazer isso em tiques do relógio (não em segundos).

EDITAR:
arquivos de cabeçalho responsáveis ​​- <ctime>ou<time.h>

Bayda
fonte
4
Lembre-se de que, embora clock () retorne um número de milissegundos, a precisão de clock () pode ser muito pior do que isso. Por exemplo, no Windows, a precisão da função clock () é algo como 40 ms.
John Dibling,
2
Tentei fazer isso no Mac 10.7. meu aplicativo executa um arquivo de 100 MB em 15 segundos, mas o tempo de comparação está relatando 61 segundos. Não adianta muito. Acho que o tempo () é provavelmente melhor.
Miek
5
clock()retorna o tempo de CPU consumido pelo programa. Portanto, se o programa for executado em paralelo, o tempo retornado pela função seria o acumulado do tempo gasto em todas as CPUs, ao invés do tempo decorrido cplusplus.com/reference/ctime/clock
Ameer Jewdaki
3
Essa resposta é enganosa porque mostra o tempo da CPU, não o tempo real do relógio de parede.
Ultravioleta
1
Eu tenho que concordar com o Ultraviolet aqui, usar o tempo da CPU para medir a velocidade de um programa parece a coisa errada a se fazer. OP deve desmarcar esta como a resposta certa. IMO, você deve usar std :: chrono :: stable_clock :: now () conforme descrito por várias respostas no seguinte tópico stackoverflow.com/questions/2808398/easily-measure-elapsed-time
arunsun
37

se você estiver usando c ++ 11, aqui está um invólucro simples (veja esta essência ):

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

Ou para c ++ 03 em * 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_;
};

Exemplo de uso:

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
fonte
2
Outra opção seria usar boost :: chrono em vez do namespace C ++ 11 STL std :: chrono. Obrigado pelo seu código.
Didac Perez Parera
Cuidado: Isso não funcionará se o usuário alterar seu tempo entre Timer()e a chamada para elapsed()if !std::chrono::high_resolution_clock::is_steady- que é o caso no Linux!
jhasse de
30

Eu consideraria seriamente o uso de Boost, particularmente boost :: posix_time :: ptime e boost :: posix_time :: time_duration (em http://www.boost.org/doc/libs/1_38_0/doc/html/date_time/posix_time .html ).

É multiplataforma, fácil de usar e, na minha experiência, oferece o mais alto nível de resolução de tempo que um sistema operacional oferece. Possivelmente também muito importante; ele fornece alguns operadores IO muito bons.

Para usá-lo para calcular a diferença na execução do programa (em microssegundos; provavelmente um exagero), seria algo como [navegador escrito, não testado]:

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
fonte
3
Mas boost local_time () não é monotônico, então não deve ser usado para medir lapsos de tempo. Não encontrei uma maneira de acessar o tempo monotônico de Boost.
gatopeich de
26

Eu adicionei esta resposta para esclarecer que a resposta aceita mostra o tempo de CPU, que pode não ser o tempo que você deseja. Porque de acordo com a referência , existem o tempo da CPU e o tempo do relógio de parede . O tempo do relógio de parede é o tempo que mostra o tempo real decorrido independentemente de quaisquer outras condições como CPU compartilhada por outros processos. Por exemplo, usei vários processadores para fazer uma determinada tarefa e o tempo de CPU era alto em 18s, onde na verdade demorava 2s no tempo real do relógio de parede.

Para saber o tempo real que você faz,

#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();
Ultravioleta
fonte
2
Eu não seria capaz de usar std :: chrono sem esta resposta, obrigado!
giles
13

boost 1.46.0 e superior inclui a biblioteca Chrono :

A classe thread_clock fornece acesso ao relógio de parede do thread real, ou seja, o relógio de tempo real da CPU do thread de chamada. O tempo atual relativo da thread pode ser obtido chamando 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
fonte
7
Além disso, C ++ 11 possui std::chrononamespace com quase o mesmo conteúdo.
ulidtko
12

No Windows: use 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.
fonte
8

Você também pode usar o clock_gettime . Este método pode ser usado para medir:

  1. Relógio em tempo real de todo o sistema
  2. Relógio monotônico amplo do sistema
  3. Tempo de CPU por processo
  4. Tempo de CPU por thread de processo

O código é o seguinte:

#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
fonte
6

apenas no caso de você estar no Unix, você pode usar timepara obter o tempo de execução:

$ g++ myprog.cpp -o myprog
$ time ./myprog
Fengshaun
fonte
5

Apenas uma observação: se você está executando no Windows e realmente precisa de precisão, pode usar QueryPerformanceCounter . Dá-lhe tempo em (potencialmente) nano segundos.

v3.
fonte
5

Para mim, a maneira mais fácil é:

#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 este código, você não precisa fazer o clássico end - start.

Aproveite sua abordagem favorita.

user1823890
fonte
é t.elapsed () em seg ou mili-sec?
mkuse
4

Obtenha o tempo do sistema em milissegundos no início e novamente no final e subtraia.

Para obter o número de milissegundos desde 1970 em POSIX, você escreveria:

struct timeval tv;

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

Para obter o número de milissegundos desde 1601 no Windows, você escreveria:

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 você quisesse normalizar a resposta do Windows para que ela também retornasse o número de milissegundos desde 1970, você teria que ajustar sua resposta em 11644473600000 milissegundos. Mas isso não é necessário se você só se preocupa com o tempo decorrido.

Jared Oberhaus
fonte
4

Se você estiver usando:

tstart = clock();

// ...do something...

tend = clock();

Em seguida, você precisará do seguinte para obter o tempo em segundos:

time = (tend - tstart) / (double) CLOCKS_PER_SEC;
Robert White
fonte
0

Isso parece funcionar bem para 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
fonte