【发布时间】:2015-11-18 21:22:13
【问题描述】:
我有一个非常简单的函数,它使用 Numpy 数组和 for 循环,但是添加 Numba @jit 装饰器绝对不会加快速度:
# @jit(float64[:](int32,float64,float64,float64,int32))
@jit
def Ising_model_1D(N=200,J=1,T=1e-2,H=0,n_iter=1e6):
beta = 1/T
s = randn(N,1) > 10
s[N-1] = s[0]
mag = zeros((n_iter,1))
aux_idx = randint(low=0,high=N,size=(n_iter,1))
for i1 in arange(n_iter):
rnd_idx = aux_idx[i1]
s_1 = s[rnd_idx]*2 - 1
s_2 = s[(rnd_idx+1)%(N)]*2 - 1
s_3 = s[(rnd_idx-1)%(N)]*2 - 1
delta_E = 2.0*J*(s_2+s_3)*s_1 + 2.0*H*s_1
if(delta_E < 0):
s[rnd_idx] = np.logical_not(s[rnd_idx])
elif(np.exp(-1*beta*delta_E) >= rand()):
s[rnd_idx] = np.logical_not(s[rnd_idx])
s[N-1] = s[0]
mag[i1] = (s*2-1).sum()*1.0/N
return mag
另一方面,MATLAB 的运行时间不到 0.5 秒! 为什么 Numba 缺少一些如此基本的东西?
【问题讨论】:
-
您正在循环体中的标量值上调用 NumPy 函数。这些函数旨在有效地处理大型数组,而不是单个值。 numba 无法优化这些函数调用。简而言之,您需要对代码进行矢量化,而不是 JIT 编译。
-
@ajcr 我认为其中一些实际上可以,例如
rand()和ndarray.sum()(至少在最新版本的numba中可以)。 -
@jme:啊,谢谢,我不知道是这样的。我曾认为反复调用
np.logical_not(和其他编译函数)会减慢循环速度。我应该更深入地研究 numba 文档。