Meça facilmente o tempo decorrido

297

Estou tentando usar time () para medir vários pontos do meu programa.

O que não entendo é por que os valores no antes e depois são os mesmos? Entendo que essa não é a melhor maneira de criar um perfil do meu programa, só quero ver quanto tempo leva para algo.

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

doSomthing();
doSomthingLong();

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

Eu tentei:

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

Como leio um resultado **time taken = 0 26339? Isso significa 26.339 nanossegundos = 26,3 ms?

Que tal **time taken = 4 45025, isso significa 4 segundos e 25 ms?

hap497
fonte
10
Eu não entendo a pergunta. Claro que os valores são diferentes. O tempo passou, portanto, time()retorna um valor diferente.
Thomas
1
O que você quer dizer com "Não entendo é por que os valores no antes e depois são diferentes"? Você está recebendo o horário atual (em segundos desde 1º de janeiro de 1970) usando time(NULL)... a segunda vez que você ligar será N segundos após o primeiro e, portanto, ... diferente (a menos que seja o que você estiver fazendo, não ' demore um segundo para concluir ... nesse caso, será o mesmo que o primeiro).
Brian Roach
1
Você pode nos dizer o que é impresso e quanto tempo leva se você cronometrar com um cronômetro ou relógio de parede (ou calendário)?
Matt Curtis
4
Desculpe, quero dizer que ambos os valores são os mesmos. Eu digito mal minha pergunta.
Hap497 11/11/10
2
Veja este tópico: stackoverflow.com/questions/275004/…
Padrão

Respostas:

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;
user3762106
fonte
10
sim, esta deve ser a resposta #
Ferenc Dajka 25/10
23
Para executar este você tem que adicionar a #include <chrono>directiva e gostaria de alterar o tempo de divulgação que: std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;(e não se esqueça do C ++ 11 flag quando compilar: -std=c++11)
Antonello
1
A propósito, isso mede o tempo da CPU, não o tempo do relógio de parede. Certo?
Nikos
4
@ RestlessC0bra De acordo com os documentos da cppreference, "Este relógio não está relacionado à hora do relógio de parede (por exemplo, pode ser o tempo desde a última reinicialização) e é mais adequado para medir intervalos."
cylus
1
Que tipo de dados é este std :: crono :: duration_cast <std :: crono :: microssegundos> (fim - começar)? .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;
}

A time()função é precisa apenas dentro de um segundo, mas há CLOCKS_PER_SEC"relógios" dentro de um segundo. Essa é uma medição fácil e portátil, apesar de simplificada demais.


fonte
129
Esteja ciente de que clock()mede o tempo da CPU, não o tempo real decorrido (que pode ser muito maior).
jlstrecker
12
Ao programar código paralelo para clusters, este método não reflete o tempo do mundo real ...
Nicholas Hamilton
3
Este parece ser o mais fácil dos caminhos. Gostaria de atualizar ou abordar o comentário feito em @jlstrecker?
Lorah Attkins
5
A solução postada acima não é uma boa solução por vários motivos. Esta é a resposta correta - stackoverflow.com/questions/2962785/…
Xofo 25/16/19
1
Tentei esta solução e, como sugeriram os comentários, meu cronômetro correu muito mais rápido que o tempo do mundo real.
RTbecard
267

Você pode abstrair o mecanismo de medição de tempo e medir o tempo de execução de cada chamada com um código extra mínimo , apenas sendo chamado por uma estrutura de timer. Além disso, em tempo de compilação, você pode parametrizar o tipo de tempo (milissegundos, nanossegundos etc.).

Graças à revisão de Loki Astari e à sugestão de usar modelos variados. Este é por isso que a chamada de função encaminhados.

#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

De acordo com o comentário de Howard Hinnant , é melhor não fugir do sistema de cronômetros até que seja necessário. Portanto, a classe acima pode dar ao usuário a opção de chamar countmanualmente, fornecendo um método estático extra (mostrado em 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;

e ser mais útil para clientes que

"deseja pós-processar várias durações antes da E / S (por exemplo, média)"


O código completo pode ser encontrado aqui . Minha tentativa de criar uma ferramenta de benchmarking baseada no cronógrafo é registrada aqui .


Se C ++ 17 std::invokeestiver disponível, a chamada do callable in executionpode ser feita assim:

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

para fornecer callables que são ponteiros para funções de membro.

Nikos Athanasiou
fonte
2
Agradável; Eu tenho algo semelhante no meu código, mas uso uma interface diferente para a classe: eu tenho uma classe ( code_timer) que leva a hora de início ( std::chrono::system_clock::now();) no construtor, um método code_timer::ellapsedque mede a diferença entre uma nova now()chamada e a do construtor e um code_timer::resetmétodo que redefine a hora de início para um novo now()resultado. Para medir a execução de um functor no meu código, eu uso uma função livre, fora da classe. Isso permite medir o tempo desde a construção de um objeto até o final de uma chamada assíncrona.
Utnapistim
7
<nitpick>: Não saia do chronosistema até precisar (evite usar .count()). Deixe o cliente ligar .count()quando for forçado (digamos, para E / S, o que é realmente lamentável). O cliente pode querer pós-processar várias durações antes da E / S (por exemplo, média) e isso é melhor realizado dentro do chronosistema.
Howard Hinnant
1
@ user3241228 1. O VS2013 não suporta tipos de retorno automático (apenas tipos de retorno à direita - é um recurso do c ++ 14 ainda não disponível). 2. Eu acredito que esta é a razão mas eu pedi aq só para ter certeza
Nikos Athanasiou
2
Por que não std::forward<F>(func)?
oliora 15/02
3
@oliora É a mesma coisa. Eu prefiro std::forward<decltype(func)>(func)porque ele pode se aplicar a argumentos de lambdas genéricas ( auto&& func) onde Fnão há sintaticamente lá e é fácil abstrair em uma macro de utilitário #define fw(arg) std::forward<decltype(arg)>(arg)que eu faço na minha biblioteca de benchmark (por isso, é uma sobra sintática sobre a qual eu não elaboro muito em a resposta)
Nikos Athanasiou
56

Como posso ver na sua pergunta, parece que você deseja saber o tempo decorrido após a execução de algum trecho de código. Eu acho que você ficaria confortável em ver os resultados em segundos. Nesse caso, tente usar a difftime()função como mostrado abaixo. Espero que isso resolva seu 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 );
Akanthan
fonte
4
Isso sempre me dá segundos inteiros. Isso deveria acontecer?
nitrato de sódio 15/09/14
10
o tempo sempre retornará apenas segundos, portanto, não pode ser usado para medições de segundo segundo.
DeepDeadpool
31

Apenas Windows: (a tag Linux foi adicionada após eu postar esta resposta)

Você pode usar GetTickCount () para obter o número de milissegundos decorridos desde que o sistema foi iniciado.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();
RvdK
fonte
7
Eu estou usando no linux. Portanto, não posso usar a função GetTickCount ().
115910 hap497
1
já não importa;) Obrigado por atualizar a tag da sua postagem
RvdK
Funciona e fornece o tempo real, não o tempo da CPU. Eu testei colocando SleepEx(5000,0)no lugar de // Executar operação demorada e diferença de aftere beforeera menos 5 seg.
Ruchir
14

time(NULL)retorna o número de segundos decorridos desde 01/01/1970 às 00:00 ( a época ). Portanto, a diferença entre os dois valores é o número de segundos que seu processamento levou.

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

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

Você pode obter resultados mais refinados com getttimeofday(), que retornam o tempo atual em segundos, assim como time()também em microssegundos.

filante
fonte
13

a função time (NULL) retornará o número de segundos decorridos desde 01/01/1970 às 00:00. E como essa função é chamada em um horário diferente do seu programa, sempre será diferente. Tempo em C ++

vodkhang
fonte
Não sei por que alguém votou mal, mas sua resposta não está totalmente correta. Para iniciantes, ele não retorna a data e nem sempre será diferente.
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)

O uso está abaixo:

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

Isso é semelhante ao RAII no escopo

NOTA: este não é meu, mas achei que era relevante aqui


fonte
1
inclui falta
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 
Eskay
fonte
3
Embora sua resposta seja apreciada, preferimos um preâmbulo contendo uma breve descrição do código. Obrigado.
Kev
2
Este não é o tempo decorrido, mas o tempo do processador.
JonnyJD
8

Os valores impressos pelo seu segundo programa são segundos e microssegundos.

0 26339 = 0.026'339 s =   26339 µs
4 45025 = 4.045'025 s = 4045025 µs
Didier Trosset
fonte
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;
}
Akanksha Gupta
fonte
4

O C ++ std :: chrono tem um claro benefício de ser multiplataforma. No entanto, também introduz uma sobrecarga significativa em comparação com o POSIX clock_gettime (). Na minha caixa Linux, todos os std::chrono::xxx_clock::now()sabores têm o mesmo desempenho:

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

Embora o POSIX clock_gettime(CLOCK_MONOTONIC, &time)deva ser o mesmo, steady_clock::now()mas é mais do que x3 vezes mais rápido!

Aqui está o meu teste, para ser completo.

#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 esta é a saída que recebo quando compilada com 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
Alexey Polonsky
fonte
3

A time(NULL)chamada de função retornará o número de segundos decorridos desde o epoc: 1º de janeiro de 1970. Talvez o que você queira fazer seja a diferença entre dois registros de data e hora:

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

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

Como outros já observaram, a função time () na biblioteca padrão C não possui uma resolução melhor que um segundo. A única função C totalmente portátil que pode fornecer uma melhor resolução parece ser clock (), mas que mede o tempo do processador em vez do tempo do relógio de parede. Se alguém se contentar em se limitar às plataformas POSIX (por exemplo, Linux), a função clock_gettime () é uma boa opção.

Desde o C ++ 11, existem recursos de tempo muito melhores disponíveis que oferecem melhor resolução, de uma forma que deve ser muito portátil em diferentes compiladores e sistemas operacionais. Da mesma forma, a biblioteca boost :: datetime fornece boas classes de tempo de alta resolução que devem ser altamente portáteis.

Um desafio ao usar qualquer um desses recursos é o atraso introduzido consultando o relógio do sistema. Ao experimentar clock_gettime (), boost :: datetime e std :: chrono, esse atraso pode ser facilmente uma questão de microssegundos. Portanto, ao medir a duração de qualquer parte do seu código, é necessário permitir que exista um erro de medição desse tamanho ou tente corrigir o erro zero de alguma forma. Idealmente, convém reunir várias medidas do tempo gasto por sua função e calcular o tempo médio ou máximo / mínimo gasto em várias execuções.

Para ajudar com todos esses problemas de portabilidade e coleta de estatísticas, desenvolvo a biblioteca cxx-rtimers disponível no Github, que tenta fornecer uma API simples para sincronizar blocos de código C ++, calcular erros zero e reportar estatísticas de vários timers incorporados no seu código. Se você possui um compilador C ++ 11, basta #include <rtimers/cxx11.hpp>usar algo como:

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

Na saída do programa, você obterá um resumo das estatísticas de tempo gravadas em std :: cerr, como:

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

que mostra o tempo médio, seu desvio padrão, os limites superior e inferior e o número de vezes que essa função foi chamada.

Se você quiser usar funções de tempo específicas do Linux, poderá #include <rtimers/posix.hpp>, ou se tiver as bibliotecas Boost, mas um compilador C ++ mais antigo, poderá #include <rtimers/boost.hpp>. Existem também versões dessas classes de timer que podem coletar informações de tempo estatístico de vários threads. Também existem métodos que permitem estimar o erro zero associado a duas consultas imediatamente consecutivas do relógio do sistema.

rwp
fonte
2

Internamente, a função acessa o relógio do sistema, e é por isso que retorna valores diferentes a cada vez que você o chama. Em geral, com linguagens não funcionais, pode haver muitos efeitos colaterais e estados ocultos em funções que você não pode ver apenas observando o nome e os argumentos da função.

Mike Weller
fonte
2

Pelo que se vê, tv_sec armazena os segundos decorridos enquanto tv_usec armazenou os microssegundos decorridos separadamente. E eles não são as conversões um do outro. Portanto, eles devem ser alterados para a unidade adequada e adicionados para obter o tempo total decorrido.

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))
    );
Safar Ligal
fonte
2

No linux, clock_gettime () é uma das boas escolhas. Você deve vincular a biblioteca em tempo real (-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 );
  }
cloudrain21
fonte
2

Eu precisava medir o tempo de execução de funções individuais em uma biblioteca. Eu não queria ter que agrupar todas as chamadas de todas as funções com uma função de medição de tempo, porque é feio e aprofunda a pilha de chamadas. Eu também não queria colocar o código do timer nas partes superior e inferior de todas as funções, porque isso causa confusão quando a função pode sair mais cedo ou gerar exceções, por exemplo. Então, o que acabei fazendo foi criar um cronômetro que usasse sua própria vida útil para medir o tempo.

Dessa maneira, posso medir o tempo de parede que um bloco de código levou, instanciando um desses objetos no início do bloco de código em questão (função ou qualquer escopo realmente) e, em seguida, permitindo que o destruidor de instâncias medisse o tempo decorrido desde construção quando a instância sai do escopo. Você pode encontrar o exemplo completo aqui, mas a estrutura é extremamente simples:

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

O struct chamará você de volta ao functor fornecido quando estiver fora do escopo, para que você possa fazer algo com as informações de tempo (imprimi-lo ou armazená-lo ou o que for). Se você precisar fazer algo ainda mais complexo, poderá usar std::bindcomstd::placeholders funções de callback com mais argumentos.

Aqui está um exemplo rápido de como usá-lo:

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 você quiser ser mais deliberado, também pode usar newe deletepara iniciar e parar explicitamente o cronômetro sem depender do escopo para fazer isso por você.

Kevin Kreiser
fonte
1

Eles são os mesmos porque a função doSomething acontece mais rápido que a granularidade do timer. Experimentar:

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

for(i = 0; i < 1000; ++i) {
    doSomthing();
    doSomthingLong();
}

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

A razão pela qual os dois valores são os mesmos é porque seu longo procedimento não leva muito tempo - menos de um segundo. Você pode tentar apenas adicionar um loop longo (para (int i = 0; i <100000000; i ++);) no final da função para garantir que esse seja o problema, então podemos prosseguir a partir daí ...

Caso o exposto acima seja verdadeiro, você precisará encontrar uma função de sistema diferente (eu entendo que você trabalha no Linux, por isso não posso ajudá-lo com o nome da função) para medir o tempo com mais precisão. Estou certo de que existe uma função semelhante ao GetTickCount () no linux, você só precisa encontrá-la.

David Božjak
fonte
1

Eu costumo usar o seguinte:

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

É o mesmo que o @ nikos-athanasiou propôs, exceto que evito o uso de um relógio não estável e uso um número flutuante de segundos como duração.

oliora
fonte
1
Neste comutador de tipos : Normalmente high_resolution_clocké um typedef para um system_clockou outro steady_clock. Portanto, para rastrear que, std::conditionalse a is_steadypeça for verdadeira, você escolhe o high_resolution_clockque é (um typedef para) o steady_clock. Se for falso, você escolhe steady_clocknovamente. Basta usar steady_clockdesde o início ...
Nikos Athanasiou
@ nikos-athanasiou Concordo plenamente com o comentário do 5gon12eder de que o caso "típico" não é exigido pelo padrão, portanto alguns STL podem ser implementados de uma maneira diferente. Prefiro que meu código seja mais genérico e não relacionado aos detalhes da implementação.
oliora 28/02
Não é necessário, mas explicitamente afirmado no 20.12.7.3 : high_resolution_clock may be a synonym for system_clock or steady_clock. A razão é a seguinte: high_resolution_clockrepresenta os relógios com o menor período de tick, portanto, seja qual for a implementação, ela tem duas opções, seja estável ou não. Qualquer que seja a escolha que fizermos, dizer que a implementação será diferente dos outros dois relógios é como dizer que temos uma implementação melhor para um relógio fixo (ou não) que escolhemos não usar (para relógios fixos ou não). Sabendo como é bom, saber por que é melhor
Nikos Athanasiou
@ nikos-athanasiou Eu preferiria ser 100% seguro, especialmente quando isso me custou nenhuma sobrecarga de tempo de execução e sobrecarga de tempo de compilação indetectável. Você pode confiar em "may" e suposições, se quiser.
oliora 29/02
au contraire meu amigo, é você quem confia no "maio", mas combina com você. Se você deseja ter 100% de certeza e continuar escrevendo isso, também deve encontrar uma maneira, para você e os usuários do seu código, de evitar misturas não portáteis de pontos de tempo de relógios diferentes (se esse tipo de switch adquirir um significado, ele se comportará de maneira diferente em plataformas diferentes). Diverta-se!
Nikos Athanasiou
0

Em resposta às três perguntas específicas do OP .

"O que eu não entendo é por que os valores no antes e depois são os mesmos? "

A primeira pergunta e o código de exemplo mostram que time()tem uma resolução de 1 segundo, portanto, a resposta deve ser que as duas funções sejam executadas em menos de 1 segundo. Mas, ocasionalmente, (aparentemente ilogicamente) informa 1 segundo se as duas marcas do cronômetro ultrapassarem o limite de um segundo.

O próximo exemplo usa o gettimeofday()que preenche essa estrutura

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

e a segunda pergunta: "Como leio um resultado **time taken = 0 26339? Isso significa 26.339 nanossegundos = 26,3 ms?"

Minha segunda resposta é que o tempo gasto é de 0 segundos e 26339 microssegundos, ou seja, 0,026339 segundos, o que mostra o primeiro exemplo sendo executado em menos de 1 segundo.

A terceira pergunta: "Que tal **time taken = 4 45025, isso significa 4 segundos e 25 ms?"

Minha terceira resposta é que o tempo gasto é de 4 segundos e 45025 microssegundos, ou seja, 4,045025 segundos, o que mostra que o OP alterou as tarefas executadas pelas duas funções que ele cronometrou anteriormente.

Cata-vento
fonte
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));

}

Exemplo semelhante ao disponível aqui, apenas com a função de conversão adicional + impressão.

TarmoPikaro
fonte
0

Criei uma classe para medir automaticamente o tempo decorrido. Verifique o código (c ++ 11) neste link: https://github.com/sonnt174/Common/blob/master/time_measure.h

Exemplo de como usar a 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));
}
Sirn Nguyen Truong
fonte
Gosto da sua declaração impressa com as unidades. O que seria necessário para portar seu código para o gcc e o clang? ( wandbox.org )
Howard Hinnant
1
@ HowardHinnant: obrigado pelo endereço, atualizei o código para o gcc e o clang também.
Sirn Nguyen Truong 20/01
0

Matlab com sabor!

ticinicia um cronômetro para medir o desempenho. A função registra o tempo interno na execução do comando tic. Exiba o tempo decorrido com a tocfunção

#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;
}
Yas
fonte
-4

Você pode usar a biblioteca SFML , que é a Biblioteca multimídia simples e rápida. Inclui muitas classes úteis e bem definidas, como Relógio, Soquete, Som, Gráficos, etc. É muito fácil de usar e altamente recomendado.

Este é um exemplo para esta pergunta.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
cloudrain21
fonte