11月の末に公開された Numba 0.52.0 では、Intel からの寄贈により Typed List のパフォーマンスがよくなった(Release Notes 参照)ということなので、実際に試してみました。
本当に速くなっていたのは、Reflected List だった
Typed List のパフォーマンスがどれぐらい良くなったかを試すため、以下のコードで、clac_typedlist(2000) を計算してみると、ver 0.48.0 では 250ms かかっていたものが、ver 0.52.0 では 132ms と約半分に改善されていました。かなり改善されているものの、もともとが Python の速度とほとんど変わらないぐらい遅かったので、少しがっかりしました。
from numba.typed import List
@njit
def clac_typedlist(n):
x = List()
for i in range(n):
y = List()
for j in range(i + 1):
y.append(j)
x.append(y)
sum_ = 0
for i in range(n):
for j in range(i + 1):
sum_ += x[i][j]
return sum_
試しにと思って、Reflected List の方も試してみました。以下のコードで試すと、ver 0.48.0 では 82ms かかっていたものが、ver 0.52.0 では 16ms と大幅に改善されています。生の Python より20倍ぐらい処理が早くなっています。
@njit
def clac_reflectedlist(n):
x = [[y for y in range(i + 1)] for i in range(n)]
sum_ = 0
for i in range(n):
for j in range(i + 1):
sum_ += x[i][j]
return sum_
今後への期待
Typed List については問題が多く、Projects の一つになっています。それにもかかわらず長い間抜本的な改善がなかったのですが、今回、大きく改善されたのが、Reflected List の方であったとしても、Typed List の方も、今後やっと改善されていくのではないかと思われます。
Numba のメリットはなんといっても、pythonのコードを手軽に高速化できることです。また、Cuda と AMD ROCm にも対応しているので、GPU を使って計算を高速化できるというのも大きなメリットです。一方で、Python と比べると、Python の機能の一部しか使えず、制約が大きいので、不便だと感じる人は多いと思います。今後、List, Dict, Set というコンテナが十分に成熟していないという問題が解消されると Numba はかなり使いやすくなると思います。
PyPy よりも高速になった
AtCoder 等の競技プログラミングでは、PyPy の方がよく使われていますが、AtCoder で list を使った速度の比較をしてみました。Qiita の記事「AtCoderで Python を高速化する Numpy + Numba を使う」で使った ABC129 の問題 D を使って試すと以下のようになりました。Reflected List の場合、PyPy3 より速くなりました。現在の Numba では、Graph の問題で ndarray が使えない場合には困っていたのですが、PyPy より高速であれば、TLE になる心配はほぼないので安心して使えるようになります。
種別 | 実行時間 | 詳細 |
---|---|---|
Python(list) | TLE | 詳細 |
PyPy3 | 422 ms | 詳細 |
Numba (AOT np.ndarray) | 188 ms | 詳細 |
Numba (AOT Reflected List) | 307 ms | 詳細 |
Numba (AOT Typed List) | 841 ms | 詳細 |
なお、Reflected List、Typed List の場合は、Numba 0.52.0 を使用する必要があるため、AtCoder への提出は、自分でコンパイルをしてバイナリを提出することで行っています。