[英]Improving Numpy Performance
我想使用python提高卷積的性能,並希望能夠對如何最好地提高性能有所了解。
我目前正在使用scipy執行卷積,使用的代碼有點像下面的代碼片段:
import numpy
import scipy
import scipy.signal
import timeit
a=numpy.array ( [ range(1000000) ] )
a.reshape(1000,1000)
filt=numpy.array( [ [ 1, 1, 1 ], [1, -8, 1], [1,1,1] ] )
def convolve():
global a, filt
scipy.signal.convolve2d ( a, filt, mode="same" )
t=timeit.Timer("convolve()", "from __main__ import convolve")
print "%.2f sec/pass" % (10 * t.timeit(number=10)/100)
我正在處理圖像數據,使用灰度(0到255之間的整數值),我目前每個卷積得到大約四分之一秒。 我的想法是做以下其中一項:
使用corepy,最好進行一些優化使用icc和ikml重新編譯numpy。 使用python-cuda。
我想知道是否有人對這些方法有任何經驗(什么樣的增益是典型的,如果值得花時間),或者是否有人知道有更好的庫與Numpy進行卷積。
謝謝!
編輯:
通過使用Numpy在C中重寫python循環來加速大約10倍。
用於進行2d卷積的scipy中的代碼有點混亂且未經優化。 如果你想了解scipy的低級功能,請參見http://svn.scipy.org/svn/scipy/trunk/scipy/signal/firfilter.c 。
如果您想要的只是使用您展示的小型常量內核進行處理,那么這樣的函數可能會起作用:
def specialconvolve(a):
# sorry, you must pad the input yourself
rowconvol = a[1:-1,:] + a[:-2,:] + a[2:,:]
colconvol = rowconvol[:,1:-1] + rowconvol[:,:-2] + rowconvol[:,2:] - 9*a[1:-1,1:-1]
return colconvol
這個函數利用了像上面建議的DarenW那樣的內核的可分離性,以及利用更優化的numpy算術例程。 通過我的測量,它比convolve2d函數快1000多倍。
對於3x3內核的特定示例,我會觀察到
1 1 1
1 -8 1
1 1 1
1 1 1 0 0 0
= 1 1 1 + 0 -9 0
1 1 1 0 0 0
並且其中第一個是可以考慮的 - 它可以通過對每一行進行卷積(111)來進行復雜化,然后對每一列進行卷積。 然后減去原始數據的九倍。 這可能會或可能不會更快,這取決於scipy程序員是否足夠智能自動執行此操作。 (我有一段時間沒有檢查過。)
您可能想要進行更有趣的卷積,其中可能會或可能不會考慮因子。
在使用ctypes說C之前,我建議在C中運行一個獨立的卷積,以查看限制的位置。
同樣對於CUDA,cython,scipy.weave ......
增加了7feb:convolve33帶剪輯的8位數據每個點需要大約20個時鍾周期,每個存儲器訪問需要2個時鍾周期,在我的mac g4 pcc上使用gcc 4.2。 你的里程會有所不同。
一些細微之處:
順便說一句,谷歌theano convolve =>“一個卷積操作,應該模仿scipy.signal.convolve2d,但更快!在開發中”
卷積的典型優化是使用信號的FFT。 原因是:真實空間中的卷積是FFT空間中的乘積。 計算FFT,產品和結果的iFFT通常比通常的方式更快。
截至2018年,似乎SciPy / Numpy組合已經加速了很多。 這是我在筆記本電腦上看到的(戴爾Inspiron 13,i5)。 OpenCV做得最好,但你對模式沒有任何控制。
>>> img= np.random.rand(1000,1000)
>>> kernel = np.ones((3,3), dtype=np.float)/9.0
>>> t1= time.time();dst1 = cv2.filter2D(img,-1,kernel);print(time.time()-t1)
0.0235188007355
>>> t1= time.time();dst2 = signal.correlate(img,kernel,mode='valid',method='fft');print(time.time()-t1)
0.140458106995
>>> t1= time.time();dst3 = signal.convolve2d(img,kernel,mode='valid');print(time.time()-t1)
0.0548939704895
>>> t1= time.time();dst4 = signal.correlate2d(img,kernel,mode='valid');print(time.time()-t1)
0.0518119335175
>>> t1= time.time();dst5 = signal.fftconvolve(img,kernel,mode='valid');print(time.time()-t1)
0.13204407692
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.