奇怪的numpy fft表现

时间:2014-01-16 11:52:43

标签: python numpy fft

在测试期间,我注意到一些奇怪的事情。

我正在对很多向量进行FFT,并且有时会出现numpy FFT函数崩溃的情况。

我简要地调试了这个,发现一些矢量长度触发了这种行为。

事件中,我保持一个脚本运行,令我惊讶的是,它没有崩溃,只是花了一点时间。

有没有人知道发生了什么,以及如何反击这一点。我已经看到了许多不同的FFT大小,下面只是一个例子。

import numpy as np    
import time

a = np.zeros(166400)
start = time.time()
audio_fft = np.fft.fft(a,len(a))                          
print "it took %fs"%(time.time() -start)

a = np.zeros(165039)
start = time.time()
audio_fft = np.fft.fft(a,len(a))                          
print "it took %fs"%(time.time() -start)

a = np.zeros(165038)
start = time.time()
audio_fft = np.fft.fft(a,len(a))                          
print "it took %fs"%(time.time() -start)

a = np.zeros(165036)
start = time.time()
audio_fft = np.fft.fft(a,len(a))                          
print "it took %fs"%(time.time() -start)

a = np.zeros(165035)
start = time.time()
audio_fft = np.fft.fft(a,len(a))                          
print "it took %fs"%(time.time() -start)

a = np.zeros(165034)
start = time.time()
audio_fft = np.fft.fft(a,len(a))                          
print "it took %fs"%(time.time() -start)

a = np.zeros(165037)
start = time.time()
audio_fft = np.fft.fft(a,len(a))                          
print "it took %fs"%(time.time() -start)

print "done"

输出:

c:\Users\sol_sf\Desktop\math>fftTest.py
it took 0.029000s
it took 0.101000s
it took 0.176000s
it took 0.220000s
it took 0.671000s
it took 0.065000s
it took 369.132000s
done

c:\Users\sol_sf\Desktop\math>

3 个答案:

答案 0 :(得分:11)

分割和征服FFT算法(例如Cooley-Tukey)在输入长度越多的因素下效果越好。 2的功率特别好,而素数(如165037)需要交替的,较慢的实现。如果您可以将输入填充到2的幂长度,则可以大幅加速慢速FFT。

答案 1 :(得分:2)

我认为阵列的2次填充有几个缺点:

  1. 如果将阵列切换到2长度,则会产生大数据的大数据
  2. 如果用零填充数组,它将产生所谓的"边缘效应"
  3. 我在这个topic中发现fft性能取决于数组大小素数因子分解。如果数组长度为素数,则会导致计算时间过长。因此,我建议使用以下代码来减少数组长度,以寻找最佳的分解。

    from sympy.ntheory import factorint
    
    FACTOR_LIMIT = 100
    
    def bestFFTlength(n):
        while max(factorint(n)) >= FACTOR_LIMIT:
            n -= 1
        return n
    
    a = np.zeros(166400)
    audio_fft = np.fft.fft(a,bestFFTlength(len(a)))
    

答案 2 :(得分:0)

解决此问题的一种简单方法(其他答案中未提及)是使用scipy.fftpack.next_fast_len填充数组。给定目标长度,它会为您提供下一个长度>目标,该目标由2、3和5组成。

正如其他答案所指出的那样,当数组的长度为质数时,FFT表现最差。它的效率随着主要因子数量的增加(2、3、5等)而增加。