Cythonのパフォーマンス
2chの「pythonがこの先生きのこるには」というスレでfibでCythonがかなり遅い結果になっていたので調べてみた。
Pythonは、2.5.2、Cythonは、0.9.8.1.1を使用。
以下は、psycoを使用した通常のPython。 1.157秒。psycoを外すと 19.844秒。
# pyfib.py def fib(n): if n == 0 or n == 1: return n else: return fib(n-1) + fib(n-2)
import time import psyco from pyfib import fib psyco.full() t1 = time.time() for i in range(36): print "n=%d => %d" % (i, fib(i)) t2 = time.time() print t2 - t1, 'sec' #=> 1.15700006485 sec
以下は、Cythonでfib.pydを作成し、それをPythonで利用。 0.922秒。Cythonの方がpsycoよりも若干速い。
# fib.pyx def fib(int n): return cfib(n) cdef long cfib(int n): if n == 0 or n == 1: return n else: return cfib(n-1) + cfib(n-2)
import time from fib import fib t1 = time.time() for i in range(36): print "n=%d => %d" % (i, fib(i)) t2 = time.time() print t2 - t1, 'sec' #=> 0.921999931335 sec
結論としてきちんとしたコードを書けば、Cythonの方が細かい指定できる分、自動で全て行ってしまうpsycoよりもパフォーマンスを調整できる可能性があると思われる。フィボナッチ数を計算する単純な例でもCythonの方が速くなったのでCythonは期待できる。マニュアルを見る限りかなりしっかりしているし、Pyrexに比べかなり制限もなくなってきていると思われるのでかなり使えそう。
以下は、純粋なCとCythonの比較。測定した速度はそれぞれ、Cが0.628秒で、Cythonが0.841秒。約1.34倍の速度差なのでオーバーヘッドとしては妥当だろうか。
/* fib.c */ #include <stdio.h> #include <time.h> long fib(int n) { if (n==0 || n==1) return n; else return fib(n-1) + fib(n-2); } int main() { int i; clock_t t1, t2; t1 = clock(); for (i=0; i < 36; i++) { printf("n=%d => %d\n", i, fib(i)); } t2 = clock(); printf("%f sec\n", (double)(t2-t1)/1000.); /*=> 0.628280 sec */ }
# fib.pyx import time t1 = time.clock() cdef long fib(int n): if n == 0 or n == 1: return n else: return fib(n-1) + fib(n-2) for i from 0 <= i < 36: print "n=%d => %d" % (i, fib(i)) t2 = time.clock() print t2 - t1, 'sec' #=> 0.841137996589 sec