답변:
timeit이 작동 하는 방법 은 설정 코드를 한 번 실행 한 다음 일련의 명령문을 반복해서 호출하는 것입니다. 따라서 정렬을 테스트하려는 경우 전체 정렬에서 한 번의 패스가 이미 정렬 된 데이터가있는 다음 패스에 영향을 미치지 않도록주의해야합니다 (물론 Timsort가 최상의 성능을 발휘하기 때문에 실제로 빛나게합니다) 데이터가 이미 부분적으로 주문 된 경우).
정렬 테스트를 설정하는 방법의 예는 다음과 같습니다.
>>> 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
일련의 명령문은 모든 패스에서 정렬되지 않은 데이터의 새로운 사본을 만듭니다.
또한 측정 제품군을 7 회 실행하고 최상의 시간 만 유지하는 타이밍 기술에 유의하십시오. 이는 시스템에서 실행중인 다른 프로세스로 인한 측정 왜곡을 줄이는 데 실제로 도움이됩니다.
이것들은 timeit을 올바르게 사용하는 팁입니다. 도움이 되었기를 바랍니다 :-)
.repeat(7,1000)
이미 같은 씨앗을 사용하여 이것을 한다는 것입니다 ! 따라서 귀하의 솔루션은 완벽한 IMO입니다.
.repeat(7, 1000)
대 .repeat(2, 3500)
대가 .repeat(35, 200
) 때문에 시스템 부하에 대한 오류로 인해 입력 변동에 오류 비교하는 방법에 의존한다. 극단적 인 경우 시스템에 항상 부하가 큰 상태에서 실행 시간 분포 왼쪽에 길고 얇은 꼬리가 나타나는 경우 (드문 유휴 상태에서 시스템을 잡을 때) .repeat(7000,1)
더 유용한 경우 .repeat(7,1000)
가 있습니다. 7,000 회 이상의 예산을 책정 할 수 없습니다.
timeit
대화식 Python 세션에서 사용하려는 경우 두 가지 편리한 옵션이 있습니다.
IPython 쉘을 사용하십시오 . 편리한 %timeit
특수 기능이 있습니다.
In [1]: def f(x):
...: return x*x
...:
In [2]: %timeit for x in range(100): f(x)
100000 loops, best of 3: 20.3 us per loop
표준 Python 인터프리터에서는 대화식 세션 중에 이전에 정의한 함수 및 기타 이름을 __main__
setup 문에서 가져 와서 액세스 할 수 있습니다 .
>>> def f(x):
... return x * x
...
>>> import timeit
>>> timeit.repeat("for x in range(100): f(x)", "from __main__ import f",
number=100000)
[2.0640320777893066, 2.0876040458679199, 2.0520210266113281]
from __main__ import f
기술 을 보여주기 위해 +1 . 나는 이것이 널리 알려져 있다고 생각하지 않습니다. 함수 또는 메소드 호출 시간이 초과되는 경우에 유용합니다. 다른 경우 (일련의 단계 타이밍)에는 함수 호출 오버 헤드가 발생하므로 도움이되지 않습니다.
%timeit f(x)
sys._getframe(N).f_globals
)이 처음부터 기본값이었을 것입니다.
비밀로 알려 드리겠습니다. 사용하는 가장 좋은 방법 timeit
은 명령 줄에 있습니다.
명령 행에서 timeit
적절한 통계 분석을 수행합니다. 가장 짧은 실행 시간을 알려줍니다. 이것은 모두 좋기 때문에 좋습니다타이밍의 오류가 양수 . 따라서 가장 짧은 시간은 오류가 가장 적습니다. 컴퓨터가 계산할 수있는 것보다 빠르게 계산할 수 없기 때문에 부정적인 오류를 얻을 수있는 방법이 없습니다!
따라서 명령 행 인터페이스는 다음과 같습니다.
%~> python -m timeit "1 + 2"
10000000 loops, best of 3: 0.0468 usec per loop
아주 간단합니다.
당신은 물건을 설정할 수 있습니다 :
%~> python -m timeit -s "x = range(10000)" "sum(x)"
1000 loops, best of 3: 543 usec per loop
유용합니다!
여러 줄을 원한다면 쉘의 자동 연속을 사용하거나 별도의 인수를 사용할 수 있습니다.
%~> python -m timeit -s "x = range(10000)" -s "y = range(100)" "sum(x)" "min(y)"
1000 loops, best of 3: 554 usec per loop
그것은 설정을 제공합니다
x = range(1000)
y = range(100)
그리고 시간
sum(x)
min(y)
더 긴 스크립트를 원한다면 timeit
Python 스크립트 내부 로 이동하고 싶을 수도 있습니다 . 명령 줄에서 분석과 타이밍이 더 좋기 때문에 피하는 것이 좋습니다. 대신 쉘 스크립트를 만드는 경향이 있습니다.
SETUP="
... # lots of stuff
"
echo Minmod arr1
python -m timeit -s "$SETUP" "Minmod(arr1)"
echo pure_minmod arr1
python -m timeit -s "$SETUP" "pure_minmod(arr1)"
echo better_minmod arr1
python -m timeit -s "$SETUP" "better_minmod(arr1)"
... etc
여러 초기화로 인해 시간이 조금 더 걸릴 수 있지만 일반적으로 큰 문제는 아닙니다.
하지만 사용 하고 싶다면timeit
모듈 내부에?
간단한 방법은 다음과 같습니다.
def function(...):
...
timeit.Timer(function).timeit(number=NUMBER)
그 누적 당신 (제공 하지 그 횟수만큼 실행하는 최소한이 !) 시간을줍니다.
좋은 분석을 얻으려면 .repeat
최소 사용 하고 사용하십시오.
min(timeit.Timer(function).repeat(repeat=REPEATS, number=NUMBER))
일반적으로 오버 헤드를 낮추는 functools.partial
대신 이것을 결합해야합니다 lambda: ...
. 따라서 다음과 같은 것을 가질 수 있습니다.
from functools import partial
def to_time(items):
...
test_items = [1, 2, 3] * 100
times = timeit.Timer(partial(to_time, test_items)).repeat(3, 1000)
# Divide by the number of repeats
time_taken = min(times) / 1000
당신은 또한 할 수 있습니다 :
timeit.timeit("...", setup="from __main__ import ...", number=NUMBER)
명령 줄에서 인터페이스에 더 가까운 것을 제공 하지만 훨씬 덜 멋진 방식으로 제공합니다. 은 "from __main__ import ..."
당신이 만든 인공 환경 내부에 메인 모듈의 코드를 사용할 수 있습니다 timeit
.
이것은 편리한 래퍼 Timer(...).timeit(...)
이므로 타이밍에 특히 좋지 않습니다. 나는 Timer(...).repeat(...)
위에서 보여준 것처럼 개인적으로 사용하는 것을 훨씬 선호합니다 .
timeit
사방에 몇 가지 경고가 있습니다.
오버 헤드는 계산되지 않습니다. x += 1
추가 시간이 얼마나 걸리는지 알아 보려면 시간을 정하고 싶다고 가정 해보십시오 .
>>> python -m timeit -s "x = 0" "x += 1"
10000000 loops, best of 3: 0.0476 usec per loop
글쎄, 그것은 0.0476 µs 가 아닙니다 . 당신은 그것 보다 적은 것을 알고 있습니다. 모든 오류는 양수입니다.
따라서 순수한 오버 헤드를 시도하고 찾으십시오 .
>>> python -m timeit -s "x = 0" ""
100000000 loops, best of 3: 0.014 usec per loop
타이밍만으로도 30 % 의 우수한 오버 헤드입니다! 이로 인해 상대 타이밍이 크게 왜곡 될 수 있습니다. 그러나 당신은 정말로 타이밍을 추가하는 것에 관심을 가졌습니다. 조회 시간 x
도 오버 헤드에 포함되어야합니다.
>>> python -m timeit -s "x = 0" "x"
100000000 loops, best of 3: 0.0166 usec per loop
그 차이는 그다지 크지 않지만 거기에 있습니다.
돌연변이 방법은 위험합니다.
>>> python -m timeit -s "x = [0]*100000" "while x: x.pop()"
10000000 loops, best of 3: 0.0436 usec per loop
그러나 그것은 완전히 잘못입니다! x
첫 번째 반복 후 빈 목록입니다. 다시 초기화해야합니다.
>>> python -m timeit "x = [0]*100000" "while x: x.pop()"
100 loops, best of 3: 9.79 msec per loop
그러나 오버 헤드가 많이 있습니다. 별도로 설명하십시오.
>>> python -m timeit "x = [0]*100000"
1000 loops, best of 3: 261 usec per loop
여기서 오버 헤드를 빼는 것은 오버 헤드가 시간의 작은 부분 이기 때문에 합리적 입니다.
예를 들어 삽입 정렬과 팀 정렬 모두 이미 정렬 된 목록에 대해 완전히 특이한 타이밍 동작을 가지고 있음을 주목할 가치가 있습니다. 즉 random.shuffle
, 타이밍을 방해하지 않으려면 여러 종류 가 필요합니다 .
timeit
실행합니다 pass
. 물론 시간이 걸립니다. 인수가 주어지면, pass
것 없는 일부 뺀 때문에, 실행 얻을 0.014
모든 타이밍에서 usecs하는 것은 잘못된 것입니다.
# Генерация целых чисел
def gen_prime(x):
multiples = []
results = []
for i in range(2, x+1):
if i not in multiples:
results.append(i)
for j in range(i*i, x+1, i):
multiples.append(j)
return results
import timeit
# Засекаем время
start_time = timeit.default_timer()
gen_prime(3000)
print(timeit.default_timer() - start_time)
# start_time = timeit.default_timer()
# gen_prime(1001)
# print(timeit.default_timer() - start_time)
이것은 잘 작동합니다 :
python -m timeit -c "$(cat file_name.py)"
다음 각각에 동일한 사전을 설정하고 실행 시간을 테스트하십시오.
설정 인수는 기본적으로 사전을 설정합니다.
숫자는 코드를 1000000 번 실행하는 것입니다. 설정이 아니라 표준
이것을 실행하면 색인이 얻는 것보다 훨씬 빠르다는 것을 알 수 있습니다. 여러 번 실행하여 볼 수 있습니다.
코드는 기본적으로 사전에서 c 값을 가져 오려고 시도합니다.
import timeit
print('Getting value of C by index:', timeit.timeit(stmt="mydict['c']", setup="mydict={'a':5, 'b':6, 'c':7}", number=1000000))
print('Getting value of C by get:', timeit.timeit(stmt="mydict.get('c')", setup="mydict={'a':5, 'b':6, 'c':7}", number=1000000))
내 결과는 다음과 같습니다.
색인으로 : 0.20900007452246427
으로 : 0.54841166886888
단순히 전체 코드를 timeit의 인수로 전달하십시오.
import timeit
print(timeit.timeit(
"""
limit = 10000
prime_list = [i for i in range(2, limit+1)]
for prime in prime_list:
for elem in range(prime*2, max(prime_list)+1, prime):
if elem in prime_list:
prime_list.remove(elem)
"""
, number=10))
import timeit
def oct(x):
return x*x
timeit.Timer("for x in range(100): oct(x)", "gc.enable()").timeit()
gc.enable()
?
내장 timeit 모듈은 IPython 명령 행에서 가장 잘 작동합니다.
모듈 내에서 기능 시간을 설정하려면 :
from timeit import default_timer as timer
import sys
def timefunc(func, *args, **kwargs):
"""Time a function.
args:
iterations=3
Usage example:
timeit(myfunc, 1, b=2)
"""
try:
iterations = kwargs.pop('iterations')
except KeyError:
iterations = 3
elapsed = sys.maxsize
for _ in range(iterations):
start = timer()
result = func(*args, **kwargs)
elapsed = min(timer() - start, elapsed)
print(('Best of {} {}(): {:.9f}'.format(iterations, func.__name__, elapsed)))
return result
매개 변수를 허용하는 함수와 함께 Python REPL 인터프리터를 사용하는 방법의 예
>>> import timeit
>>> def naive_func(x):
... a = 0
... for i in range(a):
... a += i
... return a
>>> def wrapper(func, *args, **kwargs):
... def wrapper():
... return func(*args, **kwargs)
... return wrapper
>>> wrapped = wrapper(naive_func, 1_000)
>>> timeit.timeit(wrapped, number=1_000_000)
0.4458435332577161
두 개의 함수를 만든 다음 이와 비슷한 것을 실행합니다. 사과와 사과를 비교하기 위해 같은 수의 실행 / 실행을 선택하려고합니다.
이것은 Python 3.7에서 테스트되었습니다.
!/usr/local/bin/python3
import timeit
def fibonacci(n):
"""
Returns the n-th Fibonacci number.
"""
if(n == 0):
result = 0
elif(n == 1):
result = 1
else:
result = fibonacci(n-1) + fibonacci(n-2)
return result
if __name__ == '__main__':
import timeit
t1 = timeit.Timer("fibonacci(13)", "from __main__ import fibonacci")
print("fibonacci ran:",t1.timeit(number=1000), "milliseconds")
timsort(a)
하고 차이를보십시오 :-)