gpt4 book ai didi

arm - 如何使用 ARM Neon 内在函数对 IF block 进行矢量化?

转载 作者:行者123 更新时间:2023-12-02 17:14:18 25 4
gpt4 key购买 nike

我想在 ARM 处理器上处理大量 float ,使用 Neon 技术一次计算它们四个。对于加法和乘法等操作,一切都很好,但是如果我的计算进入 IF block ,我该怎么办?示例:

// In the non-vectorized original code, A is an array of many floating-point
// numbers, which are calculated one at a time. Now they're packed
// into a vector and processed four at a time

...calculate A...

if (A > 10.f)
{
A = A+5.f;
}
else
{
A = A+10.f;
}

现在,我要执行哪个 IF 分支?如果正在处理的向量中的某些值大于 10 而另一些值小于 10 怎么办?甚至可以像这样矢量化代码吗?

最佳答案

到目前为止,我将通过描述如何在 Neon 内在函数中对其进行编码来补充答案。

  1. 通常,您不会根据并行寄存器内容执行 IF block 逻辑,因为一个值可能需要 IF block 的一个分支,而同一寄存器中的不同值可能需要另一个。 “Eager Execution”意味着首先进行所有可能的计算,然后决定在哪些车道上实际使用哪些结果。 (请记住,仅对寄存器的一个 channel 进行 Neon 计算不会获得任何好处。任何必须完成的计算都会对所有 2 或 4 个 channel 完成。)

  2. 要进行基于 IF 的计算,请使用 Neon 条件内在函数,例如“大于”做一个位掩码,然后一个“选择”函数根据位掩码填充最终结果

双 aval[2] = {11.5, 9.5};

float64x2_t AA= vld1q_f64(aval);       // an array with two 64-bit double values

float64x2 TEN= vmovq_n_f64(10.f); // load a constant into a different array
float64x2 FIVE= vmovq_n_f64(5.f); // load a constant into a different array

// Do both of the computations
float64x2 VALIFTRUE = vaddq_f64(AA, TEN); // {21.5, 19.5}
float64x2 VALIFFALSE = vaddq_f64(AA, FIVE); // {16.5, 14.5}


uint64x2_t IF1 = vcgtq_f64 (AA, TEN); // comparison "(if A > 10.)"

vcgtq_f64 的返回值不是一组 double ,而是两个 64 位无符号整数。它们实际上是一个位掩码,可以被 vbslq_f64 等“按位选择”函数使用。 IF1 的前 64 位全为 1(大于条件为真),后 64 位全为 0。

AA = vbslq_f64(IF1, VALIFTRUE, VALIFFALSE);  // {21.5, 14.5}

...并且 AA 的每个 channel 都根据需要填充该 channel 的 VALIFTRUE 或 VALIFFALSE。

  1. 如果 eager execution 太慢怎么办——一个分支中的计算非常耗费处理器时间,如果可以的话,您想完全避免这样做?您必须验证任何矢量 channel 的分支条件都不成立,然后使用适当的“if”语句跳过计算。也许其他人可以评论这在实践中的效果如何。

关于arm - 如何使用 ARM Neon 内在函数对 IF block 进行矢量化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47320062/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com