2

任务:大型阵列的快速实数到复数 FFT 计算。

数组的形状a是(103430 x 1 x 100 x 900),其中尺寸是(时间,虚拟暗淡,经度,纬度),所以我们说(~100000 x 1 x 100 x 900)。FFT 应在轴 0、2、3 上计算。

Numpy.fft.fftn(a,axes=(0,2,3))耗时太长(约 6 小时),因此我想使用pyfftw。我尝试使用pyfftw.interfaces.numpy_fft.fftn(a,axes=(0,2,3)).

问题:输入数组的内存消耗大约相当于。我们机器 RAM 的 13%,因此包括输出数组,它应该变成 ~ 40%(输出很复杂)。然而,在计算过程中,内存使用率上升到接近 100%,直到命令退出并在PyCharm中出现内存错误。

我创建了一个较小版本的随机数数组 (10000,1,100,900),内存消耗约为 1.3%。如果仅在轴 3 上执行 FFT,则内存使用量暂时上升到 ~10.6 %,如果在前面提到的轴 0、2、3 上执行,内存使用率会暂时上升到 ~ 13 %。

我假设中间数组副本会导致这种高内存使用。我搜索了pyfftw 文档并尝试将auto_align_inputandauto_contiguous选项设置为 False 和overwrite_inputTrue,但没有成功。我还尝试自己创建 FFTW 对象并使用参数。

同样使用 FFTW 的 MATLAB 在几秒钟内执行 (100000,1,100,900) 的任务,最大内存消耗是必要的 ~40%。显然,从算法的角度来看,数组的中间副本(运行 pyfftw 时使用额外内存的可能原因)是不必要的,如 MATLAB 示例所示。

问题:有没有办法在 pyfftw 中强制绝对没有额外的内存消耗?如果是这样,怎么做?哪些参数?


PS:两种可能的解决方法是

  1. 将数组从 python 保存到 fit,将其加载到 MATLAB,执行 FFT,将其从 MATLAB 保存到 fit,然后将其加载回 python
  2. 通过 for 循环进行重复的单维 FFT;内存开销将不相关,结果可以作为循环的一部分插入到输出数组中

但是,我想避免这些。应该有一种方法可以执行单个 3D-FFT,而不会消耗机器的整个 RAM (512 GB)。


更新:我运行了以下命令:

a = np.random.rand(10000,1,100,900)
run_fftw = pyfftw.builders.fftn(a, axes=(3,), auto_contiguous=False, auto_align_input=False, avoid_copy=True)
b = run_fftw()

事实证明,正在使用的内存实际上是 a + b + 内部 run_fftw() 的复杂广播副本。如果在定义 run_fftw 之前已经将 a 广播到复合体,或者在创建 run_fftw 之后删除 a ,这可以减少到复合广播 a + b 的内存。

由于这个问题现在已经准解决了(感谢@HenryGomersall),现在唯一好奇的问题是是否有一个可通过 fftn 调用的从实数到复数的方案,它提供所有频率,包括负频率,并且不在内部广播输入数组复杂。

我明白虽然在这种情况下可以使用 rfftn 。不过,这会丢弃(冗余的)负频率。

4

0 回答 0