Entendo o conceito do que timeit
faz, mas não tenho certeza de como implementá-lo no meu código.
Como posso comparar duas funções, digamos insertion_sort
e tim_sort
, com timeit
?
A maneira como o timeit funciona é executar o código de instalação uma vez e depois fazer chamadas repetidas para uma série de instruções. Portanto, se você deseja testar a classificação, são necessários alguns cuidados para que uma passagem em uma classificação no local não afete a próxima passagem com dados já classificados (que, é claro, fariam o Timsort realmente brilhar, porque apresenta melhor desempenho quando os dados já estiverem parcialmente solicitados).
Aqui está um exemplo de como configurar um teste para classificação:
>>> import timeit
>>> setup = '''
import random
random.seed('slartibartfast')
s = [random.random() for i in range(1000)]
timsort = list.sort
'''
>>> print min(timeit.Timer('a=s[:]; timsort(a)', setup=setup).repeat(7, 1000))
0.334147930145
Observe que a série de instruções faz uma nova cópia dos dados não classificados em cada passagem.
Além disso, observe a técnica de tempo de execução do conjunto de medições sete vezes e mantendo apenas o melhor tempo - isso pode realmente ajudar a reduzir distorções de medição devido a outros processos em execução no seu sistema.
Essas são minhas dicas para usar o timeit corretamente. Espero que isto ajude :-)
timsort(a)
e tirar a diferença :-).repeat(7,1000)
já faz isso (usando a mesma semente)! Portanto, sua solução é perfeita IMO..repeat(7, 1000)
vs..repeat(2, 3500)
vs.repeat(35, 200
) deve depender de como o erro devido à carga do sistema se compara ao erro devido à variabilidade de entrada. No caso extremo, se o seu sistema estiver sempre sob carga pesada e você vir uma cauda longa e fina à esquerda da distribuição do tempo de execução (quando você o pega em um raro estado inativo), você pode até achar.repeat(7000,1)
mais útil do que.repeat(7,1000)
se não pode orçar mais de 7000 execuções.Se você deseja usar
timeit
em uma sessão interativa do Python, há duas opções convenientes:Use o shell IPython . Possui a
%timeit
função especial conveniente :Em um intérprete padrão do Python, você pode acessar funções e outros nomes que você definiu anteriormente durante a sessão interativa importando-os da
__main__
instrução setup:fonte
from __main__ import f
técnica. Eu não acho que isso seja tão conhecido como deveria ser. É útil em casos como este em que uma chamada de função ou método está sendo cronometrada. Em outros casos (cronometrando uma série de etapas), é menos útil porque introduz uma sobrecarga de chamada de função.%timeit f(x)
sys._getframe(N).f_globals
) deveriam ter sido o padrão desde o início.Vou contar um segredo: a melhor maneira de usar
timeit
é na linha de comando.Na linha de comando,
timeit
faz uma análise estatística adequada: informa quanto tempo levou a menor execução. Isso é bom porque todo erro no tempo é positivo. Portanto, o menor tempo tem o menor erro. Não há como obter um erro negativo, porque um computador nunca pode calcular mais rápido do que ele pode calcular!Portanto, a interface da linha de comandos:
Isso é bem simples, né?
Você pode configurar as coisas:
o que também é útil!
Se você desejar várias linhas, poderá usar a continuação automática do shell ou argumentos separados:
Isso fornece uma configuração de
e tempos
Se você deseja ter scripts mais longos, pode ser tentado a mudar para
timeit
dentro de um script Python. Sugiro evitar isso porque a análise e o tempo são simplesmente melhores na linha de comando. Em vez disso, costumo criar scripts de shell:Isso pode demorar um pouco mais devido às múltiplas inicializações, mas normalmente isso não é grande coisa.
Mas e se você quiser usar
timeit
dentro do seu módulo?Bem, a maneira mais simples é fazer:
e isso dá a você tempo cumulativo ( não mínimo!) para executar esse número de vezes.
Para obter uma boa análise, use
.repeat
e use o mínimo:Você normalmente deve combinar isso com, em
functools.partial
vez delambda: ...
diminuir a sobrecarga. Assim, você pode ter algo como:Você também pode fazer:
o que proporcionaria algo mais próximo da interface na linha de comando, mas de uma maneira muito menos interessante. O
"from __main__ import ..."
permite usar o código do seu módulo principal dentro do ambiente artificial criado portimeit
.Vale a pena notar que este é um invólucro de conveniência
Timer(...).timeit(...)
e, portanto, não é particularmente bom no momento. Pessoalmente, prefiro usarTimer(...).repeat(...)
como mostrei acima.Advertências
Existem algumas ressalvas com
timeit
isso em todos os lugares.As despesas gerais não são contabilizadas. Digamos que você queira tempo
x += 1
para descobrir quanto tempo leva a adição:Bem, não são 0,0476 µs. Você só sabe que é menos que isso. Todo erro é positivo.
Portanto, tente encontrar uma sobrecarga pura :
Essa é uma boa sobrecarga de 30% apenas por tempo! Isso pode distorcer enormemente os tempos relativos. Mas você realmente se importava apenas com a adição de horários; os tempos de pesquisa
x
também precisam ser incluídos nas despesas gerais:A diferença não é muito maior, mas está lá.
Métodos de mutação são perigosos.
Mas isso está completamente errado!
x
é a lista vazia após a primeira iteração. Você precisará reinicializar:Mas então você tem muita sobrecarga. Conta isso separadamente.
Observe que subtrair a sobrecarga é razoável aqui apenas porque a sobrecarga é uma fração pequena do tempo.
No seu exemplo, vale a pena notar que tanto a Insertion Sort quanto a Tim Sort têm comportamentos de tempo completamente incomuns para listas já classificadas. Isso significa que você precisará de uma
random.shuffle
classificação intermediária, se quiser evitar prejudicar seus horários.fonte
timeit
em um programa, mas funcionando da mesma maneira que a linha de comando? .timeit
executa umapass
declaração quando nenhum argumento é fornecido, o que, é claro, leva algum tempo. Se algum argumento for fornecido, nãopass
será executado, portanto, subtrair alguns usecs de cada momento seria incorreto.0.014
Se você deseja comparar dois blocos de código / funções rapidamente, você pode fazer:
fonte
Acho que a maneira mais fácil de usar o timeit é pela linha de comando:
Dado test.py :
tempo de execução assim:
fonte
para mim, esta é a maneira mais rápida:
fonte
fonte
Isso funciona muito bem:
fonte
permite configurar o mesmo dicionário em cada um dos itens a seguir e testar o tempo de execução.
O argumento de configuração é basicamente configurar o dicionário
Número é para executar o código 1000000 vezes. Não é a configuração, mas o stmt
Quando você executa isso, pode ver que o índice é muito mais rápido que o obtido. Você pode executá-lo várias vezes para ver.
O código basicamente tenta obter o valor de c no dicionário.
Aqui estão os meus resultados, os seus serão diferentes.
por índice: 0.20900007452246427
por get: 0.54841166886888
fonte
basta passar todo o seu código como argumento de timeit:
fonte
fonte
gc.enable()
?O módulo timeit interno funciona melhor na linha de comando do IPython.
Para cronometrar funções de dentro de um módulo:
fonte
Exemplo de como usar o interpretador Python REPL com função que aceita parâmetros.
fonte
Você criaria duas funções e depois executaria algo semelhante a isso. Observe que você deseja escolher o mesmo número de execução / execução para comparar apple com apple.
Isso foi testado no Python 3.7.
Aqui está o código para facilitar a cópia
fonte