답변:
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)
더 긴 스크립트를 원한다면 timeitPython 스크립트 내부 로 이동하고 싶을 수도 있습니다 . 명령 줄에서 분석과 타이밍이 더 좋기 때문에 피하는 것이 좋습니다. 대신 쉘 스크립트를 만드는 경향이 있습니다.
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)하고 차이를보십시오 :-)