在Matlab中使用fft进行卷积的执行时间

时间:2018-10-09 21:03:15

标签: matlab fft convolution

我有两个信号x1和x2。我试图一次直接使用CONV(x1,X2)进行一次卷积,一次使用fft和ifft进行卷积,并比较两个操作的执行时间。

我不知道为什么fft的执行时间不会比使用conv快。

n = 0: 2^15 ;
x1(n+1) = (0.25).^n ;
x2(n+1) = 1;

tic
Time_Convolution = conv(x1,x2);
toc


Padding = (length(x1)+ length(x2) - 1)-length(x1) ;
x1_before_fft = [ x1 zeros(1, Padding) ];
x2_before_fft = [ x2 zeros(1,  Padding)];

tic
Convolution = ifft(fft( x1_before_fft).*fft(x2_before_fft));   
toc

这是输出

经过的时间为0.010414秒。   经过的时间是0.017308秒。

1 个答案:

答案 0 :(得分:1)

这里的关键是输入信号之一主要包含零,因为您失去了将精度从0.25提高到较大幂的舍入精度。

 >> nnz(x1) / numel(x1)
 ans =
     0.0164

少于2%的第一个输入为非零。卷积的直接实现可以利用它来摆脱很多对结果没有任何贡献的操作。但是,基于FFT的卷积将始终执行几乎相同的工作量,而与所涉及系数的大小无关。

当您将这些系数设为非零时,情况就大不相同了。在我的机器上,我看到:

 >> tic; for k = 1:100, conv(x1,x2); end, toc
 Elapsed time is 0.291373 seconds.
 >> x1 = x1 + eps;
 >> tic; for k = 1:100, conv(x1,x2); end, toc
 Elapsed time is 3.937819 seconds.

要注意的另一件事是,您正在使用不幸的FFT大小选择来通过FFT进行卷积。任何使用至少length(x1)+length(x2)-1个点的变换都可以解决问题(如果您有较大的变换,则只需在末尾修剪掉所有额外的系数),因此最好选择一个素数较小的变换。但是,在这种情况下,length(x1)+length(x2)-1本身就是素数,因此这是最糟糕的选择。只需将长度增加1:即可看到不同之处。

 >> N = length(x1)+length(x2)-1;  % Original size.
 >> tic; for k = 1:100, ifft(fft( x1, N).*fft(x2,N)); end, toc
 Elapsed time is 1.036913 seconds.
 >> N = length(x1)+length(x2);  % Better size.
 >> tic; for k = 1:100, ifft(fft( x1, N).*fft(x2,N)); end, toc
 Elapsed time is 0.289473 seconds.

当然,如果不断减少N的因素,您甚至可以做得更好:

 >> N = length(x1)+length(x2)
 N =
        65538
 >> while max(factor(N)) > 7, N = N + 2; end
 >> N
 N =
        65610
 >> tic; for k = 1:100, ifft(fft( x1, N).*fft(x2,N)); end, toc
 Elapsed time is 0.250967 seconds.

因此,仅通过选择更好的变换大小,您就能获得4倍的加速,并且即使具有conv能够针对所有这些零进行优化的能力,您也将获得更好的速度。