【问题标题】:@jit slowing down function@jit 减速功能
【发布时间】:2017-07-21 18:40:42
【问题描述】:

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

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.zeros 还是 array.shape()?

【问题讨论】:

    标签: python jit numba


    【解决方案1】:

    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 会话缓存编译。请参阅numba.pydata.org/numba-doc/latest/user/jit.html#cache 上的文档
    猜你喜欢
    • 2015-05-08
    • 1970-01-01
    • 2022-10-05
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    相关资源
    最近更新 更多