改善Numpy表现

时间:2010-02-04 01:00:43

标签: python math numpy scipy convolution

我想使用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&重新编译numpy ikml。   使用python-cuda。

我想知道是否有人对这些方法有任何经验(通常会获得什么样的收益,如果值得花时间),或者是否有人知道有更好的库来与Numpy进行卷积。< / p>

谢谢!

编辑:

通过使用Numpy在C中重写python循环来加速大约10倍。

5 个答案:

答案 0 :(得分: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多倍。

答案 1 :(得分:2)

对于特定示例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程序员是否足够智能自动执行此操作。 (我有一段时间没有检查过。)

您可能希望进行更有趣的回合,其中可能会或可能不会考虑因子。

答案 2 :(得分:1)

在使用ctypes说C之前,我建议在C中运行一个独立的卷积,以查看限制的位置。
同样对于CUDA,cython,scipy.weave ......

增加了7feb:convolve33带剪辑的8位数据每个点约需20个时钟周期, 每个mem访问2个时钟周期,在我的mac g4 pcc上使用gcc 4.2。您的里程 会有所不同。

一些细微之处:

  • 你关心正确裁剪到0..255吗? np.clip()很慢, cython等不知道。
  • Numpy / scipy可能需要内存大小为A的临时值(因此保持2 * sizeof(A)&lt; cache size)。
    但是,如果您的C代码在内部进行了正在运行的更新,那么这只是mem的一半,而是一种不同的算法。

顺便说一下,Google theano convolve =&gt; “卷积运算应该模仿scipy.signal.convolve2d,但更快!在开发中”

答案 3 :(得分:0)

卷积的典型优化是使用信号的FFT。原因是:真实空间中的卷积是FFT空间中的乘积。计算FFT,产品和结果的iFFT通常比通常的方式更快。<​​/ p>

答案 4 :(得分:0)

截至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
相关问题