【问题标题】:Neon code for converting b/w rectangular and polar forms用于在矩形和极坐标之间转换的霓虹灯代码
【发布时间】:2017-07-06 13:50:48
【问题描述】:

我正在尝试在我的 CPP 项目中使用 Project NE10 执行 FFT->signal manipulation->Inverse FFT,并将复数输出转换为幅度和相位以用于 FFT,反之亦然以用于 IFFT。但是根据基准测试,我的 C++ 代码的性能不如启用 SIMD 的 NE10 代码。由于我没有手臂组装经验,我正在寻找一些帮助来为未优化的 C 模块编写霓虹灯代码。例如,在 IFFT 之前,我会这样做:

for (int bin = 0; bin < NUM_FREQUENCY_BINS; bin++) {
    input[bin].real = amplitudes[bin] * cosf(phases[bin]);
    input[bin].imag = amplitudes[bin] * sinf(phases[bin]);
}

其中input 是一个 C 结构数组(用于复数值),amplitudesphasesfloat 数组。

上面的块(O(n) complexity) 需要大约 0.6ms 来处理 8192 个 bin 而 NE10 FFT (O(n*log(n)) complexity) 因为 SIMD 操作只需要 0.1ms。从我目前在 StackOverflow 和其他地方读到的内容来看,内在函数不值得付出努力,所以我只尝试使用 arm neon。

【问题讨论】:

  • 内在函数绝对值得付出努力。特别是,您可以将寄存器分配等繁琐的工作留给编译器,与手写汇编相比,这将提高性能,除非您非常擅长编写汇编并且知道代码将在其上运行的微架构的详细信息。
  • 我有a godbolt example,它在循环中显示对cosfsinf 的调用。函数调用会产生大量内存开销。这是link here for youanother linkcosfsinf 是相关的,所以计算两者。标准的“C”库具有非常严格的精度(或者至少这是重点)。 sin(x)^2+cos(x)^2=1.
  • ...同时在上面...也就是说,您的“信号操纵”可以在极坐标或实数/虚数上执行,因此您无需进行此转换。确实,您需要做一些数学运算以使事物保持在相同的坐标中(或者至少值得研究)。 '卷积'可能是你添加到你的工具包中的东西?或者至少问题的信号处理方面可能很重要;即,您为什么需要转换?
  • 我正在通过将幅度转移到更高频率来更改来自麦克风的输入信号。对我来说,最简单的方法是使用振幅。

标签: arm simd neon


【解决方案1】:

据我所知,NEON 不支持几何函数(sin、cos)的矢量运算。但是当然你可以改进你的代码。作为变体,您可以使用函数正弦和余弦的预计算值表。它可以显着提高性能。

关于使用 NEON 的内在函数。我尝试过使用它们,但在大多数情况下,它们给出的结果几乎相同(对于现代编译器)。但是使用 if 汇编器更加劳动密集。主要的性能改进是通过正确处理数据(加载、存储)和使用向量指令来实现的,但这些操作可以通过使用内在函数来执行。

当然,如果你想达到 100% 的 CPU 利用率,你有时需要使用汇编程序。但这种情况很少见。

【讨论】:

    【解决方案2】:

    如果您满足于近似值,您可以将 NEON 用于三角函数。我不隶属于,但有一个实现 here 使用内在函数创建精确到许多小数位的向量化 sin/cos 函数,其性能比简单地调用 sinf 等要好得多(基准由作者提供)。

    该代码特别适合您的极坐标到笛卡尔计算,因为它同时生成 sin 和 cos 结果。它可能不适合绝对精度至关重要的事情,但对于与频域音频处理有关的事情,通常情况并非如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-14
      相关资源
      最近更新 更多