如何在 Neon 内在函数中使用 if 条件进行并行操作?

Posted

技术标签:

【中文标题】如何在 Neon 内在函数中使用 if 条件进行并行操作?【英文标题】:How to do parallel operation with if condition in Neon intrinsics? 【发布时间】:2013-12-09 03:27:14 【问题描述】:

我问了一个关于 vclt_s8 比较的问题。 Does anybody know how to use Neon intrinsics uint8x8_t vclt_s8 (int8x8_t, int8x8_t)

但是,如果我们有这样的代码:

if(a > b + c) 
    a = b + c;
 else if(a < b - c) 
    a = b - c;

如何将其转换为 Neon 内在函数?在这种情况下,我们似乎无法进行 8 个算子并行操作。不是吗?

【问题讨论】:

【参考方案1】:

显然你不能使用 SIMD 进行分支,所以你必须看看如何使用掩码以无分支的方式实现这种逻辑。我只是给出伪代码,所以你会明白一般的想法 - 编码应该相当简单:

bc = b + c       ; get `(b + c)` in a vector register
mask = a > bc    ; use compare instruction to generate mask (-1 = true, 0 = false)
bc = bc & mask   ; use bitwise AND to zero out elements of `(b + c)` which we do not want
a = a & ~mask    ; use bitwise ANDC to zero out elements of `a` which we do not want
a = a | bc       ; combine required elements into `a` using bitwise OR

bc = b - c       ; get `(b - c)` in a vector register
mask = a < bc    ; use compare instruction to generate mask (-1 = true, 0 = false)
bc = bc & mask   ; use bitwise AND to zero out elements of `(b - c)` which we do not want
a = a & ~mask    ; use bitwise ANDC to zero out elements of `a` which we do not want
a = a | bc       ; combine required elements into `a` using bitwise OR

请注意,我在这里作弊并从您的标量代码中省略了else(假设这两个分支是互斥的)所以我实现的实际上相当于:

if (a > b + c) 
    a = b + c;

if (a < b - c) 
    a = b - c;

如果这是一个错误的假设,那么您将需要执行一些额外的按位运算来实现逻辑 else

【讨论】:

让 a = 2, b = 2, c = -1... 你需要正确处理它! (OP 使用的是 's8' 内在函数,所以我猜签名对他们很重要) @James:不一定——这取决于用例——从图像/信号处理的上下文来看,我的猜测是c 总是积极的——如果不是这样,但它很容易添加更多按位指令来实现else,正如我上面所说的,但你不想这样做并在不需要时牺牲性能。 掩码是签名还是未签名? int8x8_t 掩码;或 uint8x8_t 掩码; @BonderWu:这真的没关系 - 每个元素都是 1 表示“真”(将其视为 255 或 -1,无论你喜欢哪个),而全 0 表示“假”。请参阅您的previous question 接受的答案,他们使用无符号掩码结果。 @BonderWu:如果这有助于您解决问题,请接受答案

以上是关于如何在 Neon 内在函数中使用 if 条件进行并行操作?的主要内容,如果未能解决你的问题,请参考以下文章

使用 ARM neon 内部函数进行深度转换

使用NEON优化ARM的卷积运算

使用NEON内在函数除以浮点数

如何使用 ARM NEON 内在函数将 u8 掩码转换为 u32 掩码?

如何在 ARM NEON SIMD 内在函数上编写“a[i]=b[c[i]]”

ARM NEON 没有 xor gcc 内在函数