ますはらの日記(?)

無線通信の勉強をしてる学生のぼやき(?)

Cython始めました1

どうも、お久しぶりです(笑)
研究室生活が始まって慣れるまでに相当時間がかかってしまい、ブログを再開するのに約半年掛かってしまうハメになっちゃいました(・・;)

せっかくブログを再開できそうなので、何かしたいなーという思いがあったので今回は“Cython”を用いた数値解析に挑戦していきます。


何故Cythonなのか?というと、僕は無線通信に関する研究室に入り様々な計算機シミュレーションをする機会があるのですが、C言語でやっているとやたらと面倒な場面が多いので今まで勉強していた(途中で放り投げてしまいましたが...笑)Pythonの数値解析に便利なモジュールを用いて楽に行いたい!
けど、試行回数が多い計算機シミュレーションでは通常のPythonではC言語に比べて遥かに処理速度が遅く実用的ではない感じになります。

そこでPythonとほぼ同じように各種のモジュールを用いることができるのにもかかわらず、処理速度が割と速いCythonに注目したのである。


今回はCythonの導入とちょっとしたPythonとCythonの比較を行いました(*゚▽゚*)
なお、自分はMacbook Airを用います。そこだけ注意してください。あとはpython3の方に入ってしまっているので実行等する際はpython3で行っています。

それでは、まずCythonの導入です。
これはpipを用いることで簡単に導入できます。

pip install cython

この1行でエラーなどを吐かなければ問題なく使えるはずです!


次は実際にコンパイルして実行する手順です。今回はpyximportを用いた手順のみ紹介します。
例はフィボナッチ数列の計算になります。
(1)pyxファイルを作成

# fib.pyx
#! -*- coding: utf-8 -*-

def fib(int n):
  cdef int i
  cdef double a=0.0, b=1.0
  for i in range(n):
    a, b = a + b, a
  return a

ここでの"cdef"文はC版に静的に片付けしている。

(2)pyximportによって使用

$ python3
>>> import pyximport
>>> pyximport.install()
(None, <pyximport.pyximport.PyxImporter object at 0x10619e240>)
>>> import fib
>>> fib.fib(90)
2.880067194370816e+18

ちなみに、このpyximportは普通に.pyファイルにも組み込んでfibをimportして関数fib()を用いることができます。


最後にPythonとの処理速度を比較してみました。
比較するために以下の2つのファイル(普通の.pyファイルとCythonを適用した.pyファイル)を実行させた。
(i)普通の.pyファイル

# fib.py
#! -*- coding: utf-8 -*-

import time
start = time.time()

def fib(n):
    a, b = 0.0, 1.0
    for i in range(n):
        a, b = a + b, a
    return a

for i in range(1000):

    c = fib(90)

elapsed_time = time.time() - start
print("elapsed_time:{0}".format(elapsed_time))

(ii)Cythonを用いた.pyファイル

# sample.py
#! -*- coding: utf-8 -*-

import time
start = time.time()

import pyximport
pyximport.install()
import fib

for i in range(1000):

    a = fib.fib(90)

elapsed_time = time.time() - start
print("elapsed_time:{0}".format(elapsed_time))


実際に計測した結果は次のようになりました。

関数の実行繰り返し回数: 1000
$ python3 fib.py
elapsed_time:0.006333112716674805
$ python3 sample.py
elapsed_time:0.012300968170166016

関数の繰り返し回数: 100000
$ python3 fib.py
elapsed_time:0.5685431957244873
$ python3 sample.py
elapsed_time:0.041645050048828125

この結果から考えると、関数にループを用いた処理が含まれる場合、試行回数が増えれば増えるほど処理速度の改善が目に見えることがわかりました。
参考にこの本を用いています。↓

Cython ―Cとの融合によるPythonの高速化

Cython ―Cとの融合によるPythonの高速化

Cythonの勉強にはもってこいだと思いますので興味ある人は是非見てみてください。

すごく簡単なことしかできてませんが、これから徐々に進めていって、いずれはシミュレーションも行っていきたいと思います。
次回はいつになるかは未定ですが、ブログ更新したいと思います(笑)

それでは、また。