【发布时间】:2014-12-13 08:21:27
【问题描述】:
我使用 NumPy 的 fft 函数编写了一个脚本,在其中我将输入数组填充到最接近的 2 次幂以获得更快的 FFT。
在分析代码后,我发现 FFT 调用花费的时间最长,所以我摆弄了参数,发现如果我 没有 填充输入数组,FFT 就会运行快几倍。
这里有一个最小的例子来说明我在说什么(我在 IPython 中运行了这个并使用了 %timeit 魔法来计时执行)。
x = np.arange(-4.*np.pi, 4.*np.pi, 1000)
dat1 = np.sin(x)
计时结果:
%timeit np.fft.fft(dat1)
100000 loops, best of 3: 12.3 µs per loop
%timeit np.fft.fft(dat1, n=1024)
10000 loops, best of 3: 61.5 µs per loop
将数组填充到 2 的幂会导致非常严重的减速。
即使我创建了一个包含素数元素的数组(因此理论上最慢的 FFT)
x2 = np.arange(-4.*np.pi, 4.*np.pi, 1009)
dat2 = np.sin(x2)
运行所需的时间仍然没有太大变化!
%timeit np.fft.fft(dat2)
100000 loops, best of 3: 12.2 µs per loop
我原以为填充数组将是一次操作,然后计算 FFT 应该更快。 我错过了什么吗?
编辑:我应该使用np.linspace 而不是np.arange。下面是使用linspace的计时结果
In [2]: import numpy as np
In [3]: x = np.linspace(-4*np.pi, 4*np.pi, 1000)
In [4]: x2 = np.linspace(-4*np.pi, 4*np.pi, 1024)
In [5]: dat1 = np.sin(x)
In [6]: dat2 = np.sin(x2)
In [7]: %timeit np.fft.fft(dat1)
10000 loops, best of 3: 55.1 µs per loop
In [8]: %timeit np.fft.fft(dat2)
10000 loops, best of 3: 49.4 µs per loop
In [9]: %timeit np.fft.fft(dat1, n=1024)
10000 loops, best of 3: 64.9 µs per loop
填充仍然会导致减速。这可能是本地问题吗?即,由于我的 NumPy 设置中的一些怪癖,它的行为方式是这样的?
【问题讨论】:
-
用更大的数组(例如 32768 附近)尝试相同的测试。
-
@WarrenWeckesser - 当我将其填充到 2 的幂(即 32768)时,性能现在有了 巨大 的提升。所以我猜在性能提升开始显现的地方有一个截止点。
-
对于小型阵列,开销(额外复制,其他?)淹没了使用 2 的幂的性能增益。使用
n=1024的开销数量令人惊讶,但我没有看过进入代码查找原因。