ARM 机器上的 mm_shuffle_epi8 等效项
Posted
技术标签:
【中文标题】ARM 机器上的 mm_shuffle_epi8 等效项【英文标题】:mm_shuffle_epi8 equivalent on ARM machines 【发布时间】:2021-11-29 10:52:57 【问题描述】:在一个专注于加速 ARM 性能的项目中, 我正在使用下面页面 https://github.com/f4exb/cm256cc/blob/master/sse2neon.h#L981 中的 mm_shuffle_epi8 实现。
但上述实现不是最优的,会导致性能成本。
ARM 的 _mm_shuffle_epi8 是否有正确的等价物?
【问题讨论】:
我的建议是,如果您需要这种性能,您可能应该对整个功能进行特定于 Arm 的实现。这样就可以更改算法以更好地适应 Arm 指令集。 @Johan 我认为 OP 正在执行特定于 ARM 的实现,并且正在寻找线索。我自己学习了AVX2
和NEON2SSE
。
您可能对 [SIMD Everywhere(github.com/simd-everywhere/simde) 感兴趣。除了实现之外,wiki 和文档还链接到其他实现。
【参考方案1】:
vtbl2
(可能还有vtbx2
)正是您要找的。p>
但请注意,这些指令有很长的延迟,尤其是在 Cortex-a57 和 Cortex-a72 上。(aarch64
模式)它甚至没有在 A-57 上流水线。
我自己不惜一切代价避免使用它们:太贵了。
NEON 具有优于 AVX
的置换指令。也许你可以找到解决方法。
PS:SSE2NEON.... IMO 根本不是一个好主意。而且您提供的链接的方式非常糟糕。
【讨论】:
谢谢。找到了与 SSE 上的 shuffle 等效的内在 vqtbl1q_u8【参考方案2】:等价物应该是这样的
uint8x16_t shuffle_epi8(uint8x16_t table, uint8x16_t index)
int8x16_t mask = vshrq_n_s8(vreinterpretq_s8_u8(index), 7);
index = vandq_u8(index, vdupq_n_u8(15));
index = vqtbl1q_u8(table, index);
return vbicq_u8(index, vreinterpretq_u8_s8(mask));
在 armv7 上,需要模拟 16 位宽的表
inline uint8x16_t vqtbl1q_u8(uint8x16_t table, uint8x16_t idx)
uint8x8x2_t table2vget_low_u8(table), vget_high_u8(table);
uint8x8_t lo = vtbl2_u8(table2, vget_low_u8(idx));
uint8x8_t hi = vtbl2_u8(table2, vget_high_u8(idx));
return vcombine_u8(lo, hi);
【讨论】:
你看到cortex-a8
标签了吗? :-)
如果已知索引向量在 0..15 以内,那么只使用 vqtbl1q_u8
函数就足够了。
您应该进行 msb 检查以使其 100% 兼容。是的,这很糟糕,这就是为什么我说 SSE2NEON 不是一个好主意。
MSB 检查从一开始就存在于shuffle_epi8
中。我正在使用vcltq_u8(index, 0x80);
,它转换为与立即数的有符号比较。它不需要添加到 vqtbl1q_u8
,因为这只是 armv7 的 arm64 仿真。
你不需要vclt
。你只需要在 7 之前签名 vshr
,然后 vbic
以上是关于ARM 机器上的 mm_shuffle_epi8 等效项的主要内容,如果未能解决你的问题,请参考以下文章