应用numpy FFT操作时出现数组数据布局(步长)意外变化问题咨询
numpy FFT输出数组步长异常的成因说明
核心原因
numpy 1.17版本之后,官方将np.fft模块的底层实现从旧的FFTPACK替换为了pocketFFT库,该库的核心优化点之一就是优先保障计算过程的内存访问效率:
- 你构造的输入数组是标准C顺序(行优先)的连续数组,
strides=(400, 8)说明行方向是慢变轴、列方向是快变轴 - 当你指定沿
axis=0(行方向,慢变轴)做FFT时,pocketFFT为了让每次参与1D FFT计算的数列在内存中尽可能连续,会自动调整输出数组的内存布局,计算完成后输出的数组为非连续布局,因此会出现和输入shape一致但strides完全不同的情况 scipy.fftpack.fft的底层仍然沿用传统FFTPACK实现,该实现不会做这类内存布局优化,无论输入布局如何都会输出和输入内存布局一致的结果,因此strides符合预期。
补充说明
该现象是pocketFFT的性能优化策略,不属于numpy的bug,也不会影响计算结果的数值正确性:逻辑上通过索引访问
output数组得到的结果和scipy FFT的输出完全一致,差异仅存在于底层内存存储顺序。
替代解决方案
除了切换到scipy的fftpack之外,你也可以通过以下方式得到符合预期布局的数组:
- 对FFT输出做连续内存转换:
output = np.ascontiguousarray(np.fft.fft(input, axis=0)),转换开销极低,不会影响整体计算效率 - 若你使用的numpy版本 >=1.25,也可以在调用
np.fft.fft时指定out参数为预先分配好的、符合你需要布局的数组,直接写入结果即可。
内容的提问来源于stack exchange,提问作者Andreas Hadjigeorgiou
相关产品推荐
相关产品推荐

