O(n) vs O(nlogn)

Pythonは、インタプリタ型の言語なので、インタプリタのオーバーヘッドに気をつけなければならない。以下のようなパフォーマンスのテストを行ってみた。

import time

def min1(lst):
    min_v = lst[0]
    for v in lst:
        if min_v > v:
            min_v = v
    return min_v

def min2(lst):
    lst_sorted = sorted(lst)
    return lst_sorted[0]

a = range(10000)
a.reverse()

t1 = time.time()
for i in range(10000):
    v1 = min1(a)
t2 = time.time()
print v1
print 'time of min1() =', t2 - t1  #=> time of min1() = 6.641

t1 = time.time()
for i in range(10000):
    v2 = min2(a)
t2 = time.time()
print v2
print 'time of min2() =', t2 - t1  #=> time of min2() = 4.233

つまり、Pythonでは、インタプリタのオーバーヘッドにより、O(n)より、O(nlogn)の計算量の方が、このケースにおいては早い。
sorted()では、関数の中でループを行っており、オーバーヘッドは少ない。しかし、forを使用した例では、ループごとに毎回オーバーヘッドが加算される。
つまり、Pythonでは、大量のデータに対するforループは遅い。なるべく、リスト内包表記を使用すべきであるが、関数呼び出しを伴ってしまう場合は、どちらが早いかはケースバイケースであると思われる。


ここら辺の処理を早くする工夫(ライブラリ)もあるので、今後の研究課題にするつもりである。