Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Numba@jit未能优化简单功能_Python_Numpy_Numba - Fatal编程技术网

Python Numba@jit未能优化简单功能

Python Numba@jit未能优化简单功能,python,numpy,numba,Python,Numpy,Numba,我有一个非常简单的函数,它使用Numpy数组和for循环,但是添加Numba@jit decorator绝对不会加快速度: # @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 = ze

我有一个非常简单的函数,它使用Numpy数组和for循环,但是添加Numba@jit decorator绝对不会加快速度:

# @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
#@jit(float64[:](int32,float64,float64,float64,int32))
@准时制
定义模型(N=200,J=1,T=1e-2,H=0,N=1e6):
β=1/T
s=randn(N,1)>10
s[N-1]=s[0]
mag=零((国际热核实验堆,1))
aux_idx=randint(低=0,高=N,大小=(N_iter,1))
对于arange(国际热核实验堆)的i1:
rnd_idx=辅助_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
如果(δE<0):
s[rnd_idx]=np.逻辑的(s[rnd_idx])
elif(np.exp(-1*beta*delta_E)>=rand()):
s[rnd_idx]=np.逻辑的(s[rnd_idx])
s[N-1]=s[0]
mag[i1]=(s*2-1).sum()*1.0/N
回传杂志
另一方面,MATLAB运行这个程序只需不到0.5秒!
为什么Numba缺少这么基本的东西?

这里是对您的代码的重新编写,在我的机器上运行大约0.4秒:

def ising_model_1d(N=200,J=1,T=1e-2,H=0,n_iter=1e6):
    n_iter = int(n_iter)
    beta = 1/T
    s = randn(N) > 10
    s[N-1] = s[0]

    mag = zeros(n_iter)
    aux_idx =  randint(low=0,high=N,size=n_iter)

    pre_rand = rand(n_iter)

    _ising_jitted(n_iter, aux_idx, s, J, N, H, beta, pre_rand, mag)

    return mag


@jit(nopython=True)
def _ising_jitted(n_iter, aux_idx, s, J, N, H, beta, pre_rand, mag):
    for i1 in range(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
        t = rand()
        if delta_E < 0:
            s[rnd_idx] = not s[rnd_idx]
        elif np.exp(-1*beta*delta_E) >= pre_rand[i1]:
            s[rnd_idx] = not s[rnd_idx]

        s[N-1] = s[0]
        mag[i1] = (s*2-1).sum()*1.0/N
但是
rand()
不能通过
numba
进行优化(至少在
numba
的较旧版本中是这样。在较新的版本中,只要调用
rand
时不带参数,就可以进行优化)。观察结果是,您需要为每一次
n_iter
迭代使用一个随机数。因此,我们只需在包装函数中使用
numpy
创建一个随机数组,然后将该随机数组馈送给jitted函数。获取一个随机数就像索引到这个数组一样简单


最后,有关可由最新版本的编译器优化的
numpy
函数的列表,请参阅。在我重新编写代码的过程中,我积极地删除了对
numpy
函数的调用,以便代码能够处理更多版本的
numba

您正在对循环体中的标量值调用numpy函数。这些函数设计用于在大型阵列上高效运行,而不是在单个值上。numba无法优化这些函数调用。简言之,你需要对代码进行矢量化,而不是JIT编译。@ajcr我认为他们中的一些人实际上可以,比如
rand()
ndarray.sum()
(至少,他们可以在
numba
的最新版本中进行矢量化)。@jme:啊,谢谢,我不知道是这样的。我原以为反复调用
np.logical\u not
(和其他编译函数)会减慢循环速度。我应该更深入地研究一下numba医生。太好了!谢谢你的详细回复。Numba文档在细节上有点稀疏。
elif(np.exp(-1*beta*delta_E) >= rand()):