Pythonのtimeitで時間計測


2016年 08月 12日

人工知能系のプログラムは、実はとても計算量が多いので、プログラムが効率がよいかどうか常に気にしておく必要がある。

時間を計測するのに、自分で、対象範囲の前後でシステムの時間を読み取り、差を取るということで求めることはできる。でも、そんなことをしなくても、Pythonには時間計測の仕組みが用意されている。

以下では、リストに追加するときに、insertとappendでどのくらい差が出るかを計測してみたものだ。計測する部分は、それぞれ関数にまとめてある。

import timeit

def insfirstfunc(n):
    a = []
    for i in range(n):
        a.insert(0,i)

def inslastfunc(n):
    a = []
    for i in range(n):
        a.insert(len(a),i)

def apdfunc(n):
    a = []
    for i in range(n):
        a.append(i)

for i in range(1000,10001,1000):
    t = timeit.Timer("insfirstfunc(i)","from __main__ import insfirstfunc,i")
    t1 = t.timeit(number=1000)
    t = timeit.Timer("inslastfunc(i)","from __main__ import inslastfunc,i")
    t2 = t.timeit(number=1000)
    t = timeit.Timer("apdfunc(i)","from __main__ import apdfunc,i")
    t3 = t.timeit(number=1000)
    print("%6d  t1=%10.6f  t2=%10.6f  t3=%10.6f" % (i,t1,t2,t3))



timeitをインポートしておいて、timeit.Timerでタイマーを生成している。
Timerの第1引数に実行したいことを文字列で書く。ここには、変数などが含まれてもよい。
第2引数に、”from  main  import”の後ろにインポートしたいものを並べておけば大丈夫なようだ。

Timerを作ったら、実際の時間計測を作ったTimerオブジェクトのtimeitメソッドで計測できる。引数に number=繰り返し回数 を指定することができる。とくに短時間の計測の場合、システムの状態に大きく依存してしまうので、なんども繰り返し実行すると誤差が減る。

詳細はマニュアルを参照して欲しい。

iPython3 で実行してみた結果を以下に示す。

In [1]: %run timeit
  1000  t1=  0.395643  t2=  0.204404  t3=  0.073373
  2000  t1=  1.217943  t2=  0.423568  t3=  0.153751
  3000  t1=  2.477653  t2=  0.639693  t3=  0.238761
  4000  t1=  4.179113  t2=  0.859387  t3=  0.316046
  5000  t1=  6.390812  t2=  1.081363  t3=  0.400768
  6000  t1=  9.033100  t2=  1.297038  t3=  0.481604
  7000  t1= 12.073041  t2=  1.506441  t3=  0.561811
  8000  t1= 15.538109  t2=  1.731817  t3=  0.645874
  9000  t1= 20.012774  t2=  2.071590  t3=  0.771902
 10000  t1= 24.719389  t2=  2.313333  t3=  0.866832



appendが一番高速で、insertで最後に挿入するのは3倍程度遅くなる。
そして、insertで最初に挿入するのは、O(n**2)のオーダーで遅くなっているのが分かる。

appendで済むなら、insertを使うのはやめるべきなのだ。

timeitを使うことで、big-O がどの程度か簡単に調べることができる。