Python @jit减速功能

Python @jit减速功能,python,jit,numba,Python,Jit,Numba,我正在为一个复杂的水库运行问题开发一个优化代码。这部分要求我计算大量潜在解决方案的目标函数。我正在Rosenbrock函数上测试优化器,并试图提高其速度。我在分析代码时注意到,在for循环中计算目标函数是代码瓶颈之一,因此我开发了一种方法,可以对多组决策变量并行执行此操作。我有两个目标函数计算器:一组决策变量的FO和多组决策变量的P_FO。目标函数的计算是我代码中最慢的部分之一,所以我想使用@jit进一步加快速度。我使用@jit测试了这两个函数,发现有@jit的P_FO函数比没有@jit的慢。代

我正在为一个复杂的水库运行问题开发一个优化代码。这部分要求我计算大量潜在解决方案的目标函数。我正在Rosenbrock函数上测试优化器,并试图提高其速度。我在分析代码时注意到,在for循环中计算目标函数是代码瓶颈之一,因此我开发了一种方法,可以对多组决策变量并行执行此操作。我有两个目标函数计算器:一组决策变量的FO和多组决策变量的P_FO。目标函数的计算是我代码中最慢的部分之一,所以我想使用@jit进一步加快速度。我使用@jit测试了这两个函数,发现有@jit的P_FO函数比没有@jit的慢。代码如下:

import time
import numpy as np
from numba import jit 

def FO(X):
    #Rosenbrock function
    ObjV=0
    for i in range(65-1):
        F=100*((X[i+1]-X[i]**2)+(X[i]-1)**2)
        ObjV+=F
    return ObjV

t0=time.time()
X=10+np.zeros(65)
for i in range(5000):
    FO(X)
t1 = time.time()
total = t1-t0
print("time FO="+str(total))

@jit
def FO(X):
    #Rosenbrock function
    ObjV=0
    for i in range(65-1):
        F=100*((X[i+1]-X[i]**2)+(X[i]-1)**2)
        ObjV+=F
    return ObjV

t0=time.time()
X=10+np.zeros(65)
for i in range(5000):
    FO(X)
t1 = time.time()
total = t1-t0
print("time FO with @jit="+str(total))



def P_FO(X):
    ObjV=np.zeros(X.shape[0])  
    for i in range(X.shape[1]-1):
        F=100*((X[:,i+1]-X[:,i]**2)+(X[:,i]-1)**2)
        ObjV+=F
    return ObjV       

t0=time.time()
X=10+np.zeros((65, 5000))
P_FO(X)
t1 = time.time()
total = t1-t0
print("time P_FO="+str(total))


@jit
def P_FO(X):
    ObjV=np.zeros(X.shape[0])  
    for i in range(X.shape[1]-1):
        F=100*((X[:,i+1]-X[:,i]**2)+(X[:,i]-1)**2)
        ObjV+=F
    return ObjV       

t0=time.time()
X=10+np.zeros((65, 5000))
P_FO(X)
t1 = time.time()
total = t1-t0
print("time P_FO with @jit="+str(total))
结果如下:

time FO=0.523999929428
time FO with @jit=0.0720000267029
time P_FO=0.0380001068115
time P_FO with @jit=0.229000091553

有人能告诉我为什么@jit会减慢并行目标函数p_FO的速度吗?这是因为使用了np.zero还是array.shape()?

numba函数是惰性编译的,也就是说,直到第一次调用时才编译,因此计时是一次性编译开销的一部分。如果在运行计时部分之前调用每个函数一次,我会得到:

time FO=0.4103426933288574
time FO with @jit=0.0020008087158203125
time P_FO=0.04154801368713379
time P_FO with @jit=0.004002809524536133

这是有道理的。由于每次模拟我最多运行300次(以及数百万次模拟),它可能仍然会改善结果。好奇的是,如果@jit函数在另一个.py文件中,它是否每次调用时都要编译?或者从我的主函数编译一次会加快其余函数调用的速度吗?不,一旦导入,编译只需要执行一次。更好的是,有一个
cache=True
选项可以跨python会话缓存编译。见