.NET的FF实现比较

目录

介绍

附加

基准

结果

解释FFT结果

结论


介绍

在这篇简短的文章中,我们将比较.NET平台的几个快速傅立叶变换(FFT)实现。参赛者是:

Accord

Exocortex

Math.NET

NWaves

NAudio

Lomont

DSPLib

FFTW

版本:

3.8.0

1.2

5.0

0.9.6

2.1

1.1

(2017)

3.3.9

许可证:

LGPL

BSD

MIT

MIT

MIT

-

MIT

GPL

组件:

3

1

1

1

1

-

-

1+1

大小:

3.6MB

-

1.6MB

0.3MB

0.2MB

-

-

2.3MB

Nuget

附加

  • Accord.NET是一个结合了音频和图像处理的机器学习框架。它不再积极开发。
  • Exocortex项目是在早期的.NET 1.0中创建的。本文提供的副本已更新为面向.NET标准2.0并使用System.Numerics命名空间的类型Complex
  • NAudio使用具有单精度实部和虚部的自定义Complex类型实现。
  • DSPLib是一个简明的库,用于实值输入和频谱分析的FFT。未实现反向FFT
  • FFTW是一种流行的本机FFT实现。它可能是互联网上可以找到的最快的开源实现,因此与托管代码进行比较有点不公平。不过,我认为看看代码如何竞争可能会很有趣。

FFTW二进制文件不随本文一起分发。如果您希望FFTW包含在基准测试、fftw3.dllfftw3f.dll则必须手动下载二进制文件。对于最新的构建,请尝试Conda或访问Github项目以获取更多选项:GitHub - wo80/SharpFFTW: SharpFFTW - A lightweight C# wrapper for native FFTW.

基准

我对用于真实值输入(音频处理)的1D FFT特别感兴趣。以下接口用于所有测试。如果您有自己的FFT实现,则通过实现此接口并将其合并到基准测试中应该很容易,并在Util.LoadTests()方法中实例化测试。

interface ITest
{
    /// <summary>
    /// Gets the name of the test.
    /// </summary>
    string Name { get; }

    /// <summary>
    /// Gets the FFT size of the test.
    /// </summary>
    int Size { get; }

    /// <summary>
    /// Gets or sets a value indicating whether the test should be run.
    /// </summary>
    bool Enabled { get; set; }

    /// <summary>
    /// Prepare the real valued data for FFT processing.
    /// </summary>
    /// <param name="data">The samples array.</param>
    void Initialize(double[] data);

    /// <summary>
    /// Apply FFT to data.
    /// </summary>
    /// <param name="forward">If false, apply inverse FFT.</param>
    void FFT(bool forward);

    // Ignore for benchmark (used only for 'FFT Explorer', see next section)
    double[] Spectrum(double[] input, bool scale);
}

看看fftbench.Common项目的fftbench.Benchmark命名空间中的不同测试,了解如何正确实现接口。

ExocortexLomontFFTW对真实有价值的数据进行了专门的实现,预计代码的速度大约是标准复杂实现的两倍。

Accord.NETMath.NETFFTW支持任何大小的输入数组(即大小不必是2的幂)。由于ExocortexNAudioNWavesLomont仅支持基数 2,因此基准测试使用大小为2的数组。

结果

运行fftbench控制台应用程序,输出可能如下所示。第一列显示与以下各项相比Exocortex (real)的相对速度: 

$ ./fftbench 10 200
FFT size: 1024
  Repeat: 200

[14/14] Done

    FFTWF (real):  0.2  [min:    1.29, max:    1.64, mean:    1.33, stddev:    0.03]
     FFTW (real):  0.2  [min:    1.34, max:    1.60, mean:    1.43, stddev:    0.05]
            FFTW:  0.5  [min:    2.86, max:    3.13, mean:    2.87, stddev:    0.03]
Exocortex (real):  1.0  [min:    5.72, max:    6.20, mean:    5.76, stddev:    0.05]
   Lomont (real):  1.1  [min:    6.12, max:    8.04, mean:    6.26, stddev:    0.17]
   NWaves (real):  1.5  [min:    8.44, max:   10.73, mean:    8.52, stddev:    0.24]
          NWaves:  1.7  [min:    9.70, max:   11.90, mean:    9.79, stddev:    0.21]
       Exocortex:  1.9  [min:   10.56, max:   12.93, mean:   10.71, stddev:    0.22]
          Lomont:  1.9  [min:   10.58, max:   15.90, mean:   10.77, stddev:    0.38]
          NAudio:  2.1  [min:   11.80, max:   14.17, mean:   12.03, stddev:    0.20]
          AForge:  2.6  [min:   14.72, max:   15.90, mean:   14.93, stddev:    0.12]
          DSPLib:  2.8  [min:   15.30, max:   22.10, mean:   15.91, stddev:    0.94]
          Accord:  3.8  [min:   21.06, max:   29.19, mean:   21.69, stddev:    0.93]
        Math.NET:  7.4  [min:   38.26, max:   73.53, mean:   42.74, stddev:    4.60]

Timing in microseconds.

在基准测试中,每个FFT实际上被调用了50 * 200次(从第二个命令行参数(200)中获取的重复值乘以默认值50次内部迭代)。FFT大小为2^10(第一个命令行参数)。该基准测试在AMD Ryzen 3600处理器上运行。

下图显示了大小为10242048 4096的不同FFT的基准结果。fftbench-win应用程序使用的重复值为200

解释FFT结果

fftbench-win应用程序(WinForms 项目仅包含在文章下载中——不在Github上)包含一个名为FFT Explorer 的实用程序。您可以通过单击基准测试窗口最左侧的图标来打开它。

FFT浏览器允许您选择FFT实现、输入信号和FFT大小。三个图形将显示输入信号、所选FFT计算的频谱和反向FFT计算的信号。

让我们看一下SignalGenerator类的示例信号。生成的信号是频率为1.0 Hz,振幅20.0的简单正弦波:

public static double[] Sine(int n)
{
    const int FS = 64; // sampling rate

    return MathNet.Numerics.Generate.Sinusoidal(n, FS, 1.0, 20.0);
}

FFT帧大小为n=256。在64 Hz 的采样率下,我们的周期信号将在所选窗口内精确重复四次。请注意,选择所有值时,信号周期、采样率和FFT大小之间都完全匹配。这样,我们就不必处理光谱泄漏问题。

FFT输出的每个箱由频率分辨率(采样率)/FFT大小)间隔,在我们的例子中为64 / 256 = 0.25。因此,我们期望对应于我们的1.0 Hz信号的窥视位于箱号 4 中(因为1.0 = 4 * 0.25)。

由于DFT的性质,信号的频谱将被缩放n=256,因此如果不进行进一步缩放,我们预计该值为20.0 * 256 / 2 = 2560。我们除以2,因为振幅分布在两个箱中。第二个箱位于索引256 - 4=252处,并且具有相同的幅度,因为对于实值输入信号,FFT 输出是(共轭)对称的(跨越n/2,对应于奈奎斯特频率的箱)。

速览的实际值在FFT实现之间不一致,因为没有通用的缩放约定。如果FFT大小为n,则一些实现将FFT缩放1/n,一些实现将逆FFT缩放1/n,一些实现将两者缩放1/sqrtn)。有些根本不可扩展(如FFTW)。

下表显示了上述示例的不同FFT计算的幅度:

Accord.NET

Exocaortex.DSP

Math.NET

NAudio

NWaves

Lomont

DSPLib

FFTW

值:

2560

2560

160

10

2560

160

10

2560

您可以看到NAudioDSPLib1/n缩放,Math.NETLomont缩放1/sqrtn)(Math.NETLomont都允许用户更改缩放约定;上面计算并在基准测试中使用的值表示默认设置)。

结论

显然,FFTW显然是赢家。因此,如果使用原生的GPL许可库是您的一种选择,那就去吧。查看托管代码,NWaves表现相当不错。ExocortexLomont对于较小尺寸的FFT都表现良好,但对于较大尺寸的FFT,复杂FFT的性能似乎有所下降。对于真实值的信号,ExocortexLomont都表现得很好——即使对于更大的尺寸也是如此。

https://www.codeproject.com/Articles/1095473/Comparison-of-FFT-Implementations-for-NET

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值