任务:大型阵列的快速实对复FFT计算。
阵列a
的形状是(103430 x 1 x 100 x 900),其中尺寸是(时间,虚拟暗淡,经度,纬度),所以让我们说(~100000 x 1) x 100 x 900)。应在轴0,2,3上计算FFT。
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 documentation,并尝试将auto_align_input
和auto_contiguous
选项设置为False,将overwrite_input
设置为True,但未成功。我也尝试自己创建FFTW对象并使用params。
MATLAB,也使用FFTW,在几秒钟内执行(100000,1,100,900)任务,最大内存消耗是必要的~40%。显然,数组的中间副本(运行pyfftw时使用额外内存的可能原因)从算法的角度来看是不必要的,正如MATLAB示例所示。
问题:有没有办法在pyfftw中强制执行绝对没有额外的内存消耗?如果是这样,怎么样?哪个参数?
P.S:两种可能的解决方法是
但是,我想避免这些。应该有一种方法可以执行单个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()
事实证明,正在使用的内存实际上是内部run_fftw()的+ b +复杂广播副本。如果在定义run_fftw之前已经广播复杂,或者在创建run_fftw之后删除了,则可以将其缩小为复杂广播a + b的内存。
由于问题现在是准解决的(感谢@HenryGomersall),现在唯一的好奇心问题是,是否存在可通过fftn调用的真实到复杂的方案,它可以提供所有频率,包含负数,以及不会在内部广播输入数组到复杂。
我理解虽然在这种情况下可以使用rfftn。但这会抛弃(冗余)负频率。