可以并行化 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 的过滤器吗?的主要内容,如果未能解决你的问题,请参考以下文章