Pythonのまま高速化するNumba

Cythonは結構使ってきたのですが、どうもめんどくさいと思うことがあり(大規模になるとsetup.pyが必要になるなど)、もっと簡単にPythonを高速化するNumbaというものを知りました。llvmでJITするなんてJuliaみたいで素敵じゃないですか。以下の記事を参考に私も挑戦してみました。Numba自体を初めて目にする方はまずリンク先をご覧ください。

-  [Python高速化　Numba入門](http://yutori-datascience.hatenablog.com/entry/2014/12/09/235628)
-  [Python: Numbaによる高速化](http://dr-kayai.hatenablog.com/entry/2014/10/09/175456)
-  [python: 行列演算の高速化](http://kzky.hatenablog.com/entry/2015/04/11/python%3A_行列演算の高速化)

今のところは導入方法に関してのみです。

# インストール方法
## 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](https://store.continuum.io/cshop/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](https://github.com/pyinstaller/pyinstaller/tree/v2.1)を使っています。

## Macの場合
1. python pyinstaller/pyinstaller.py --onefile test.py する。このときtest.specができると同時にこのtest.specを元にexeが作られるが、このexeは上記エラー状態。
2. test.specに以下のように一行足して、libllvmlite.dylibをonefileされたexecutableの中に埋め込むように指示する。

    ```py
    # -*- 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 )
    ```
	          
3. python pyinstaller/pyinstaller.py --clean test.specとし、修正後のtest.specで再ビルドする。

## Windows Anacondaの場合
(C:¥Anacondaに環境をインストールしたと仮定します) まずAnaconda環境をPyInstallerで使おうとするとNumba関係なくpywintypesが見つからないエラーに遭遇します。が、[ここに書いてあった方法](http://stackoverflow.com/questions/19280894/py2exe-no-system-module-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')]
```