代码之家  ›  专栏  ›  技术社区  ›  Bear

改善麻木的表现

  •  18
  • Bear  · 技术社区  · 15 年前

    我想使用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。 使用巨蟒Cuda。

    我想知道是否有人对这些方法有任何经验(什么样的收获是典型的,如果值得花时间),或者是否有人知道一个更好的库来执行与numpy的卷积。

    谢谢!

    编辑:

    通过使用numpy在C中重新编写python循环,可以提高大约10倍的速度。

    5 回复  |  直到 7 年前
        1
  •  10
  •   Theran    14 年前

    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算法例程。根据我的测量,它比卷积2d函数快1000多倍。

        2
  •  2
  •   DarenW    15 年前

    对于特定的示例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
    

    其中第一个是可分解的——它可以通过对每行进行(1 1 1)卷积,然后再对每列进行卷积来实现。然后减去原始数据的9倍。这可能会更快,也可能不会更快,这取决于那些神经质的程序员是否足够聪明地自动地做到了这一点。(我有一段时间没有登记。)

    您可能想做更有趣的卷积,其中因子分解可能是可能的,也可能是不可能的。

        3
  •  1
  •   denis    15 年前

    在用ctypes说c之前,我建议在c中运行一个独立的卷积函数,看看限制在哪里。
    同样地,对于库达,赛通,西皮,编织…

    增加了7feb:将33个8位数据与剪裁进行卷积,每个点需要大约20个时钟周期, 在带有GCC 4.2的Mac G4 PCC上,每个MEM访问2个时钟周期。你的里程数 各不相同。

    一些微妙之处:

    • 您是否关心0..255的正确剪裁?clip()很慢, 赛通等不知道。
    • numpy/scipy可能需要内存来存储a大小的temps(因此请保留2*size of(a)<缓存大小)。
      不过,如果您的C代码就地进行了一次运行更新,这是MEM的一半,但却是一个不同的算法。

    顺便说一下,谷歌 theano 卷积=& “一个卷积运算应该模仿scipy.signal.卷积2d,但速度更快!发展中的“

        4
  •  0
  •   PierreBdR    15 年前

    卷积的一个典型优化是使用信号的FFT。其原因是:实空间的卷积是FFT空间的积。与通常的卷积方法相比,计算结果的fft、积和ifft通常更快。

        5
  •  0
  •   Ruthvik Vaila    7 年前

    截至2018年,似乎scipy/numpy组合已经加速了很多。这是我在笔记本电脑上看到的(Dell 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