Numba
Numba(ナンバ)はPythonのJIT(Just In Time)コンパイラです。簡単にいえば,Pythonの自前の関数を高速にする仕組みです。以下は M1 Mac mini 上の Python 3.12.4、NumPy 2.0.0、Numba 0.60.0 で実行しました。
使い方は、pip install numba
して、from numba import jit
して、高速化が必要な関数定義の前に @jit
(Numba 0.59以前では @jit(nopython=True)
)を付けるだけです(具体的には以下で説明します)。
速さ比べのため,まずは100万個の乱数を用意します:
import numpy as np rng = np.random.default_rng(12345) a = rng.random(1000000)
これをPython標準の sum()
関数を使って合計するのに要する時間を計測します:
%timeit sum(a)
結果:
39.1 ms ± 8.28 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
次は,自前の関数を作って,時間を計測します:
def sum1(a): s = 0 for x in a: s += x return s %timeit sum1(a)
結果:
45.8 ms ± 517 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
次はNumbaを使ってみましょう。pip install numba
などとしてインストールしてから,次を実行します(今は nopython=True
がデフォルトなので @jit
だけでいいのですが、Google Colabなどで古いバージョンが入っているかもしれないので):
from numba import jit @jit(nopython=True) def sum2(a): s = 0 for x in a: s += x return s %timeit sum2(a)
最初はコンパイルのために遅くなるかもしれないので、もう一度:
%timeit sum2(a)
結果:
962 μs ± 26.4 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
約1ミリ秒です。数十倍速くなりました。最後にNumPyの np.sum()
も試します:
%timeit np.sum(a)
結果:
198 μs ± 196 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
Numbaで高速化したものよりさらに高速です。
つまり,ループを含むようなPythonのコードはたいていNumbaで高速化できますが,同じ機能のNumPy関数があるなら,そちらを使いましょう。
NumbaでPythonのどんなコードでもコンパイルできるわけではありません。NumbaNotImplementedError
が出ない範囲で、ループなど高速化に役立つ部分だけを切り分けて @jit
を付けます。