几个月前,我发现使用FFT算法以最快的方式计算卷积(使用FFTW库更多)
使用以下代码我有争议的结果。
进口
from scipy import fftpack
from numba import jit
使用FFT进行卷积:
def conv_fft(X, R):
n = len(X)
a = fftpack.fft(X)
b = fftpack.fft(R)
c = a * b
e = fftpack.ifft(c)
result = e[n]
return result
使用公式进行卷积:
@jit(cache=True)
def conv(X, R):
n = len(X)
result = complex_type(0)
for i in range(n+1):
result += X[n-i] * R[i]
return result
这是一个复杂过程中的关键功能,只有使用一个版本或另一个版本才会产生差异。
no FFT with FFT increment
Test1 0.028761 0.034139 0.0053780
Test2 0.098565 0.103180 0.0046150
** test2计算每次测试的更多卷积。*
测试显示带有FFT的代码较慢,我无法理解为什么因为fftpack显然调用了“西部最快”的FFTW库 ...
感谢任何指导。
我的结论是,numba JIT编译的速度令人难以置信。
答案 0 :(得分:2)
您只返回卷积的单个值(第n个),而不是整个数组。使用FFT,您总是计算所有值,而在您的转换函数中,您只计算您所追求的值。复杂性方面,FFT为O(N * log(N)),您的conv实现为O(N)。如果你要实现一个返回完整卷积的朴素转换函数,它将是O(N ^ 2)。 所以,如果你想要完整的复杂阵列,你最好的选择就是采用FFT方式。如果您只想要第n个值,那么您的方法最好是复杂的。
答案 1 :(得分:0)
您应该能够使用这种类型的语法来创建更少的临时数组,这样可以加快它的速度。
def conv_fft(X, R):
fftpack.fft(X, overwrite_x=True)
b = fftpack.fft(R)
X *= b
fftpack.ifft(X, overwrite_x=True)
return X