【问题标题】:mm_shuffle_epi8 equivalent on ARM machinesARM 机器上的 mm_shuffle_epi8 等效项
【发布时间】: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 的实现,并且正在寻找线索。我自己学习了AVX2NEON2SSE
  • 您可能对 [SIMD Everywhere}(github.com/simd-everywhere/simde) 感兴趣。除了实现之外,wiki 和文档还链接到其他实现。

标签: c arm neon cortex-m cortex-a8


【解决方案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 table2{vget_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
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
  • 2014-10-24
相关资源
最近更新 更多