timeit 대 타이밍 데코레이터
코드 시간을 맞추려고합니다. 먼저 타이밍 데코레이터를 사용했습니다.
#!/usr/bin/env python
import time
from itertools import izip
from random import shuffle
def timing_val(func):
def wrapper(*arg, **kw):
'''source: http://www.daniweb.com/code/snippet368.html'''
t1 = time.time()
res = func(*arg, **kw)
t2 = time.time()
return (t2 - t1), res, func.__name__
return wrapper
@timing_val
def time_izip(alist, n):
i = iter(alist)
return [x for x in izip(*[i] * n)]
@timing_val
def time_indexing(alist, n):
return [alist[i:i + n] for i in range(0, len(alist), n)]
func_list = [locals()[key] for key in locals().keys()
if callable(locals()[key]) and key.startswith('time')]
shuffle(func_list) # Shuffle, just in case the order matters
alist = range(1000000)
times = []
for f in func_list:
times.append(f(alist, 31))
times.sort(key=lambda x: x[0])
for (time, result, func_name) in times:
print '%s took %0.3fms.' % (func_name, time * 1000.)
수확량
% test.py
time_indexing took 73.230ms.
time_izip took 122.057ms.
그리고 여기에서는 timeit을 사용합니다.
% python - m timeit - s '' 'alist=range(1000000);[alist[i:i+31] for i in range(0, len(alist), 31)]'
10 loops, best of 3:
64 msec per loop
% python - m timeit - s 'from itertools import izip' 'alist=range(1000000);i=iter(alist);[x for x in izip(*[i]*31)]'
10 loops, best of 3:
66.5 msec per loop
timeit을 사용하면 결과는 거의 동일하지만 나타나는 타이밍 데코레이터를 사용하는 time_indexing
것이 time_izip
.
이 차이의 원인은 무엇입니까?
어느 방법을 믿어야합니까?
그렇다면 어느 것입니까?
timeit을 사용하십시오. 테스트를 두 번 이상 실행하면 훨씬 더 나은 결과를 얻을 수 있습니다.
func_list=[locals()[key] for key in locals().keys()
if callable(locals()[key]) and key.startswith('time')]
alist=range(1000000)
times=[]
for f in func_list:
n = 10
times.append( min( t for t,_,_ in (f(alist,31) for i in range(n))))
for (time,func_name) in zip(times, func_list):
print '%s took %0.3fms.' % (func_name, time*1000.)
->
<function wrapper at 0x01FCB5F0> took 39.000ms.
<function wrapper at 0x01FCB670> took 41.000ms.
functools
Matt Alcock의 답변을 개선 하려면 래핑을 사용하세요 .
from functools import wraps
from time import time
def timing(f):
@wraps(f)
def wrap(*args, **kw):
ts = time()
result = f(*args, **kw)
te = time()
print 'func:%r args:[%r, %r] took: %2.4f sec' % \
(f.__name__, args, kw, te-ts)
return result
return wrap
예에서 :
@timing
def f(a):
for _ in range(a):
i = 0
return -1
다음으로 f
래핑 된 메서드 호출 @timing
:
func:'f' args:[(100000000,), {}] took: 14.2240 sec
f(100000000)
이것의 장점은 원래 기능의 속성을 보존한다는 것입니다. 즉, 함수 이름 및 독 스트링과 같은 메타 데이터가 반환 된 함수에 올바르게 보존됩니다.
I would use a timing decorator, because you can use annotations to sprinkle the timing around your code rather than making you code messy with timing logic.
import time
def timeit(f):
def timed(*args, **kw):
ts = time.time()
result = f(*args, **kw)
te = time.time()
print 'func:%r args:[%r, %r] took: %2.4f sec' % \
(f.__name__, args, kw, te-ts)
return result
return timed
Using the decorator is easy either use annotations.
@timeit
def compute_magic(n):
#function definition
#....
Or re-alias the function you want to time.
compute_magic = timeit(compute_magic)
I got tired of from __main__ import foo
, now use this -- for simple args, for which %r works, and not in Ipython.
(Why does timeit
works only on strings, not thunks / closures i.e. timefunc( f, arbitrary args ) ?)
import timeit
def timef( funcname, *args, **kwargs ):
""" timeit a func with args, e.g.
for window in ( 3, 31, 63, 127, 255 ):
timef( "filter", window, 0 )
This doesn't work in ipython;
see Martelli, "ipython plays weird tricks with __main__" in Stackoverflow
"""
argstr = ", ".join([ "%r" % a for a in args]) if args else ""
kwargstr = ", ".join([ "%s=%r" % (k,v) for k,v in kwargs.items()]) \
if kwargs else ""
comma = ", " if (argstr and kwargstr) else ""
fargs = "%s(%s%s%s)" % (funcname, argstr, comma, kwargstr)
# print "test timef:", fargs
t = timeit.Timer( fargs, "from __main__ import %s" % funcname )
ntime = 3
print "%.0f usec %s" % (t.timeit( ntime ) * 1e6 / ntime, fargs)
#...............................................................................
if __name__ == "__main__":
def f( *args, **kwargs ):
pass
try:
from __main__ import f
except:
print "ipython plays weird tricks with __main__, timef won't work"
timef( "f")
timef( "f", 1 )
timef( "f", """ a b """ )
timef( "f", 1, 2 )
timef( "f", x=3 )
timef( "f", x=3 )
timef( "f", 1, 2, x=3, y=4 )
Added: see also "ipython plays weird tricks with main", Martelli in running-doctests-through-ipython
Just a guess, but could the difference be the order of magnitude of difference in range() values?
From your original source:
alist=range(1000000)
From your timeit
example:
alist=range(100000)
For what it's worth, here are the results on my system with the range set to 1 million:
$ python -V
Python 2.6.4rc2
$ python -m timeit -s 'from itertools import izip' 'alist=range(1000000);i=iter(alist);[x for x in izip(*[i]*31)]'
10 loops, best of 3: 69.6 msec per loop
$ python -m timeit -s '' 'alist=range(1000000);[alist[i:i+31] for i in range(0, len(alist), 31)]'
10 loops, best of 3: 67.6 msec per loop
I wasn't able to get your other code to run, since I could not import the "decorator" module on my system.
Update - I see the same discrepancy you do when I run your code without the decorator involved.
$ ./test.py
time_indexing took 84.846ms.
time_izip took 132.574ms.
Thanks for posting this question; I learned something today. =)
regardless of this particular exercise, I'd imagine that using timeit
is much safer and reliable option. it is also cross-platform, unlike your solution.
ReferenceURL : https://stackoverflow.com/questions/1622943/timeit-versus-timing-decorator
'IT박스' 카테고리의 다른 글
제네릭 메서드로 인터페이스 구현 (0) | 2021.01.07 |
---|---|
PHP에서 두 문자열을 알파벳순으로 비교하는 방법은 무엇입니까? (0) | 2021.01.07 |
Ruby 1.9 : 멀티 바이트 문자열을 올바르게 업 케이스 및 다운 케이스하려면 어떻게해야합니까? (0) | 2021.01.07 |
SQL의 기존 테이블에 새로운 널이 아닌 열이있는 대체 테이블 (0) | 2021.01.07 |
2012 년에 권장되는 jQuery 템플릿? (0) | 2021.01.06 |