Pythonのコードを高速化(はじめてのNumba)
大昔の記事を書き足してなんとかしたいなぁと思いつつ、いつまでも更新出来ずにいました。
少し諦めてもう少し最近のことを書くことにしました。
背景
最近仕事でPythonのコードでツールを作って間に合わせることが増えたけれど、
実行時間が遅くてコマリンスなことになることもあったので、高速化のアプローチをしてみましたとさ。
最近はこんな本を読んでます。
- 作者: Kurt W. Smith,中田秀基(監訳),長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/06/19
- メディア: 大型本
- この商品を含むブログ (2件) を見る
英語kindle版がとてもとても安かったので買ってしまいました。
で、Pythonでは下のように色々な高速化手法が色々あるけど、さてどんな感じかなと。
- Numpy
- MultiProcessing
- Cython
- C拡張
- Numba
- ???
紹介した本と関係なしに、今回は聞いたこともなかったNumba様を使ってみます。
やってみよう!
本サイトはこちら。 解説本とかは探したけど見つかりませんでした。
時間測定方法
ipython
でsample.py
に対して実行するときは大体こんな感じ。
> %timeit -n 5 %run sample
普通に書く
何もしない時
def fibo(n): if n < 2: return n return fibo(n-1) + fibo(n-2) if __name__=="__main__": fibo(38)
In [83]: %timeit -n 1 %run sample 1 loops, best of 3: 15.7 s per loop
メモ化的なやつ
def fibo(n): a,b = 0,1 for x in range(n): a,b = b,a+b return a
In [86]: %timeit -n 5 %run sample 5 loops, best of 3: 745 µs per loop
nを増やす
if __name__=="__main__": n = 10**6 fibo2(n)
In [92]: %timeit -n 1 %run sample 1 loops, best of 3: 11 s per loop
Numba1
単にjitを使ってみる
@jit def numfibo(n): a,b = 0,1 for x in range(n): a,b = b,a+b return a
In [98]: %timeit -n 5 %run sample 5 loops, best of 3: 42.6 ms per loop
もっと増やす
if __name__=="__main__": n = 10**10 numfibo(n)
In [116]: %timeit -n 1 %run sample 1 loops, best of 3: 3.32 s per loop
Numba2
型定義を入れる
@jit(int64(int64)) def numfibo2(n): a,b = 0,1 for x in range(n): a,b = b,a+b return a
In [118]: %timeit -n 1 %run sample 1 loops, best of 3: 3.23 s per loop
少し条件を変えてみる
if __name__=="__main__": n = 10**10 numfibo2(n-2) numfibo2(n-1) numfibo2(n)
Numba2
In [120]: %timeit -n 1 %run sample 1 loops, best of 3: 9.61 s per loop
ベクトル化
@vectorize([int64(int64)]) def numvfibo(n): a,b = 0,1 for x in range(n): a,b = b,a+b return a
In [122]: %timeit -n 1 %run sample 1 loops, best of 3: 9.66 s per loop
結果
単にJIT
を入れるだけでも割と高速化されそうな印象。
型定義はおまけ程度に早くなるのかな?何度やっても多少早かったので。
ベクトル化は使いどころを知らないと高速化出来なさそう。
guvectorizeもあるけど、チュートリアルを見ても使い方がぱっとは分からない割に早くなってくれなかったのでアレゲ。。。
雑記
仕事中に遊びで少し使ってみたけど、数値計算的な所以外ではjit
を入れても速くはならなかった。
というより、JIT分遅くなっている所もあるので闇雲に突っ込んでも逆効果かも。
普通のWebアプリケーションだと、計算よりも分岐とか文字列の分離結合のが多いと思うので、案外使い道が無いのではなかろうか?