我正在嘗試優化以下迴圈:def numpy(nx, nz, c, rho):
for ix in range(2, nx-3):
for iz in range(2, nz-3):
a[ix, iz] = sum(c*rho[ix-1:ix+3, iz])
b[ix, iz] = sum(c*rho[ix-2:ix+2, iz])
return a, b
我嘗試了不同的解決方案,發現使用numba計算產品總和可以獲得更好的效能:
^$這導致time numpy : 4.1595
time numba1 : 0.6993
time numba2 : 1.0135
使用numba版本的sum函式(sum\u opt)效能非常好。但是我想知道為什麼numba版本的雙迴圈函式(numba2)會導致執行速度變慢。我試圖使用jit而不是autojit,指定引數型別,但情況更糟。在
我還注意到,先在最小的迴圈上迴圈比先在最大的迴圈上迴圈慢。有什麼解釋嗎?在
不管怎樣,我確信這個雙迴圈函式可以改進很多向量化問題(比如this)或使用其他方法(map?)但我對這些方法有點困惑。在
在我**的其他部分,我使用numba和numpy切片方法來替換所有顯式迴圈,但是在這個特殊的例子中,我不知道如何設定它。在
有什麼想法嗎?在
編輯import numpy as np
from scipy import signal
import time
@nb.jit(['float64(float64[:], float64[:])'], nopython=true)
def sum_opt(arr1, arr2):
s = arr1[0]*arr2[0]
for i in xrange(1, len(arr1)):
s+=arr1[i]*arr2[i]
return s
@nb.autojit
def numba1(nx, nz, c, rho, a, b):
for ix in range(2, nx-3):
for iz in range(2, nz-3):
a[ix, iz] = sum_opt(c, rho[ix-1:ix+3, iz])
b[ix, iz] = sum_opt(c, rho[ix-2:ix+2, iz])
return a, b
@nb.jit(nopython=true)
def numba2(nx, nz, c, rho, a, b):
for ix in range(2, nx-3):
for iz in range(2, nz-3):
a[ix, iz] = sum_opt(c, rho[ix-1:ix+3, iz])
b[ix, iz] = sum_opt(c, rho[ix-2:ix+2, iz])
return a, b
@nb.jit(['float64[:,:](int16, int16, float64[:], float64[:,:], float64[:,:])'], nopython=true)
def numba3a(nx, nz, c, rho, a):
for ix in range(2, nx-3):
for iz in range(2, nz-3):
a[ix, iz] = sum_opt(c, rho[ix-1:ix+3, iz])
return a
@nb.jit(['float64[:,:](int16, int16, float64[:], float64[:,:], float64[:,:])'], nopython=true)
def numba3b(nx, nz, c, rho, b):
for ix in range(2, nx-3):
for iz in range(2, nz-3):
b[ix, iz] = sum_opt(c, rho[ix-2:ix+2, iz])
return b
def convol(nx, nz, c, aa, bb):
s1 = rho[1:nx-1,2:nz-3]
s2 = rho[0:nx-2,2:nz-3]
kernel = c[:,none][::-1]
aa[2:nx-3,2:nz-3] = signal.convolve2d(s1, kernel, boundary='symm', mode='valid')
bb[2:nx-3,2:nz-3] = signal.convolve2d(s2, kernel, boundary='symm', mode='valid')
return aa, bb
nx = 1024
nz = 256
rho = np.random.rand(nx, nz)
c = np.random.rand(4)
a = np.zeros((nx, nz))
b = np.zeros((nx, nz))
ti = time.clock()
for i in range(1000):
a, b = numba1(nx, nz, c, rho, a, b)
print 'time numba1 : ' + `round(time.clock() - ti, 4)`
ti = time.clock()
for i in range(1000):
a, b = numba2(nx, nz, c, rho, a, b)
print 'time numba2 : ' + `round(time.clock() - ti, 4)`
ti = time.clock()
for i in range(1000):
a = numba3a(nx, nz, c, rho, a)
b = numba3b(nx, nz, c, rho, b)
print 'time numba3 : ' + `round(time.clock() - ti, 4)`
ti = time.clock()
for i in range(1000):
a, b = convol(nx, nz, c, a, b)
print 'time convol : ' + `round(time.clock() - ti, 4)`
您的解決方案非常優雅,但我必須在**中大量使用此函式。因此,對於1000次迭代,這將導致time numba1 : 3.2487
time numba2 : 3.7012
time numba3 : 3.2088
time convol : 22.7696
autojit和{}非常接近。
但是,在使用jit時,指定所有引數型別似乎很重要。在
當函式有多個輸出時,我不知道是否有方法在jit修飾符中指定引數型別。有人嗎?在
現在我沒有找到其他的解決辦法,除了使用numba。歡迎有新想法!在
python優化迴圈 Python 優化迴圈
我希望優化一些由兩個巢狀迴圈組成的 python 我對numpy並不那麼熟悉,但據我所知,它應該能夠幫助我提高這項任務的效率.下面是我編寫的測試 它反映了實際 中發生的情況.目前使用numpy範圍和迭代器比通常的python更慢.我究竟做錯了什麼?這個問題的最佳解決方案是什麼?謝謝你的幫助!impo...
Python之迴圈優化
儘量減少迴圈內部不必要的計算 巢狀迴圈中,儘量減少內層迴圈的計算,盡可能向外提。區域性變數查詢較快,盡量使用區域性變數 import time start time.time for i in range 10000 lib1 for x in range 10000 1000 x 1000 end...
python效率怎麼樣 如何優化python的效率
優化python的效率的方法 1 優化演算法時間複雜度 2 減少冗餘資料 3 合理使用copy與deepcopy 4 使用dict或set查詢元素 5 合理使用生成器 generator 和yield。優化方法 1 優化演算法時間複雜度 演算法的時間複雜度對程式的執行效率影響最大,在python中可...