Pythonで計算処理時間を計測する方法
今回はプログラムの処理時間を計測する方法について解説していきます。
様々な計測方法があるのでその違いについても少し触れていこうと思います。
以下が今回のコンテンツです。
目次
- モジュールを使わない時間計測方法
- %%time
- %%timeit
- モジュールを使う時間計測方法
- time.time()
- time.perf_counter()
- time.process_time()
- time.monotonic()
- 実際に処理時間を計ってみよう
- まとめ
モジュールを使わない場合
pythonを対話型で実行できるJupyter Notebookでは%%timeや%%timeitといったマジックコマンドを使うことができます。おそらくこの方法が最も簡単に計測時間を計れる方法ではないでしょうか。以下が実行例です。
%%time
-処理-
#処理時間
また、
%%timeit
-処理-
#何回か-処理-を実行した時の平均的な時間
気をつけたいのは必ずプログラムの先頭に記述するということです。
勘が鋭い方は気づいたかもしれませんが先頭にしか配置できないということは部分的な処理の計測時間を計ることはできません。したがって部分的な処理の時間を計測したいなーというときは次節で紹介するモジュールを使った方法を使う方が良きです。
モジュールを使う場合
先ほどはモジュールを使わない場合をご紹介しましたが今度はtimeモジュールをインポートして時間を計測する場合です。この方法はプログラム全体の処理時間ではなく一部の処理の時間を計測することができます。
time.time()
先ずはtimeモジュールのオーソドックスなtime.time()です。
精度としては1/60程度だそうです。
import time
start = time.time()
-処理-
end = time.time()
print(end-start)
#処理時間出力
time.perf_counter()
次にtime.time()より高精度で計測したい場合の方法です。
精度としてはマイクロ秒程度だそうです。
尚、Python3.3以降ではtime.clock()が廃止されてこれになったといわれています。
import time
start = time.perf_counter()
-処理-
end = time.perf_counter()
print(end-start)
#処理時間出力
time.process_time()
精度としては先ほどのtime.perf_counter()と同程度でこちらはsleep時間を計測しない場合の処理時間の計測になります。
import time
import time
start = time.process_time()
-処理-
end = time.process_time()
print(end-start)
#処理時間出力
time.monotonic()
最後に単調増加な時刻を返すことによる計測方法です。
import time
start = time.process_time()
-処理-
end = time.process_time()
print(end-start)
#処理時間出力
実際に処理時間を計ってみよう
実際に以下のフィボナッチ数列の関数を用いて処理時間を計測してみましょう。
def fibonacci(n):
if n == 0:
return 0
if n == 1:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
先ずはマジックコマンドを使った場合です。
今回はn=30のフィボナッチ数を出力する処理の計測をしていきます。
%%time
fibonacci(30)
#出力
#Wall time: 271 ms
Wall timeの横に出てきた数字が処理に掛かった時間を表しています。
また、timeitの場合は、
%%timeit
fibonacci(30)
#出力
#309 ms ± 13.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
色んな情報(誤差・実行回数等)が出力されますが309msという部分が計測時間になります。
次にモジュールを使った方法について一気にやちゃいます(5回の平均を出します)。
import time
def cal_time(x):
if x==0:
return time.time()
if x==1:
return time.perf_counter()
if x==2:
return time.process_time()
if x==3:
return time.monotonic()
n = 5
time_list = ["time.time","time.perf_counter","time.process_time","time.monotonic"]
for j in range(4):
t = 0
for i in range(n):
start = cal_time(j)
fibonacci(30)
end = cal_time(j)
t+=end-start
print(time_list[j],":{0:.10f}".format(t/5))
#出力結果
time.time :0.2656502724
time.perf_counter :0.2656119600
time.process_time :0.2718750000
time.monotonic :0.2812000000
各計測方法での時間が出力されていることが分かります。
まとめ
基本time.perf_counter()は精度が高くWin32 API で用意されている高分解能パフォーマンスカウンタであるQueryPerformanceCounterに匹敵すると思われます。
また、余談ですがtimeitにも実装されているらしいので迷ったらこれを使うのが良いのではないでしょうか。
みなさんもぜひ処理を計測したい時にどれかを使ってみてください!