Scipy NDimage相关:难以忍受的缓慢

时间:2015-03-09 02:21:30

标签: python memory numpy scipy ndimage

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

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

这里我感到困惑:第一次关联在70秒内完成;第二个(看似相同的)过程并没有完成(即等了一个多小时......)。

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

据推测,这不是一个记忆问题;在第二个过程中,内存高度为18 GB(但我仍然有14 GB可用......)。

发生了什么?

这是我的代码:

import numpy as np
from scipy import ndimage as im

A部分:

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 = 1D图像大小,n = 1D内核大小。

1 个答案:

答案 0 :(得分:4)

并不是相关运算符很慢,而是你的问题非常大。

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

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

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