파이썬에서 정확한 함수 타이밍
Windows에서 Python으로 프로그래밍 중이며 함수가 실행되는 데 걸리는 시간을 정확하게 측정하고 싶습니다. 다른 함수를 사용하여 실행하고 실행하는 데 걸린 시간을 반환하는 "time_it"함수를 작성했습니다.
def time_it(f, *args):
start = time.clock()
f(*args)
return (time.clock() - start)*1000
나는 이것을 1000 번 호출하고 결과를 평균화합니다. (끝의 1000 상수는 밀리 초 단위로 답을 제공하는 것입니다.)
이 기능은 작동하는 것처럼 보이지만 내가 뭔가 잘못하고 있다는 잔소리가 들며, 이런 식으로 수행하면 기능이 실행될 때 실제로 사용하는 것보다 더 많은 시간을 사용하고 있습니다.
이를 수행하는 더 표준 또는 승인 된 방법이 있습니까?
더 오래 걸리도록 테스트 함수를 변경하여 인쇄를 호출하면 time_it 함수는 평균 2.5ms를 반환하고 cProfile.run ( 'f ()')은 평균 7.0ms를 반환합니다. 내 기능이 시간을 과대 평가할 것이라고 생각했습니다. 여기서 무슨 일이 일어나고 있습니까?
한 가지 추가 참고 사항은 하드웨어 및 기타 요인에 따라 분명히 달라질 수 있으므로 절대 시간이 아니라 내가 관심을 갖는 서로 비교 한 기능의 상대적 시간입니다.
고유 한 프로파일 링 코드를 작성하는 대신 내장 Python 프로파일 러 ( profile
또는 cProfile
필요에 따라) 를 확인하는 것이 좋습니다 . http://docs.python.org/library/profile.html
Python 표준 라이브러리 의 timeit
모듈 을 사용합니다 .
기본 사용법 :
from timeit import Timer
# first argument is the code to be run, the second "setup" argument is only run once,
# and it not included in the execution time.
t = Timer("""x.index(123)""", setup="""x = range(1000)""")
print t.timeit() # prints float, for example 5.8254
# ..or..
print t.timeit(1000) # repeat 1000 times instead of the default 1million
다음과 같이 "timeme"데코레이터를 만들 수 있습니다.
import time
def timeme(method):
def wrapper(*args, **kw):
startTime = int(round(time.time() * 1000))
result = method(*args, **kw)
endTime = int(round(time.time() * 1000))
print(endTime - startTime,'ms')
return result
return wrapper
@timeme
def func1(a,b,c = 'c',sleep = 1):
time.sleep(sleep)
print(a,b,c)
func1('a','b','c',0)
func1('a','b','c',0.5)
func1('a','b','c',0.6)
func1('a','b','c',1)
이 코드는 매우 정확하지 않습니다.
total= 0
for i in range(1000):
start= time.clock()
function()
end= time.clock()
total += end-start
time= total/1000
이 코드는 덜 정확합니다.
start= time.clock()
for i in range(1000):
function()
end= time.clock()
time= (end-start)/1000
함수의 런타임이 클록의 정확도에 가까우면 매우 부정확 한 경우 측정 바이어스가 발생합니다. 대부분의 측정 된 시간은 시계의 0에서 몇 틱 사이의 난수 일뿐입니다.
시스템 워크로드에 따라 단일 기능에서 관찰하는 "시간"은 전적으로 OS 스케줄링 및 기타 제어 할 수없는 오버 헤드의 아티팩트 일 수 있습니다.
두 번째 버전 (덜 부정확 함)은 측정 편향이 적습니다. 함수가 정말 빠르다면 OS 스케줄링 및 기타 오버 헤드를 줄이기 위해 10,000 번 실행해야 할 수도 있습니다.
물론 둘 다 끔찍하게 오해의 소지가 있습니다. 전체적으로 프로그램의 실행 시간은 함수 실행 시간의 합계가 아닙니다. 상대 비교를 위해서만 숫자를 사용할 수 있습니다. 많은 의미를 전달하는 절대적인 측정치가 아닙니다.
If you want to time a python method even if block you measure may throw, one good approach is to use with
statement. Define some Timer
class as
import time
class Timer:
def __enter__(self):
self.start = time.clock()
return self
def __exit__(self, *args):
self.end = time.clock()
self.interval = self.end - self.start
Then you may want to time a connection method that may throw. Use
import httplib
with Timer() as t:
conn = httplib.HTTPConnection('google.com')
conn.request('GET', '/')
print('Request took %.03f sec.' % t.interval)
__exit()__
method will be called even if the connection request thows. More precisely, you'd have you use try
finally
to see the result in case it throws, as with
try:
with Timer() as t:
conn = httplib.HTTPConnection('google.com')
conn.request('GET', '/')
finally:
print('Request took %.03f sec.' % t.interval)
This is neater
from contextlib import contextmanager
import time
@contextmanager
def timeblock(label):
start = time.clock()
try:
yield
finally:
end = time.clock()
print ('{} : {}'.format(label, end - start))
with timeblock("just a test"):
print "yippee"
Similar to @AlexMartelli's answer
import timeit
timeit.timeit(fun, number=10000)
can do the trick.
참고URL : https://stackoverflow.com/questions/889900/accurate-timing-of-functions-in-python
'programing tip' 카테고리의 다른 글
Swift : 튜플을 사용하는 단일 스위치 케이스에서 여러 간격 (0) | 2020.11.27 |
---|---|
개체에서 가장 높은 값으로 키 가져 오기 (0) | 2020.11.27 |
C에서 char 문자열을 수정할 수 있습니까? (0) | 2020.11.26 |
.NET C #에서 전체 단어의 문자열 자르기 (0) | 2020.11.26 |
Windows 7에서 git 사용 권한이 거부 됨 (공개 키) 오류 (0) | 2020.11.26 |