簡単なプログラムの概要です
# some pre-defined constants
A = 1
B = 2
# function that does something critical
def foo(num1, num2):
# do something
# main program.... do something to A and B
for i in range(20):
# do something to A and B
# and update A and B during each iteration
import timeit
t = timeit.Timer(stmt="foo(num1,num2)")
print t.timeit(5)
「グローバル名fooが定義されていません」というメッセージが表示され続けるだけです。ありがとう!
コードスニペットは自己完結型である必要があります。外部参照を作成することはできません。ステートメント文字列またはセットアップ文字列で値を定義する必要があります。
import timeit
setup = """
A = 1
B = 2
def foo(num1, num2):
pass
def mainprog():
global A,B
for i in range(20):
# do something to A and B
foo(A, B)
"""
t = timeit.Timer(stmt="mainprog()" setup=setup)
print(t.timeit(5))
さらに良いことに、グローバル値を使用しないようにコードを書き直してください。
関数はtimeit
で引数を使用できます。これらがクロージャーを使用して作成されている場合、別の関数でそれらをラップすることにより、この動作を追加できます。
def foo(num1, num2):
def _foo():
# do something to num1 and num2
pass
return _foo
A = 1
B = 2
import timeit
t = timeit.Timer(foo(A,B))
print t.timeit(5)
短くするか、明示的なクロージャー宣言の代わりに functools.partial を使用できます
def foo(num1, num2):
# do something to num1 and num2
pass
A = 1
B = 2
import timeit, functools
t = timeit.Timer(functools.partial(foo, A, B))
print t.timeit(5)
モジュールのファイル名がtest.pyであるとします
# some pre-defined constants
A = 1
B = 2
# function that does something critical
def foo(n, m):
pass
# main program.... do something to A and B
for i in range(20):
pass
import timeit
t = timeit.Timer(stmt="test.foo(test.A, test.B)", setup="import test")
print t.timeit(5)
関数は、セットアップ文字列で定義する必要があります。これを行うための良い方法は、モジュール内にコードを設定することです。
t = timeit.Timer("foo(num1, num2)", "from myfile import foo")
t.timeit(5)
それ以外の場合は、すべてのセットアップをセットアップステートメント内の文字列として定義する必要があります。
setup = """
# some pre-defined constants
A = 1
B = 2
# function that does something critical
def foo(num1, num2):
# do something
# main program.... do something to A and B
for i in range(20):
# do something to A and B
# and update A and B during each iteration
"""
t = timeit.Timer("foo(num1, num2)", setup)
t.timeit(5)
私が見つけた素晴らしいものは、cProfileを使用するiPythonのショートカットです。
def foo(x, y):
print x*y
%prun foo("foo", 100)
私は通常、追加の関数を作成します。
def f(x,y):
return x*y
v1 = 10
v2 = 20
def f_test():
f(v1,v2)
print(timeit.timeit("f_test()", setup="from __main__ import f_test"))
別のオプションは、関数をその引数に functools を介してバインドすることです(std :: bindと同様)。その後、timeitに引数を渡す必要はありません。functool.partial
によって返される呼び出し可能オブジェクトがそれを処理します。
def findMax(n):#n is an array
m = 0
c = 0
for i in range(len(n)):
c += 1
if m < n[i]:
m = n[i]
return m, c
import timeit
import functools
a = [6, 2, 9, 3, 7, 4, 5]
t = timeit.Timer(functools.partial(findMax,a))
t.timeit(100)
グローバルを呼び出さずにタイミングルーチンを区分化する方法の例を次に示します
_def foo(a, b):
'''Do something to `a` and `b`'''
return a + b
def time_foo():
'''Create timer object simply without using global variables'''
import timeit
_foo = foo
a = 1
b = 2
# Get `Timer` oject, alternatively just get time with `timeit.timeit()`
t = timeit.Timer('_foo(a, b)', globals=locals())
return t
_
同じtimeit
関数を使用して他の関数の時間を計る場合は、これを一般化することもできます。例はmain()
ルーチンの例です:
_def foo1(a, b):
'''Add `a` and `b`'''
return a + b
def foo2(a, b):
'''More math on `a` and `b`'''
return (a**2 * b)**2
def time_foo(func, **kwargs):
'''Create timer object simply without using global variables'''
import timeit
return timeit.timeit('func(**kwargs)', globals=locals())
def run():
'''Modify inputs to foo and see affect on execution time'''
a = 1
b = 2
for i in range(10):
# Update `a` and `b`
a += 1
b += 2
# Pass args to foo as **kwargs dict
print('foo1 time: ', time_foo(foo1, **{'a':a, 'b':b}))
print('foo2 time: ', time_foo(foo2, **{'a':a, 'b':b}))
return None
_
より簡単な解決策があります(少なくともPython 3の場合))、現在のグローバル名前空間内でコードを実行させることができます:
t = timeit.Timer(stmt="foo(num1,num2)", globals=globals())
https://docs.python.org/3/library/timeit.html#examples グローバルは推奨されませんが、何かを確認する簡単なスクリプトを作成している場合、これは最も簡単な実装。
今日Python 3.7でタイミングをいじって、関数と変数をタイマーに渡そうとしました。これが私が思いついたものです。
import re
text = "This is a test of the emergency broadcast system"
def regex(text):
return re.sub(r"(\s)\1{1,}", r"\1", text)
def loop_while(text):
if " " in text:
while " " in text:
text = text.replace(" ", " ")
return text
if __name__ == "__main__":
import timeit
callable_functions = [item for item in locals().items() if callable(item[1])]
for func_name, func in callable_functions:
elapsed_time = timeit.timeit(f"{func_name}(text)", globals=globals(), number=100000)
print(f"{func_name}: {elapsed_time} \n{func(text)}\n")
これは出力します:
正規表現:1.378352418
これは緊急放送システムのテストですloop_while:0.15858950299999997
これは緊急放送システムのテストです
次に、新しいバージョンをテストするために必要なのは、新しい関数を追加することだけです。何かのようなもの:
def split_join(text):
return " ".join(text.split())
これで出力されます:
正規表現:1.378352418
これは緊急放送システムのテストですloop_while:0.15858950299999997
これは緊急放送システムのテストですsplit_join:0.05700970800000005
これは緊急放送システムのテストです
これはうまくいくはずです:
import timeit
def f(x,y):
return x*y
x = 5
y = 7
print(timeit.timeit(stmt='f(x,y)',
setup='from __main__ import f, x, y',
number=1000))
タイマーを実行する前にすべてのデータを取得する準備ができたstatic
クラスを作成することをお勧めします。
別のメモとして、グローバルスペースは
FAST_LOAD
を活用していないため、グローバルスペースではなく、関数でテスト実行する方が良いPythonコードは関数内でより速く実行されますか?
class Data(object):
"""Data Creation"""
x = [i for i in range(0, 10000)]
y = Tuple([i for i in range(0, 10000)])
def __init__(self):
pass
import timeit
def testIterator(x):
for i in range(10000):
z = i
print timeit.timeit("testIterator(Data.x)", setup="from __main__ import testIterator, Data", number=50)
print timeit.timeit("testIterator(Data.y)", setup="from __main__ import testIterator, Data", number=50)