Eu tenho que calcular o tempo de execução de um trecho de código C ++ em segundos. Ele deve estar funcionando em máquinas Windows ou Unix.
Eu uso o código a seguir para fazer isso. (importar antes)
clock_t startTime = clock();
// some code here
// to compute its execution duration in runtime
cout << double( clock() - startTime ) / (double)CLOCKS_PER_SEC<< " seconds." << endl;
No entanto, para pequenas entradas ou instruções curtas como a = a + 1, recebo o resultado "0 segundos". Eu acho que deve ser algo como 0,0000001 segundos ou algo assim.
Lembro que System.nanoTime()
em Java funciona muito bem nesse caso. No entanto, não consigo obter a mesma funcionalidade exata da clock()
função do C ++.
Você tem uma solução?
c++
benchmarking
AhmetB - Google
fonte
fonte
Respostas:
Você pode usar esta função que escrevi. Você chama
GetTimeMs64()
e retorna o número de milissegundos decorridos desde a época do unix usando o relógio do sistema - exatamente comotime(NULL)
, exceto em milissegundos.Funciona em janelas e linux; é thread-safe.
Observe que a granularidade é de 15 ms no Windows; no linux, é dependente da implementação, mas geralmente 15 ms também.
fonte
gettimeofday
pode dar um resultado não intencional se o relógio do sistema for alterado. Se isso for um problema para você, você pode querer dar uma olhadaclock_gettime
.GetTickCount
?gcc -std=c99
GetTickCount
é o tempo decorrido desde que o sistema foi iniciado, enquanto minha função retorna o tempo desde a época do UNIX, o que significa que você pode usá-lo para datas e horas. Se você está interessado apenas no tempo decorrido entre dois eventos, a minha ainda é uma escolha melhor porque é uma int64; GetTickCount é um int32 e transborda a cada 50 dias, o que significa que você pode obter resultados estranhos se os dois eventos registrados estiverem entre o transbordamento.Eu tenho outro exemplo de trabalho que usa microssegundos (UNIX, POSIX, etc).
Aqui está o arquivo em que codificamos isso:
https://github.com/arhuaco/junkcode/blob/master/emqbit-bench/bench.c
fonte
#include <sys/time.h>
no início do seu exemplo.Aqui está uma solução simples no C ++ 11, que oferece uma resolução satisfatória.
Ou no * nix, para c ++ 03
Aqui está o exemplo de uso:
De https://gist.github.com/gongzhitaao/7062087
fonte
/usr/lib/x86_64-linux-gnu/libstdc++.so.6: version GLIBCXX_3.4.19 not found (required by ../cpu_2d/g500)
Quando
progress_timer
sair do escopo, imprimirá o tempo decorrido desde a sua criação.ATUALIZAÇÃO : Aqui está uma versão que funciona sem o Boost (testado no macOS / iOS):
fonte
O Windows fornece a função QueryPerformanceCounter () e o Unix possui gettimeofday (). Ambas as funções podem medir pelo menos 1 diferença de microssegundos.
fonte
#ifdef
deve estar ok (e é a julgar pela resposta que você aceita), e então eu não vejo o problema:#ifdef WIN32 #include <windows.h> ... #else ... #endif
.Em alguns programas que escrevi, usei o RDTS para esse fim. RDTSC não é sobre o tempo, mas sobre o número de ciclos desde o início do processador. Você precisa calibrá-lo em seu sistema para obter um resultado em segundo, mas é realmente útil quando você deseja avaliar o desempenho; é ainda melhor usar o número de ciclos diretamente, sem tentar alterá-los para segundos.
(o link acima é para uma página da Wikipedia, mas tem exemplos de código C ++, a versão em inglês está aqui )
fonte
Sugiro usar as funções da biblioteca padrão para obter informações de tempo do sistema.
Se você deseja uma resolução mais precisa, execute mais iterações de execução. Em vez de executar o programa uma vez e obter amostras, execute-o 1000 vezes ou mais.
fonte
É melhor executar o loop interno várias vezes com o tempo de desempenho apenas uma vez e média dividindo as repetições do loop interno do que executar a coisa toda (loop + tempo de desempenho) várias vezes e média. Isso reduzirá a sobrecarga do código de tempo do desempenho em relação à sua seção de perfil real.
Envolva as chamadas do timer para o sistema apropriado. Para o Windows, o QueryPerformanceCounter é bastante rápido e "seguro" de usar.
Você também pode usar "rdtsc" em qualquer PC X86 moderno, mas pode haver problemas em algumas máquinas com vários núcleos (o salto de núcleo pode alterar o timer) ou se você tiver algum tipo de velocidade ativada.
fonte
(solução específica para Windows) A maneira atual (por volta de 2017) de obter horários precisos no Windows é usar "QueryPerformanceCounter". Essa abordagem tem o benefício de fornecer resultados muito precisos e é recomendada pela EM. Basta inserir o blob de código em um novo aplicativo de console para obter uma amostra funcional. Há uma longa discussão aqui: Adquirindo carimbos de data / hora de alta resolução
fonte
Uma solução completa e infalível para o agendamento de threads, que deve render exatamente os mesmos tempos para cada teste, é compilar seu programa para ser independente do SO e inicializar o computador para executar o programa em um ambiente sem SO. No entanto, isso é praticamente impraticável e seria difícil na melhor das hipóteses.
Um bom substituto para deixar o sistema operacional livre é apenas definir a afinidade do encadeamento atual como 1 núcleo e a prioridade como mais alta. Essa alternativa deve fornecer resultados consistentes o suficiente.
Além disso, você deve desativar as otimizações que interferem na depuração, o que para g ++ ou gcc significa adicionar
-Og
à linha de comando , para impedir que o código que está sendo testado seja otimizado. O-O0
sinalizador não deve ser usado porque introduz uma sobrecarga extra desnecessária que seria incluída nos resultados de temporização, assim distorcendo a velocidade programada do código.Pelo contrário, ambos assumindo que você usa
-Ofast
(ou pelo menos-O3
) na construção da produção final e ignorando o problema da eliminação de código "inoperante",-Og
executam muito poucas otimizações em comparação com-Ofast
; portanto,-Og
pode deturpar a velocidade real do código no produto final.Além disso, todos os testes de velocidade (até certo ponto) perduram: no produto final de produção compilado
-Ofast
, cada trecho / seção / função do código não é isolado; em vez disso, cada trecho de código flui continuamente para o próximo, permitindo que o compilador se junte, mescle e otimize partes de código em potencial de todo o lugar.Ao mesmo tempo, se você estiver comparando um trecho de código que faz uso pesado
realloc()
, o trecho de código poderá ser executado mais lentamente em um produto de produção com fragmentação de memória alta o suficiente. Portanto, a expressão "o todo é mais do que a soma de suas partes" se aplica a essa situação porque o código na compilação de produção final pode ser notavelmente mais rápido ou mais lento que o snippet individual que você está testando com rapidez.Uma solução parcial que pode diminuir a incongruência está sendo usada
-Ofast
no teste de velocidade COM a adição deasm volatile("" :: "r"(var))
variáveis envolvidas no teste para evitar a eliminação do código morto / loop.Aqui está um exemplo de como comparar funções de raiz quadrada em um computador com Windows.
Além disso, agradeço a Mike Jarvis por seu Timer.
Observe (isso é muito importante) que, se você estiver executando trechos de código maiores, deverá reduzir o número de iterações para evitar que o computador congele.
fonte
-O0
código é um grande desperdício de tempo, porque a sobrecarga de-O0
em vez de um normal,-O2
ou-O3 -march=native
varia descontroladamente dependendo do código e a carga de trabalho. por exemplo, tmp vars com nomes extras custa tempo em-O0
. Existem outras maneiras de evitar que as coisas sejam otimizadas, como ocultar coisas do otimizador comvolatile
funções não embutidas ou instruções asm embutidas vazias.-O0
não está nem perto de ser utilizável porque o código tem gargalos diferentes-O0
, não o mesmo, mas pior.-Og
ainda não é muito realista, dependendo do código. Pelo menos-O2
, de preferência-O3
é mais realista. Useasm volatile("" ::: "+r"(var))
ou algo para fazer o compilador materializar um valor em um registro e impedir a propagação constante por meio dele.-O3
e o trecho de código comasm volatile("" ::: "+r"(var))
.asm volatile("" ::: "+r"( i ));
parece desnecessário. No código otimizado, não há razão para forçar o compilador a se materializari
, bem comoi<<7
dentro do loop. Você está impedindo a otimização para, emtmp -= 128
vez de mudar o tempo todo. Usar o resultado de uma chamada de função é bom, se não forvoid
. Likeint result = (*function_to_do)( i << 7 );
. Você pode usar umaasm
declaração sobre esse resultado.function_to_do
para quefunction_to_do
possam ser incorporadas sem serem eliminadas. Entre em contato se tiver mais sugestões.Para casos em que você deseja cronometrar o mesmo trecho de código toda vez que ele é executado (por exemplo, para criar um perfil de código que você acha que pode ser um gargalo), aqui está um invólucro (uma pequena modificação) da função de Andreas Bonini que eu acho útil:
fonte
apenas uma classe simples que compara o código de bloqueio:
fonte
O boost :: timer provavelmente fornecerá a precisão necessária. Não é suficientemente preciso para lhe dizer quanto tempo
a = a+1;
levará, mas eu que razão você teria para cronometrar algo que leva alguns nanossegundos?fonte
clock()
função do cabeçalho padrão C ++.Eu criei um lambda que chama a chamada de função N vezes e retorna a média.
Você pode encontrar o cabeçalho do c ++ 11 aqui .
fonte
Criei um utilitário simples para medir o desempenho de blocos de código, usando o high_resolution_clock da biblioteca chrono: https://github.com/nfergu/codetimer .
Os tempos podem ser gravados em diferentes teclas, e uma exibição agregada dos tempos de cada tecla pode ser exibida.
O uso é o seguinte:
fonte
Você também pode olhar no
[cxx-rtimers][1]
GitHub, que fornece algumas rotinas somente de cabeçalho para coletar estatísticas no tempo de execução de qualquer bloco de código onde você pode criar uma variável local. Esses timers têm versões que usam std :: chrono no C ++ 11, ou timers da biblioteca Boost, ou funções padrão do timer POSIX. Esses temporizadores relatam a duração média, máxima e mínima gasta dentro de uma função, bem como o número de vezes que é chamado. Eles podem ser usados da seguinte maneira:fonte
É assim que eu faço, não muito código, fácil de entender, se encaixa nas minhas necessidades:
Uso:
fonte
fonte