cythonでpythonの計算時間を100倍に 〜(1)cythonのcdefを使う〜
概要
ある単純な足し算の計算速度向上をcythonの2つの機能を使うことで試みた。
(1)cdefを使う
純粋なpythonを使った場合と、cythonを使った場合で計算時間を比較を行った。
その結果、cythonで、cdef利用した場合には(ある条件下では)50倍程度高速化された。
(後述の環境では、5.7[sec]かかっていたものが、100[msec]程となった。)
(2)nogilを使う
cythonのwith nogilを使うことで、GIL(Global Interpreter Lock)の制限解除を行うことが出来る。
(<--pythonのAPIは一切使えない、thread切り替えのoverheadがあるなど、注意点もあるとのことだが)
GIL解除+multithreadingで、複数コア環境で更に倍速にすることを試みた。
"(2)"は近日中記載予定。
以下では、"(1)"について記載する。
背景
PyCon2013(2013/09/14-15@新宿/工学院大学)で、cythonを使うと、高速化できるという話を伺ったので、遊んでみようと簡単な例を試してみたという次第。
聴講したセッションは、以下。
「Cythonによる拡張モジュール開発」(Atsuo Ishimoto氏)
http://apac-2013.pycon.jp/zh/program/sessions.html#session-14-1630-rooma0765-ja2-en
資料:http://www.slideshare.net/atsuoishimoto/introduction-to-cython
動画:http://www.youtube.com/watch?v=eo6YcwQZV8k
# 48'06"あたりから、自分の質問も残っていたりw
環境
OS:(仮想系内)Ubuntu10.04
CPU:(仮想系内)Intel(R) Core(TM) i7-2670QM CPU @ 2.20GHz * 2
Mem:(仮想系内)4GB
コード
C,python,cython+pythonのコードを用意し、単純な足し算での速度比較を行ってみた。
C言語
simple_add_pure_c.c
#include <stdio.h> int main(){ long long a=0; long long i=0; for(i=0; i<100000000; i++){ a += i; } printf("%lld\n",a); return 0; }
python
simple_add.py
#! /usr/bin/env python # -*- coding: utf-8 -*- def simple_add(): a = 0 for i in range(100000000): a += i return a if __name__ == "__main__": print simple_add()
python+cython(cdefなし)
simple_add2.pyx
def simple_add(): a = 0 for i in range(100000000): a += i return a
simple_add2_cython.py(cythonモジュールを呼ぶ人)
#! /usr/bin/env python # -*- coding: utf-8 -*- if __name__ == "__main__": import simple_add2 print simple_add2.simple_add()
python+cython(cdefあり)
simple_add2_cdef.pyx
def simple_add(): cdef int i,a a = 0 for i in range(100000000): a += i return a
simple_add2_cython.py(cythonモジュールを呼ぶ人)
#! /usr/bin/env python # -*- coding: utf-8 -*- if __name__ == "__main__": import simple_add2_cdef print simple_add2_cdef.simple_add()
実行(ビルド/時間測定)
cのコード --> 2[msec]ほど
$ gcc -O2 simple_add_pure_c.c -o simple_add_pure_c $ time ./simple_add_pure_c real 0m0.002s user 0m0.010s sys 0m0.000s
python --> 8[sec]ほど
$ time ./simple_add.py real 0m8.138s user 0m6.660s sys 0m1.470s
cython(cdefなし) --> 5[sec]ほど
$ cython simple_add2.pyx $ export PYTHON_H_DIR=/usr/include/python2.6 $ gcc -c -O2 -fPIC -I$PYTHON_H_DIR simple_add2.c -o simple_add2.o ※最適化オプション(-O2)つけないと、あまり速くならなかった。(あたりまえといえばあたりまえ) $ gcc -shared -o simple_add2.so simple_add2.o $ time ./simple_add2_cython.py real 0m5.516s user 0m4.290s sys 0m1.220s
cython(cdefあり) --> 100[msec]ほど
$ cython simple_add.pyx $ export PYTHON_H_DIR=/usr/include/python2.6 $ gcc -c -O2 -fPIC -I$PYTHON_H_DIR simple_add2_cdef.c -o simple_add2_cdef.o $ gcc -shared -o simple_add2_cdef.so simple_add2_cdef.o real 0m0.100s user 0m0.090s sys 0m0.020s
参考
Pythonを高速化するCythonを使ってみた
http://kesin.hatenablog.com/entry/20120306/1331043675
追記
2013/09/18 Mi.
"実行"の"最適化オプション"について補足
2013/10/18 Fr.
社内勉強会で発表。指摘事項を反映。
int -> long longに変更(overflowしていたorz)
結果も確認出来るように、print文を追加。
aの初期化漏れ対応。a=0を追加。