0

我试图弄清楚是否以及如何并行化特定的现有代码以在 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];
}

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

4

1 回答 1

1

所以是的,这看起来确实像一个双二阶,每个样本的系数都会改变,也许是因为你正在平滑它们。

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

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

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

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