我想在 ARM 处理器上处理大量浮点数,使用 Neon 技术一次计算四个浮点数。对于加法和乘法等运算来说一切都很好,但是如果我的计算进入 IF 块,我该怎么办?例子:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
现在,我要执行哪个 IF 分支?如果正在处理的向量中的某些值大于 10 而某些值小于 10,该怎么办?是否有可能像这样矢量化代码?
我将通过描述如何在 Neon 内在函数中对其进行编码来添加到目前为止的答案。
一般来说,您不会基于并行寄存器内容执行 IF 块逻辑,因为一个值可能需要 IF 块的一个分支,而同一寄存器中的不同值可能需要另一个分支。“热切执行”意味着首先进行所有可能的计算,然后决定在哪些通道中实际使用哪些结果。(请记住,仅对寄存器的一个通道进行 Neon 计算不会获得任何好处。任何必须完成的计算都会针对所有 2 或 4 个通道完成。)
要进行基于 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.)"
Run Code Online (Sandbox Code Playgroud)
vcgtq_f64 的返回值不是一组双精度数,而是两个 64 位无符号整数。它们实际上是一个位掩码,可由“按位选择”函数(例如 vbslq_f64)使用。IF1 的前 64 位全为 1(大于条件为真),后 64 位全为 0。
AA = vbslq_f64(IF1, VALIFTRUE, VALIFFALSE); // {21.5, 14.5}
Run Code Online (Sandbox Code Playgroud)
...并且 AA 的每个通道都根据情况填充该通道的 VALIFTRUE 或 VALIFFALSE。
| 归档时间: |
|
| 查看次数: |
1992 次 |
| 最近记录: |