【问题标题】:A faster discrete Laplacian than scipy.ndimage.filters.laplace for small arrays对于小数组,比 scipy.ndimage.filters.laplace 更快的离散拉普拉斯算子
【发布时间】:2016-08-10 08:11:43
【问题描述】:

我的大部分计算时间都花在scipy.ndimage.filters.laplace()

scipynumpy 的主要优点是C/C++ 中的矢量化计算,包装在python 中。 scipy.ndimage.filters.laplace() 派生自 _nd_image.correlate1d,即 部分优化库nd_image.h

有没有更快的方法在 10-100 大小的数组中执行此操作?

定义 拉普拉斯滤波器 - 忽略除法

  • a[i-1] - 2*a[i] + a[i+1]
  • 可选 可以理想地环绕边界a[n-1] - 2*a[n-1] + a[0]n=a.shape[0]

【问题讨论】:

  • " 是纯python" - 你确定吗?对我来说,它看起来只是一些 c++ 函数的包装,在 python 代码中花费的时间可能可以忽略不计。
  • 我刚刚意识到你是完全正确的_nd_image.correlate1dnd_image.h 的一部分,在这种情况下我会稍微修改一下问题
  • 对于解决上述定义的显式方法,有一个很好的概述,其中 fortran 与 f2py 是最佳的不同语言:scipy.github.io/old-wiki/pages/PerformancePython。也许可能需要一种更快的方法来解决拉普拉斯算子,我认为像多重网格方法这样的方法将是最先进的,例如您可以使用github.com/pyamg/pyamg 并将 RHS 设置为零吗?或者也许过滤器/卷积是限制步骤,所以这是不值得的。
  • 见下文 - 我已经找到了解决方案,而无需重新编码任何内容 - 您的方法对于大型数组来说是理想的,但对于 10-100 长度数组 python 会妨碍

标签: python c++ numpy filter


【解决方案1】:

问题的根源在于scipy 出色的错误处理和调试。然而,在用户知道他们在做什么的情况下,它只会提供额外的开销。

下面这段代码去掉scipy后端的所有python杂乱无章,直接访问C++函数得到~6x加速!

laplace == Mine ? True
testing timings...
array size 10
100000 loops, best of 3: 12.7 µs per loop
100000 loops, best of 3: 2.3 µs per loop
array size 100
100000 loops, best of 3: 12.7 µs per loop
100000 loops, best of 3: 2.5 µs per loop
array size 100000
1000 loops, best of 3: 413 µs per loop
1000 loops, best of 3: 404 µs per loop

代码

from scipy import ndimage
from scipy.ndimage import _nd_image
import numpy as np

laplace_filter = np.asarray([1, -2, 1], dtype=np.float64)

def fastLaplaceNd(arr):
    output = np.zeros(arr.shape, 'float64')
    if arr.ndim > 0:
        _nd_image.correlate1d(arr, laplace_filter, 0, output, 1, 0.0, 0)
        if arr.ndim == 1: return output
        for ax in xrange(1, arr.ndim):
            output += _nd_image.correlate1d(arr, laplace_filter, ax, output, 1, 0.0, 0)
    return output

if __name__ == '__main__':
    arr = np.random.random(10)
    test = (ndimage.filters.laplace(arr, mode='wrap') == fastLaplace(arr)).all()
    assert test
    print "laplace == Mine ?", test
    print 'testing timings...'
    print "array size 10"
    %timeit ndimage.filters.laplace(arr, mode='wrap')
    %timeit fastLaplace(arr)
    print 'array size 100'
    arr = np.random.random(100)
    %timeit ndimage.filters.laplace(arr, mode='wrap')
    %timeit fastLaplace(arr)
    print "array size 100000"
    arr = np.random.random(100000)
    %timeit ndimage.filters.laplace(arr, mode='wrap')
    %timeit fastLaplace(arr)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-26
相关资源
最近更新 更多