亲爱的stackoverflow社区!
今天我发现在高端集群架构中,2个立方体的元素乘法与尺寸1921 x 512 x 512需要~27 s。这太长了,因为我必须对当前实现中的功率谱的方位角平均进行至少256次这样的计算。我发现性能缓慢主要是由于不同的步幅结构(一种情况下为C而另一种情况下为FORTRAN)。两个数组中的一个是新生成的布尔网格(C顺序),另一个(FORTRAN顺序)来自输入网格(C顺序)的3D numpy.fft.fftn()傅立叶变换。 numpy.fft.fftn()改变了如何防止除了反转轴之外的步幅和想法的任何原因(这只是一种解决方法)?有了类似的进步(FT网格的ndarray.copy()),可以实现~4s,这是一个巨大的进步。
因此问题如下:
考虑数组:
ran = np.random.rand(1921, 512, 512)
ran.strides
(2097152, 4096, 8)
a = np.fft.fftn(ran)
a.strides
(16, 30736, 15736832)
我们可以看到步幅结构不同。如何防止这种情况(不使用= np.fft.fftn(run,axes =(1,0)))?还有其他任何可能影响步幅结构的numpy数组例程吗?在这些情况下可以做些什么?
非常感谢有用的建议!
答案 0 :(得分:2)
您可以使用scipy.fftpack.fftn(也可以使用hpaulj),而不是numpy.fft.fftn,看起来它正在做你想要的。但是表现稍差:
$location.search('');
$location.search('parameter', null);
答案 1 :(得分:1)
为什么numpy.fft.fftn()改变了除了反转轴之外如何防止它的步伐和想法的任何原因(这只是一种解决方法)?
计算阵列的多维度DFT包括在每个维度上连续计算1D DTF。有两种策略:
numpy.fft
采用的策略。在计算结束时,数组已被转置。为避免不必要的计算,返回转置数组并修改步幅。fftw
的策略,可以通过界面pyfftw
获得。因此,输出数组具有与输入数组相同的步幅。执行here和there或there的时间numpy.fftn
和pyfftw.numpy.fftn
将告诉您FFTW是否真的是西方最快的傅里叶变换...
要检查numpy是否使用第一个策略,请查看numpy/fft/fftpack.py
。在第81-85行,调用work_function(a, wsave)
(即来自FFTPACK的fftpack.cfftf
,有关there的参数的调用)包含在执行转置的numpy.swapaxes()
调用之间
scipy.fftpack.fftn
似乎没有改变步伐......但是,似乎它利用了第一种策略。 scipy.fftpack.fftn()
根据scipy.fftpack.zfftnd()
调用zfft()
来调用zfftf1
,flatten()
似乎无法处理跨步DFT。此外,zfftnd()
多次调用执行转置的函数FFTW-MPI uses the first strategy。
另一个例子:对于并行分布式内存多维度DFT,functions to transpose the array以避免在1D DTF期间进程之间的任何MPI通信。当然,search the github repository of numpy for swapaxes
并不遥远,并且在此过程中涉及很多MPI通信。
还有其他任何可能影响步幅结构的numpy数组例程吗?在这些情况下可以做些什么?
你可以{{3}}:这个功能只使用了几次。因此,在我看来,这是一个大踏步的变化"特别是fft.fftn()
,大多数numpy函数保持步幅不变。
最后,"改变步伐"是第一个战略的一个特征,没有办法阻止这一点。唯一的解决方法是在计算结束时交换轴,这是昂贵的。但是你可以依赖pyfftw
,因为fftw
以非常有效的方式实现了第二个策略。 DFT计算会更快,如果不同数组的步幅变得一致,后续计算也会更快。