可以并行化 ARM NEON 的过滤器吗?

Posted

技术标签:

【中文标题】可以并行化 ARM NEON 的过滤器吗?【英文标题】:Possible to parallelize filter for ARM NEON? 【发布时间】:2013-05-31 13:15:01 【问题描述】:

我试图弄清楚是否以及如何并行化特定的现有代码以用于 ARM Cortex-A9 NEON SIMD 单元。这是代码:

for(int i=0; i < 11; i++)

    f4UF1 *= F[i];

    A[i][2] = A[i][1];
    A[i][1] = A[i][0];
    A[i][0] = f4UF1;

    B[i][2] = B[i][1];
    B[i][1] = B[i][0];

    C[i] = 0;

    C[i] += D[i][0] * A[i][0];
    C[i] += D[i][1] * A[i][1];
    C[i] += D[i][2] * A[i][2];

    C[i] -= E[i][1] * B[i][1];
    C[i] -= E[i][2] * B[i][2];

    B[i][0] = C[i] / E[i][0];

    f4UF1 = B[i][0];

我已经看了相当多的代码,我几乎可以肯定它不能被有效地并行化,但我想,我可以试试看这里。我不期待准备好的代码,只是关于如何做的想法。谢谢:)

【问题讨论】:

有哪些数据类型?你应该粘贴一些可以满足编译器的东西。 编译它并检查输出可能会提供一些见解。 您可以使用 vext 指令向下滑动元素。您也可以进行乘法/加法。如果你用 NEON 写的话,看起来你可以改进几个周期。唯一的问题是需要将除法转换为乘法。 这是一个标准的双二阶过滤器,对吧?好吧 - 如果您可以接受一些全局输出延迟,则可以使用技巧来并行化它。 @NilsPipenbrinck:+1 用于识别它是 Biquad;不过,如果有一些关于您提到的优化机会的指针,那就太好了。 【参考方案1】:

所以是的,这看起来确实像一个双二阶,每个样本的系数都发生了变化,可能是因为您正在对其进行平滑处理。

正如评论者所提到的,您可能希望预先计算 1/E[i][0] 比例因子,并可能将其滚动到其他系数中以减少乘法次数,尤其是在浮点平台上。您还可以经常对双二阶进行归一化以摆脱D[i][0](使其成为1.0),然后将一个标量应用于整个输出。

当然,您可能已经意识到,您希望在循环期间将所有内容保存在寄存器中,然后仅在循环完成后将它们写入内存... ;-)

在那之后,我知道有两种矢量化技术(尽管我也对 Nils 的想法感兴趣):

    频道矢量化 - 最简单。如果您需要一次将过滤器应用于多个数据集(例如,对于立体声音频非常常见),您可以同时使用两组音频数据操作两组系数。如果您使用全 SP 浮点,我发现 Neon 为两个通道提供了大约正确数量的寄存器。确实是即时 2 倍加速。 循环展开。在这里详细描述有点棘手,但幸运的是这里有一个不错的页面:http://reanimator-web.appspot.com/articles/simdiir。这种技术添加了极点/零对,本质上是一次计算更多样本。但是,额外的极点当然会为滤波器的稳定性增加额外的条件,因此您必须小心。在您的情况下,当系数似乎是动态的时,这可能是需要确保的某种噩梦。

【讨论】:

以上是关于可以并行化 ARM NEON 的过滤器吗?的主要内容,如果未能解决你的问题,请参考以下文章

ARM NEON 汇编和浮点舍入

ARM NEON 优化中的建议

ARM NEON指令集总结

带有 ARM NEON(没有 Mali GPU)的 OpenCL 可用吗?

使用 openMP v. 2.0 并行化过滤器迭代器

我可以在 x86 C 程序中模拟 ARM NEON 吗?