「ループなどの実行速度はpythonよりCの方が速いので、一部の処理だけC言語で実装したい」
「nupicを使うときにpybindが出てきたけどこれ何!?」
そんな方の疑問に答えます
コードが知りたい方は目次のソースコードへ飛んでください!
本記事のテーマ
(今回はCPUのエンディアンチェックをC++で実装し、pythonで動かす)
pybind11とは
pybind11はC++とPythonを連携させるためのライブラリである。以下のような特徴がある。
(https://kivantium.net/cpp-pybind11 から引用)
pybind11のインストール!
pip install pybind11
PythonでC・C++動かす!【実装】
流れ
pybind11の連携
(今回はCPUのエンディアンチェックをC++で実装し、pythonで動かす)
〜pybind11の連携コード
PYBIND11_MODULE()はPythonでimportする際の関数を作成する
「第一引数がimportする際の名前になる!」
m.def()の第二引数にpythonで実行したい関数のアドレスを入力する
ちなみに、C++コード内のreinterpret_cast<char*>
は強制的にキャストしたいときに使うものです。今回はint型を無理やりchar型に変換しました。
code
#include<pybind11/pybind11.h>
int check_endian() {
int src = 0x01234567;
char* src_p;
src_p = reinterpret_cast<char*>(&src);
printf("int src : 0x%x\n", src);
printf("int src >> 24 : 0x%x\n", src >> 24);
printf("char src_p : 0x%x\n", *src_p);
printf("char src_p[1] : 0x%x\n", src_p[1]);
if(*src_p != src >> 24){
printf("\nThis CPU is Littel Endian.\n");
return 1;
}else{
printf("\nThis CPU is Big Endian.\n");
return 0;
}
}
//PYBIND11_MODULE()はPythonでimportする際の関数を作成する
PYBIND11_MODULE(test, m) {
m.doc() = "pybind11 example plugin";
m.def("check_endian", &check_endian, "A function which adds tow numbers");
}
C・C++ファイルをコンパイルする
コンパイルのコマンドは以下の通りです。
clang++ -O3 -Wall -shared -std=c++11 -fPIC `python -m pybind11 --includes` -undefined dynamic_lookup check_endian.cpp -o test`python3-config --extension-suffix`
・-oの前には連携したいC++のファイル名を書く
・-oの後にはimportする際の関数名を書く(cppファイル内の名前と揃える)
出力
test.cpython-37m-darwin.so
C++の実行ファイルが作られます。
pythonで実行する
code
import test
if __name__ == "__main__" :
conclusion = test.check_endian()
print("\n"+"###"*10)
print("conclusion", conclusion)
出力
int src : 0x1234567
int src >> 24 : 0x1
char src_p : 0x67
char src_p[1] : 0x45
This CPU is Littel Endian.
##############################
conclusion 1
完成です!
C++で書いたエンディアン判別をPythonで実行しました。
機械学習などで大量の計算をする際には、こういった一工夫が必要になるのではないかと思います。知ってるだけで、次に出会ったときに対処できるので一度自分で実装してみて下さい!