Pythonのtimeitモジュールを使って時間を正確に計測する方法

スポンサーリンク

Pythonのtimeitモジュールは、小さなコードブロックの実行時間を素早く計測するためのシンプルなインターフェイスです。

アプリケーションを作成するとき、このコードのブロックはどのように動作するのだろうかと疑問に思い、異なるシナリオの下でテストしたいと思うかもしれません。

この問題に対して、 timeit モジュールは非常にシンプルな解決策を提供します。

それでは、このモジュールを使ってコードスニペットの時間を計る方法を見てみましょう。

ここでは、コマンドラインインターフェイスと呼び出し可能なインターフェイスの両方について見ていきます。


スポンサーリンク

Python timeit – コマンドラインインターフェース

コマンドラインインターフェースは、Pythonのプログラムを実行する場合と非常によく似ています。

m オプションを使って外部モジュール timeit をインポートし、あなたのコードに適用する必要があります。

python -m timeit 'print("Hello from Python")'

これは、文字列として渡されたスニペットを timeit を使って実行します。

デフォルトでは、Linuxで100万回、Windowsで2000万回実行され、その中から最適な時間を計測します。

以下の出力は、私のLinuxシステムでのものです。

import timeit

もし、あなたのスニペットの中にすでにforループがある場合、このモジュールは反復処理の合計が100万回に近いことを確認し、あなたのループ全体が100万回実行されないことに注意してください!

execution_time = timeit.timeit(code, number)

Python timeit – Python インターフェース

Python インタープリタ経由で timeit を使用することも可能で、その場合は次のようにインポートします。

>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.19053685299877543
>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
0.172546762998536
>>> timeit.timeit('"-".join(map(str, range(100)))', number=10000)
0.13625987299747067
>>>

実行時間を知るには、コードを文字列として timeit.timeit() に渡します。

setup_code = "import math"

パラメータ number を使って、反復処理の回数を制御することができる。

execution_time = timeit.timeit(setup = setup_code, stmt = main_block, number = 100)

timeit モジュールの使用

それでは、プログラムの中でスニペットの時間を計るために timeit をどのように使うか見てみましょう。

しかしその前に、あなたはあることに疑問を持つかもしれません。

この問題の解決策は、必要なモジュールと変数のセットアップを行うセットアップコードブロックを使用することです。

import timeit
 
# Setup is run only once
setup_code = '''
import numpy as np
a = np.arange(0, 1000)
print(a.shape)
def print_subarrays(a):
    op = []
    for i in range(a.shape[0]):
        op.append(a[:i])
'''
 
main_block = '''
print_subarrays(a)
'''
 
# Main Block is run 1000 times
print('Best execution Time among 1000 iterations:', timeit.timeit(setup=setup_code, stmt=main_block, number=1000))

セットアップブロックの書き方はとても簡単です。

必要なコードを書き、それを文字列として変数に渡すだけです。

この後、メインのコードブロックを書いて、 setupstmt パラメータを使って timeit.timeit() に渡します。

(1000,)
Best execution Time among 1000 iterations: 0.3830194959991786

timeit` は、メインループが計測される前にセットアップを行うので、一度だけ実行されます。

では、早速例を見てみましょう。

このコードは、numpyの配列の開始要素からすべての部分配列を取得しようとするものです。

セットアップブロックが一度だけ実行されることに注意してください。

import timeit
 
start_time = timeit.default_timer()
function_1()
time_1 = timeit.default_timer() - start_time
 
start_time = timeit.default_timer()
function_2()
time_2 = timeit.default_timer() - start_time
 
print('Function 1 took', time_1)
print('Function 2 took', time_2)

結果は以下の通りです。

import timeit
import numpy as np
 
def time_range(size):
    for i in range(size):
        pass
 
def time_arange(size):
    np.arange(size)
 
if __name__ == '__main__':
    # For smaller arrays
    print('Array size: 1000')
 
    start_time = timeit.default_timer();
    time_range(1000)
    range_time_1 = timeit.default_timer() - start_time
 
    start_time = timeit.default_timer();
    time_arange(1000)
    arange_time_1 = timeit.default_timer() - start_time
 
    # For large arrays
    print('Array size: 1000000')
 
    start_time = timeit.default_timer();
    time_range(1000000)
    range_time_2 = timeit.default_timer() - start_time
 
    start_time = timeit.default_timer();
    time_arange(1000000)
    arange_time_2 = timeit.default_timer() - start_time
 
    print(f'size 1000: range() took {range_time_1}')
    print(f'size 1000: arange() took {arange_time_1}')
    print(f'size 1000000: range() took {range_time_2}')
    print(f'size 1000000: arange() took {arange_time_2}')

コードブロックの性能を比較する

複数のコードブロックのパフォーマンスを timeit を使って簡単に比較することができます。

ここでは、timeit.default_timer()を使用して、タイマーを使用します。

コードブロックにかかった時間は、現在時刻から参照として取得した初期時刻を引いたものとなり、変数で渡すことができます。

Array size: 1000
Array size: 1000000
size 1000: range() took 2.2970001737121493e-05
size 1000: arange() took 8.393999451072887e-06
size 1000000: range() took 0.02567379199899733
size 1000000: arange() took 0.0031752489994687494

numpyの配列に対する2つの関数 range()np.arange() をテストして、両者を比較してみましょう。

python -m timeit -s 'import numpy_compare' 'numpy_compare.time_range(1000)'

結果は以下の通りです。

Python Timeit Cli Default

このように、timeit を使って簡単に異なる関数のパフォーマンスを比較することができます。


Time a Particular Function

他のコードブロックを実行せずに、スクリプト内の特定の関数のパフォーマンスのみを計測することもできます。

先ほどのファイルがnumpy_compare.pyであったとすると、以下のように実行時間を求めることができます。

Python Timeit Example 2

結果は以下の通りです。

Python Timeit Test On Function
Python Timeit Test On Function

まとめ

このモジュールの基本的な使い方はご理解いただけたと思いますので、さっそく使って生産性を高めていきましょう!


タイトルとURLをコピーしました