我想您已经找到了fftconvolve
函数的源代码。通常情况下,对于实数输入,它使用numpy.fft.rfftn
和.irfftn
函数来计算N维变换。由于目标是进行多个1-D变换,因此您可以将fftconvolve
简化为以下形式:
from scipy.signal.signaltools import _next_regular
def fftconvolve_1d(in1, in2):
outlen = in1.shape[-1] + in2.shape[-1] - 1
n = _next_regular(outlen)
tr1 = np.fft.rfft(in1, n)
tr2 = np.fft.rfft(in2, n)
out = np.fft.irfft(tr1 * tr2, n)
return out[..., :outlen].copy()
并计算所需结果:
result = fftconvolve_1d(data, Gauss)
这段代码之所以有效,是因为
numpy.fft.rfft
和
.irfft
(注意名称中缺少
n
)在输入数组的单个轴上进行变换(默认情况下是最后一个轴)。在我的系统上,这比OP代码大约快了40%。
进一步提高速度的方法是使用不同的FFT后端。
首先,
scipy.fftpack
中的函数似乎比它们的Numpy等效函数更快。然而,Scipy变量的输出格式非常笨拙(请参见
文档),这使得很难进行乘法运算。
另一个可能的后端是通过pyFFTW包装器使用FFTW。缺点是变换之前需要缓慢的“规划阶段”,并且输入必须对齐到16字节才能实现最佳性能。这在
pyFFTW教程中解释得非常好。例如,生成的代码可以是:
from scipy.signal.signaltools import _next_regular
import pyfftw
pyfftw.interfaces.cache.enable()
pyfftw.interfaces.cache.set_keepalive_time(1.0)
def fftwconvolve_1d(in1, in2):
outlen = in1.shape[-1] + in2.shape[-1] - 1
n = _next_regular(outlen)
tr1 = pyfftw.interfaces.numpy_fft.rfft(in1, n)
tr2 = pyfftw.interfaces.numpy_fft.rfft(in2, n)
sh = np.broadcast(tr1, tr2).shape
dt = np.common_type(tr1, tr2)
pr = pyfftw.n_byte_align_empty(sh, 16, dt)
np.multiply(tr1, tr2, out=pr)
out = pyfftw.interfaces.numpy_fft.irfft(pr, n)
return out[..., :outlen].copy()
通过对齐输入和缓存“规划”,我看到与OP中的代码相比加速了近3倍。内存对齐可以通过查看Numpy数组的ctypes.data
属性中的内存地址来轻松检查,详情请见。
Gauss
?是一种1-D高斯核吗?如果是,相对于z_depth
的大小是多少? - Curt F.