よく考えたら当たり前だけど, 関数の返り値に引数に含めていない変数が入っていると, 生Pythonでは呼び出したときの名前空間が参照されるがNumbaを使うとコンパイル時に名前空間にあった値が使われる.このため, **「関数の頭にデコレータをつけるだけで計算が速い!!」**とか言って書いて, たとえば関数の引数に関数が入っていると予想外の挙動をすることに.
C=10
def f(X,Y):
I=0.4
return (-C*Y+X-pow(X,3)/3+I)*C
def g(X,Y):
return (X-0.8*C*Y+0.7)/C
こんなふうに系を関数として定義して, 引数には含めない外のパラメータ(ここではC)をふくめて扱うのって結構あるあるだと思うけど, これは思わぬミスの原因.
当たり前だけど普通に計算は通ってエラーは出ないので厄介.
数値積分で系のパラメータを外から変えると積分用のアルゴリズムを一般化できて便利なんだけど, JITを使うときはパラメータも系の引数にして専用に積分アルゴリズムを書かないとだめ.
だめな例
@jit
def jit_testa():
return a
@jit
def jit_testtesta(x):
return x()
def testb():
return b
def testtestb(x):
return x()
bは途中で変えて呼び出しても反映されるけど, aを途中で変えても定義し直さないかぎり最初の値が返ってくる(実験したらわかる). 定義し直すとめちゃくちゃ重くなるのでJITを使う意味がない.解決としては引数にほしい値を入れる.こうすると呼び出し時の名前空間を参照してくれる.