_trac用户koehler于2009-10-19发行的原始票证http://projects.scipy.org/numpy/ticket/1266 ,已分配给未知帐户。
尽管numpy.fft.fft的文档指出:
“这对于2的n次方而言是最有效的。它还为不同大小的fft存储了工作内存的高速缓存,因此,如果您多次使用不同的n进行多次调用,则理论上可能会遇到内存问题。” ,我认为在fft运行时报告这种奇怪情况可能很重要。
根据数组长度的不同,fft运行时的确会极端变化:
[ipython shell, from numpy import *]
In [1]: %time fft.fft(zeros(119516))
CPU times: user 22.83 s, sys: 0.39 s, total: 23.23 s
Wall time: 23.53 s
In [3]: %time fft.fft(zeros(119517))
CPU times: user 36.33 s, sys: 0.08 s, total: 36.40 s
Wall time: 36.51 s
In [5]: %time fft.fft(zeros(119518))
CPU times: user 4.88 s, sys: 0.08 s, total: 4.96 s
Wall time: 5.02 s
In [7]: %time fft.fft(zeros(119519))
CPU times: user 0.45 s, sys: 0.00 s, total: 0.45 s
Wall time: 0.45 s
In [9]: %time fft.fft(zeros(119515))
CPU times: user 0.07 s, sys: 0.00 s, total: 0.08 s
Wall time: 0.08 s
In [11]: %time fft.fft(zeros(119514))
CPU times: user 15.84 s, sys: 0.06 s, total: 15.90 s
Wall time: 15.95 s
In [13]: %time fft.fft(zeros(119513))
CPU times: user 272.75 s, sys: 1.03 s, total: 273.78 s
Wall time: 275.63 s
_ @ endolith发表于2009-11-20_
_ @ rgommers写于2011-03-01_
里程碑由@mwiebe于2011-03-25更改为Unscheduled
在此过程中,建议对小素数进行填充
https://github.com/scipy/scipy/pull/3144
具有获得更好的填充大小的功能可能是numpys fftpack中的有用实用程序
是的,代替m = 2 ** nextpow2(2 * n - 1)
可以更快使用next_regular
功能
我还使用pymbar的detect_equilibration函数遇到了这个问题,该函数在许多越来越短的数组上通过
np.fft.fftpack._fft_cache.clear()
确保内存需求不会危险地增长。 但是,这似乎不是理想的解决方案。 最好使用kwarg(例如“ memsafe = True”)和/或无需明确引用全局变量即可手动清除缓存的函数。
@juliantaylor填充不适用于纯FFT,对吗? 只是为了卷积/相关?
@rgommers Bluestein算法确实加快了素数大小的FFT,如https://github.com/scipy/scipy/issues/4288中所述,但是需要对复杂的pre进行预计算,并且在保留在内存中发出声,并在数据块上重复使用它。 所以我不确定这是否对numpy有用,也许只是推迟到scipy.fftpack.czt用于此应用程序?
无论如何,我认为可以将其作为https://github.com/numpy/numpy/issues/1177的副本关闭? 除非像Rader的算法这样的东西比Bluestein的算法更好?
和@smcantab的问题不同?
@endolith这是很久以前的:)但是,是的,现在我再次看它,这似乎是一个不同的问题。 我报告的问题可能仍然很重要,因此我必须实施在pymbar中建议的解决方法才能起作用。
仅供参考,我在一个音频会议上遇到了一个人,向我展示了这个例子。 它易于复制且极端。
%time np.fft.fft( np.random.randn(100000) )
Wall time: 16 ms
Out[16]:
array([ 196.58599022 +0.j , -88.38483360 +89.2507627j ,
-166.72250316+339.27161306j, ..., 12.22959535 -64.01621313j,
-166.72250316-339.27161306j, -88.38483360 -89.2507627j ])
%time np.fft.fft( np.random.randn(100003) )
Wall time: 1min 42s
Out[17]:
array([ 13.36160617 +0.j , -314.86472577-340.44686425j,
-258.36716707-170.43805382j, ..., -21.18014704+441.3618185j ,
-258.36716707+170.43805382j, -314.86472577+340.44686425j])
长度1e6的fft:16毫秒
长度为1e6 + 3的英尺英尺:1分钟和42秒
功能,不是错误。 当大小因子是数字2、3、4、5的乘积时,FFTPACK才是“快速”的。长期以来,人们一直希望对较大的素数使用更快的算法,但是尚未实现。 请注意100003是质数。
我不会称其为“功能”,但这是正常现象,而不是错误。 :)
https://github.com/scipy/scipy/issues/4288具有Bluestein的算法,但是它需要对复杂的线性调频器进行预计算,因此需要进行一些测试,以了解在哪些最佳大小上值得。
有趣。 我知道的主要事情是,Julia和Matlab的默认fft实现没有此行为。 我很好奇Julia的实现是如何避免这种行为的。
朱莉娅和Matlab呼叫FFTW,由于其许可证,我们无法执行此操作。
请注意,FFTW有Python绑定。 pyFFTW似乎是最新的。 如果需要考虑FFT速度,那可能是可行的方法。 FFTPACK当时是一个很好的实现,但是代码和硬件已经发展了。
@charris我非常感谢您提供的信息,这很不幸,但是对于许可证很有道理。
@standarddeviant您也可以在numpy / scipy上方对pyfftw进行猴子补丁,以使其使用FFTW
这应该在numpy 1.17中修复。
谢谢@mreineck ,关闭
最有用的评论
这应该在numpy 1.17中修复。