Cythonは結構使ってきたのですが、どうもめんどくさいと思うことがあり(大規模になるとsetup.pyが必要になるなど)、もっと簡単にPythonを高速化するNumbaというものを知りました。llvmでJITするなんてJuliaみたいで素敵じゃないですか。以下の記事を参考に私も挑戦してみました。Numba自体を初めて目にする方はまずリンク先をご覧ください。
今のところは導入方法に関してのみです。
インストール方法
Mac 10.9 with Python2.7の場合
以下で動きました。
sudo easy_install funcsigs enum34 numba
git clone https://github.com/numba/llvmlite
cd llvmlite/
sudo python setup.py install
以下注意です。
-
llvmliteはeasy_installでも入るが、dylibが足りずに実行時エラー(なぜ?)
-
enum34の他にenumというものもeasy_install可能だが、それがあるとエラー
-
最初にトライしたマシンと別のMac OS 10.9で試したところimport numbaでエラーが出たが、numpyを入れ直したら解決。あまり何も考えずgithubから以下のコマンドでビルドしただけ…。
git clone https://github.com/numpy/numpy.git numpy_temp cd numpy_temp python setupegg.py bdist_egg sudo easy_install dist/*egg
Windows7 64bit Python2.7の場合
Windows7 with WinPython2.7の場合もそのうち挑戦しますが、llvmが必要だったりC++11対応が多分必要だったり64bitが難しそうだったり壁が多そうです… 苦戦すると思いきやAnaconda入れたらそれだけで通りました。Anaconda初めて使ったのですが数値計算かじる可能性があったり自分のPythonコードを高速化したい人は積極的に使って良さそうです。
使用方法と所感
ここも後ほど加筆しますが、敢えて数値計算ではない処理で試すつもりです。理由は、数値計算に対する効果は上述の先人様が既に評価済であることと、今たまたま自分は数値計算ではなく複雑なバイナリデータの読み書きプログラムなどを作っているからです。
PyInstallerで使えるように
PyInstallerを使うとPythonスクリプトをexecutableにできて他人に配布しやすくなったりしますが、numbaを使ったものは実行時に以下のエラーになります。これは、Pythonが動的にdlopenするファイルに関してPyInstallerが収集に失敗していることが原因です。
OSError: dlopen(/var/folders/qk/z4x58g2962q21q5570g2hj0c0000gn/T/_MEIRXXAjg/llvmlite/binding/libllvmlite.dylib, 6): image not found
そこでこのdylibもビルド結果に含めてやりましょう。以下の手順で問題を回避できます。なおPyInstallerはgithubのtag v2.1を使っています。
Macの場合
-
python pyinstaller/pyinstaller.py --onefile test.py する。このときtest.specができると同時にこのtest.specを元にexeが作られるが、このexeは上記エラー状態。
-
test.specに以下のように一行足して、libllvmlite.dylibをonefileされたexecutableの中に埋め込むように指示する。
# -*- mode: python -*- a = Analysis(['test.py'], pathex=['/path/to/main/script'], hiddenimports=[], hookspath=None, runtime_hooks=None) # この下の1行が追加 a.binaries += [("llvmlite/binding/libllvmlite.dylib", "/Library/Python/2.7/site-packages/llvmlite/binding/libllvmlite.dylib", 'BINARY')] pyz = PYZ(a.pure) exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, name='test', debug=False, strip=None, upx=True, console=True )
-
python pyinstaller/pyinstaller.py --clean test.specとし、修正後のtest.specで再ビルドする。
Windows Anacondaの場合
(C:¥Anacondaに環境をインストールしたと仮定します) まずAnaconda環境をPyInstallerで使おうとするとNumba関係なくpywintypesが見つからないエラーに遭遇します。が、ここに書いてあった方法でdllをPyInstallerに見つかる場所に置いて解決できました。
cd C:\Anaconda\Lib\site-packages\win32\
copy pywintypes27.dll lib\
copy pythoncom27.dll lib\
あとはMacの場合と同様にllvmlite.dllの調達方法を.specに書けばOKです。C:¥Anacondaにインストールした場合追加すべき一行は以下のようになるはずです。
a.binaries += [("llvmlite/binding/llvmlite.dll", "C:\\Anaconda\\Lib\\site-packages\\llvmlite\\binding\\llvmlite.dll", 'BINARY')]