如何在ARM NEON中实现x86的_mm256_sign_epi8指令?
在ARM NEON中实现x86 _mm256_sign_epi8的等效功能
首先明确_mm256_sign_epi8(a, b)的核心行为:
对每个8位有符号整数元素:
- 若
b[i] < 0,结果为-a[i]- 若
b[i] == 0,结果为0- 若
b[i] > 0,结果为a[i]
ARM NEON没有直接对应的指令,但可以通过位操作和向量选择指令高效实现,且无需乘法:
#include <arm_neon.h> int8x16_t neon_sign_epi8(int8x16_t a, int8x16_t b) { // 提取b的符号位掩码:负数对应0xFF,正数/0对应0x00 int8x16_t sign_mask = vshrq_n_s8(b, 7); // 计算a的取反向量 int8x16_t neg_a = vnegq_s8(a); // 根据符号掩码选择原a或取反后的a int8x16_t temp = vbslq_s8(sign_mask, neg_a, a); // 生成非零掩码:b[i]≠0时为0xFF,否则为0x00 int8x16_t non_zero_mask = vcgtq_s8(vabsq_s8(b), vdupq_n_s8(0)); // 将b[i]=0对应的位置置0,得到最终结果 return vbslq_s8(non_zero_mask, temp, vdupq_n_s8(0)); }
关键指令说明
vshrq_n_s8:将向量元素右移7位,直接提取最高位(符号位)并扩展为整个字节的掩码vnegq_s8:直接计算向量元素的相反数,比手动~a +1更高效且符合NEON指令集优化vbslq_s8:基于掩码选择两个向量的对应元素,是NEON实现条件选择的核心指令vcgtq_s8+vabsq_s8:生成非零掩码,筛选出b中不为0的元素位置
如果你的场景中不需要处理b[i]=0的情况(仅用符号位控制取反),可以简化代码:
int8x16_t neon_sign_only_epi8(int8x16_t a, int8x16_t b) { int8x16_t sign_mask = vshrq_n_s8(b, 7); int8x16_t neg_a = vnegq_s8(a); return vbslq_s8(sign_mask, neg_a, a); }
内容的提问来源于stack exchange,提问作者Eddie-Wang
相关产品推荐
相关产品推荐

