2017-07-20 27 views
1

我正在爲一個複雜的水庫運行問題開發優化代碼。其中一部分要求我計算大量潛在解決方案的目標函數。我正在測試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.zeros還是array.shape()?

回答

3

numba函數是懶惰地編譯的,也就是說,直到第一次調用,所以你的計時是捕獲一次性編譯開銷。如果我在運行計時部分之前調用每個函數一次,我會得到:

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

這很有道理。由於我將每次模擬運行300次(以及數百萬次模擬),它可能仍會改善結果。 – Kingle

+0

只是好奇 - 如果@jit函數在另一個.py文件中,它是否每次調用它時都要編譯?或者從我的主函數編譯一次,加速其餘函數調用? – Kingle

+2

不,一旦導入,編譯只需要完成一次。更好的是,有一個'cache = True'選項可以緩存python會話中的編譯。請參閱http://numba.pydata.org/numba-doc/latest/user/jit.html#cache上的文檔 – chrisb