C言語でpythonモジュール作成
突然ですが、pythonって便利ですよね?
組込系やWeb系、アプリケーション、機械学習(ディープラーニング)に至るまで幅広く用いることが出来る!!
万能言語ですね!!下回りから上位までを網羅できる!!
ゆりかごから墓場まで!!安心感がすごいです!!。
ただ、、、実は自分、、、あまり好きな言語ではなんですよね。。。
だってだって、処理が遅いんだもん~~~~~!!
分かってるよ、、、分かってますとも。インタプリタ型言語だしね。
だけど、繰り返し処理を実行するだけで数秒掛かる時があるとか、酷い(泣)。
色々なライブラリが提供されており、これらを組み合わせればよいのだろうけど、自分で本当にやりたい処理に対して遠回りしなきゃならない時があったり。。。(泣)
。。。!?
自分で作ればよくない!?自分で作れるならそっちの方が自由度高くかつ高速処理可能なモノが作れね?www
ということで、C言語でpythonモジュールを作成してみました!!
今回は、バブルソートをpythonモジュールで書いてみます。
一部ソースコードに誤りがありました!!申し訳ございません。。。
うまく配列をC言語モジュールに渡せていないことが原因です。以下は別に作成した簡単なソースコードで確認します。
環境はラズパイ4を用います。
下記を参考に作成してみました。
qiita.com
まず、C言語のpythonモジュールの流れですが、
①C言語でpythonモジュールを作成
②ビルド環境作成
③pythonでC言語をビルド
④pythonで生成物をimport
となります。
まず、"①C言語でpythonモジュールを作成"です。
全体はこの通りです。
static PyObject* queue(PyObject *self,PyObject *args){ int x,y,g; if (!PyArg_ParseTuple(args, "ii", &x, &y)){ return NULL; } g = 0; for(int i=0;i<100;i++){ for(int j=0;j<100;j++){ if(i%2==0 && j%2==0){ g = g - i -j; }else if(i%2==0 && j%2==1){ g = g -i + j; }else if(i%2==1 && j%2==0){ g = g + i - j; }else{ g = g + i + j; } } } return Py_BuildValue("i",g); } static PyMethodDef PracticeMethods[] = { {"queue", (PyCFunction)queue, METH_O, "c_test: queue"}, {NULL,NULL,0,NULL} }; static struct PyModuleDef practicetmodule ={ PyModuleDef_HEAD_INIT, "c_test", NULL, -1, PracticeMethods }; PyMODINIT_FUNC PyInit_practice(void){ return PyModule_Create(&practicetmodule); }
queue関数は実際にやらせたい処理になります。
残りの処理でqueue関数をモジュールとして、登録処理を実施しています。
次にpythonでビルドするために、setup.pyを作成します。
setup.pyは下記の通りになります。
ここは、参考にさせていただいたソースコードを持ってきて、
対象となるc言語のファイル名だけ変更しました。
from distutils.core import setup, Extension setup(name='practice', version='1.0', ext_modules=[Extension('practice', ['c_test.c'])] )
setup.pyでC言語をpythonモジュールにするため、下記でビルドしました。
python setup.py build_ext -i
では実際にpythonでモジュールを利用してみたいと思います。
今回pythonで書いた処理とCモジュールを用いた処理で比較するために、
このようなソースを作成。
import practice as c_practice import time start = time.time() print(c_practice.queue(0,0)) #C言語モジュールの実行. elapsed_time = time.time() - start start2 = time.time() g = 0 #pythonコードの実行. for i in range(100): for j in range(100): if i % 2 == 0 and j % 2==0: g = g -i - j elif i % 2 ==0 and j % 2==1: g = g - i+ j elif i % 2 == 1 and j % 2==0: g = g + i -j else: g = g + i + j elapsed_time2 = time.time() - start2 print("C import time is {0}".format(elapsed_time)+"[sec]") print("python time is {0}".format(elapsed_time2)+"[sec]")
こちらで作成したpythonモジュールを呼び出し、
import practice as c_practice
こちらで実行。
test_list = c_practice.queue(arry) #c言語のモジュールで実行した場合.
では最後に比較してみます!!
結果はこの通り!!
時間は、各要素数(i,j)毎に5回実施してその平均値となります。
pythonコードはやはり遅いですね。。。w
要素数(i,j)が5000だと30秒近くかかっている。。。
一方、C言語モジュールを用いた場合には要素数が5000であっても600ms程度で終了します。
モジュール化すると段違いで処理が早くなりますね!!
もしpythonで処理が重い場合にはモジュール化を実施してみるとよさそうです!!
python嫌いな理由が一つ解消しましたww。
追伸:
バブルソートについてはまたどこかでチャレンジしたいと思っております。
実はこのブログを読んだ友達がおかしなことに気づき、連絡頂いたことが原因で発覚しました!!
持つべきものは友達ですね!!