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?
time()
retorna um valor diferente.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).Respostas:
fonte
#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
)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
clock()
mede o tempo da CPU, não o tempo real decorrido (que pode ser muito maior).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.
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
count
manualmente, fornecendo um método estático extra (mostrado em C ++ 14)e ser mais útil para clientes que
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::invoke
estiver disponível, a chamada do callable inexecution
pode ser feita assim:para fornecer callables que são ponteiros para funções de membro.
fonte
code_timer
) que leva a hora de início (std::chrono::system_clock::now();
) no construtor, um métodocode_timer::ellapsed
que mede a diferença entre uma novanow()
chamada e a do construtor e umcode_timer::reset
método que redefine a hora de início para um novonow()
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.chrono
sistema 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 dochrono
sistema.std::forward<F>(func)
?std::forward<decltype(func)>(func)
porque ele pode se aplicar a argumentos de lambdas genéricas (auto&& func
) ondeF
nã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)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.fonte
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.
fonte
SleepEx(5000,0)
no lugar de // Executar operação demorada e diferença deafter
ebefore
era menos 5 seg.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.Você pode obter resultados mais refinados com
getttimeofday()
, que retornam o tempo atual em segundos, assim comotime()
também em microssegundos.fonte
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 ++
fonte
O uso está abaixo:
Isso é semelhante ao RAII no escopo
NOTA: este não é meu, mas achei que era relevante aqui
fonte
fonte
Os valores impressos pelo seu segundo programa são segundos e microssegundos.
fonte
fonte
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: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.
E esta é a saída que recebo quando compilada com gcc7.2 -O3:
fonte
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:fonte
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:Na saída do programa, você obterá um resumo das estatísticas de tempo gravadas em std :: cerr, como:
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.fonte
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.
fonte
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.
fonte
No linux, clock_gettime () é uma das boas escolhas. Você deve vincular a biblioteca em tempo real (-lrt).
fonte
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:
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::bind
comstd::placeholders
funções de callback com mais argumentos.Aqui está um exemplo rápido de como usá-lo:
Se você quiser ser mais deliberado, também pode usar
new
edelete
para iniciar e parar explicitamente o cronômetro sem depender do escopo para fazer isso por você.fonte
Eles são os mesmos porque a função doSomething acontece mais rápido que a granularidade do timer. Experimentar:
fonte
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.
fonte
Eu costumo usar o seguinte:
É 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.
fonte
high_resolution_clock
é um typedef para umsystem_clock
ou outrosteady_clock
. Portanto, para rastrear que,std::conditional
se ais_steady
peça for verdadeira, você escolhe ohigh_resolution_clock
que é (um typedef para) osteady_clock
. Se for falso, você escolhesteady_clock
novamente. Basta usarsteady_clock
desde o início ...high_resolution_clock may be a synonym for system_clock or steady_clock
. A razão é a seguinte:high_resolution_clock
representa 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 é melhorEm 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 estruturae 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.
fonte
Exemplo semelhante ao disponível aqui, apenas com a função de conversão adicional + impressão.
fonte
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:
fonte
Matlab
com sabor!tic
inicia 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 atoc
funçãofonte
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.
fonte