【问题标题】:Scipy NDimage correlate: unbearably slowScipy NDimage 相关:慢得难以忍受
【发布时间】:2015-05-10 03:45:27
【问题描述】:

我正在使用 Python 3.3 运行代码。目标是将 data_3d(一个 1000x1000x1000 布尔 ndarray)与内核(一个 35x35x35 浮点 ndarray)相关联。

然后我执行另一个相关性以对先前的结果求和。因此,我将另一个 1000x1000x1000 布尔 ndarray 与 35x35x35 浮点 ndarray 相关联 - 这与上一步完全相同。

这就是我感到困惑的地方:第一个关联在 70 秒内完成;第二个(看似相同)过程从未完成(即等待了一个多小时......)。

我尝试减小第二个关联的大小(例如,与 5x5x5 数组关联),结果相同。

大概这不是内存问题;在第二个过程中,内存稳定在 18 GB(但我仍有 14 GB 可用...)。

发生了什么事?

这是我的代码:

import numpy as np
from scipy import ndimage as im

第一部分:

t1 = time.time()
# Used to time the process`
# a is a np.ndarray of dtype = bool
a = im.correlate(data_3d, kernel) > threshold 
t2 = time.time()
print(t2 - t1) # About 70 seconds

B 部分:下一部分永远不会完成!

b = im.correlate(a, np.ones((35, 35, 35)))
t3 = time()`

编辑:我找到了解决方案。 A 部分的内核非常稀疏,而 B 部分的内核已完全填充。 Scipy 必须有一些幕后魔法来修改稀疏矩阵的过滤器大小......这使得 A = O(N^3) 和 B = O(N^3 * n^3) 的时间复杂度,其中N = 图像的一维大小,n = 内核的一维大小。

【问题讨论】:

  • 对于这么大的数组,可以通过在傅立叶空间中进行卷积/相关来获得更好的性能,例如。使用scipy.signal.fftconvolve

标签: python memory numpy scipy ndimage


【解决方案1】:

不是相关算子慢,而是你的问题很大。

大小为N 的3D 数组与大小为n 的内核之间的直接相关(或卷积)大致涉及N**3*(2*n**3) 浮点运算。因此,对于一个相当新的 CPU,每个内核 10 GFLOP,这个大小的问题至少需要 2.4 小时,即使不考虑内存复制开销。

其他因素可以加快计算速度,例如多线程,以及是否使用稀疏内核。在后一种情况下,复杂度可以从 O(N**3*n**3) 降低到 O(N**3) ,这可以解释第 1 步和第 2 步之间执行时间的差异(正如问题作者所指出的那样)。

对于第 2 步,使用 scipy.signal.fftconvolve 的基于 FFT 的方法(需要翻转内核以执行互相关)可能会更快,特别是如果问题大小 N 可以等于2 的幂(例如 1024)。

【讨论】:

  • 感谢您的反馈,尤其是关于时间复杂度的反馈。然而,事实证明,答案是由于内核的稀疏性,Scipy 为此优化了它的 ndimage 过滤器。如果您更新答案以反映这一点,我可以接受!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-09
  • 2018-03-17
  • 2023-03-14
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
相关资源
最近更新 更多