【问题标题】:Execution time of convolution using fft in MatlabMatlab中使用fft进行卷积的执行时间
【发布时间】:2018-10-09 21:03:15
【问题描述】:

我有两个信号 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:使用timeit 来衡量计算时间,tic/toc 在这种情况下并不准确。 2:除了一个元素外,您的数据全为零,这也可能会影响您的计算。
  • 接受@CrisLuengo 关于timeit 的观点,0.010 秒比 0.017 秒快很多。
  • 为什么fft 的执行时间不会更少?是什么让您认为 conv 没有优化,可能在内部使用了 FFT?
  • @bazza:通过在命令行中复制粘贴运行此代码,您可以看到比这些大得多的时序差异。如果您在新的 MATLAB 会话中运行它,您甚至可能会看到一些简单的函数在加载 M 文件时需要一秒钟。
  • 使用 Octave,我看到 conv 需要 2.0 秒,fft 需要 0.012 秒。我认为@Luis 是对的,您会看到conv 的一个非常漂亮的实现。

标签: matlab fft convolution


【解决方案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 能够针对所有这些零进行优化,您也会获得更好的速度。

【讨论】:

    猜你喜欢
    • 2013-10-09
    • 1970-01-01
    • 2016-08-18
    • 2020-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    相关资源
    最近更新 更多