内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用
我希望使用python来改进卷积的性能,并希望能够了解如何最好地改进性能。
我目前正在使用cip执行卷积,使用的代码有点像下面的代码片段:
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卷积的cipy中的代码有点混乱,而且没有优化。如果您只想使用一个小的、常量内核来处理,就像您展示的那样,这样的函数可能会工作:
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算术例程。根据我的测量,它比卷积2d函数快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
其中第一个是可分解的,它可以通过每一行的卷积(11,1)来卷积,然后再对每一列进行卷积。然后减去9倍的原始数据。这可能会更快,也可能不会更快。