私はWindowsでpythonでプログラミングしています。関数が実行されるのにかかる時間を正確に測定したいと思います。別の関数を実行し、実行する関数 "time_it"実行にかかった時間を返します。
def time_it(f, *args):
start = time.clock()
f(*args)
return (time.clock() - start)*1000
これを1000回呼び出して、結果を平均します。 (最後の1000定数は、ミリ秒単位で答えを与えることです。)
この関数は機能しているように見えますが、私は何か間違ったことをしているというしつこい感じがあります。
これを行うためのより標準的なまたは受け入れられた方法はありますか?
時間がかかるようにテスト関数を変更してprintを呼び出すと、time_it関数は平均2.5ミリ秒を返しますが、cProfile.run( 'f()')は平均7.0ミリ秒を返します。私は自分の機能が時間を過大評価していると考えましたが、ここで何が起こっていますか?
もう1つの注意点は、ハードウェアやその他の要因によって明らかに変化する絶対時間ではなく、相互に比較される機能の相対時間です。
独自のプロファイリングコードを記述する代わりに、組み込みの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スケジューリングおよびその他の制御不能なオーバーヘッドの完全な成果物である場合があります。
2番目のバージョン(あまり正確ではない)の測定バイアスは小さくなっています。関数が非常に高速な場合、OSスケジューリングやその他のオーバーヘッドを抑えるために10,000回実行する必要があるかもしれません。
もちろん、どちらもひどく誤解を招きます。プログラムの実行時間(全体として)は、関数の実行時間の合計ではありません。数値は相対比較にのみ使用できます。それらは多くの意味を伝える絶対的な測定値ではありません。
計測するブロックがスローされる可能性がある場合でもpythonメソッドの時間を計る場合、1つの良いアプローチはwith
ステートメントを使用することです。いくつかのTimer
クラスを
_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
_
次に、スローする可能性のある接続メソッドの時間を計る必要があります。つかいます
_import httplib
with Timer() as t:
conn = httplib.HTTPConnection('google.com')
conn.request('GET', '/')
print('Request took %.03f sec.' % t.interval)
_
__exit()__
メソッドは、接続要求が処理されても呼び出されます。より正確には、try
finally
を使用して、スローした場合の結果を確認する必要があります。
_try:
with Timer() as t:
conn = httplib.HTTPConnection('google.com')
conn.request('GET', '/')
finally:
print('Request took %.03f sec.' % t.interval)
_
これはすてきです
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"
@AlexMartelliの答えに似ています
import timeit
timeit.timeit(fun, number=10000)
トリックを行うことができます。