霓虹灯等效于 mm_madd_epi16 和 mm_maddubs_epi16

Posted

技术标签:

【中文标题】霓虹灯等效于 mm_madd_epi16 和 mm_maddubs_epi16【英文标题】:Neon equivalent of mm_madd_epi16 and mm_maddubs_epi16 【发布时间】:2021-10-21 09:48:19 【问题描述】:

我正在尝试将 SSE 中的代码移植到 Neon。

我找不到 mm_maddubs_epi16 和 mm_madd_epi16 的等效内在函数。

关于 Neon 的这些内在函数的任何见解。

【问题讨论】:

您将它们用于什么样的用例?作为扩大水平总和的一部分?或者两个输入都不是常数的东西,你实际上需要扩大产品以及水平添加对的一个步骤? 我的输入是非恒定的,我需要扩大产品以及水平添加对的一个步骤。 【参考方案1】:

您可能想查看_mm_madd_epi16_mm_maddubs_epi16 的 SIMDe 实现(请注意未来的读者:您可能需要检查这些文件的最新版本,因为 SIMDe 中的实现有时会得到改进,而且我不太可能会记得更新这个答案)。这些实现只是从那里复制过来的。

如果您在 AArch64 上,对于 _mm_madd_epi16,您可能希望使用 vmull_s16+vget_low_s16 作为低半部分,vmull_high_s16 作为高半部分,然后使用 vpaddq_s32 将它们加在一起成 128 位结果。如果没有 AArch64,您将需要两个 vmull_s16 调用(一个带有 vget_low_s16,一个带有 vget_high_s16),但由于不支持 vpaddq_s32,您需要两个带有 vcombine_s32vpadd_s32 调用:

#if defined(SIMDE_ARM_NEON_A64V8_NATIVE)
  int32x4_t pl = vmull_s16(vget_low_s16(a_.neon_i16),  vget_low_s16(b_.neon_i16));
  int32x4_t ph = vmull_high_s16(a_.neon_i16, b_.neon_i16);
  r_.neon_s32 = vpaddq_s32(pl, ph);
#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE)
  int32x4_t pl = vmull_s16(vget_low_s16(a_.neon_i16),  vget_low_s16(b_.neon_i16));
  int32x4_t ph = vmull_s16(vget_high_s16(a_.neon_i16), vget_high_s16(b_.neon_i16));
  int32x2_t rl = vpadd_s32(vget_low_s32(pl), vget_high_s32(pl));
  int32x2_t rh = vpadd_s32(vget_low_s32(ph), vget_high_s32(ph));
  r_.neon_i32 = vcombine_s32(rl, rh);
#endif

对于_mm_maddubs_epi16,它有点复杂,但我不认为特定于 AArch64 的版本会有多大用处:

/* Zero extend a */
int16x8_t a_odd = vreinterpretq_s16_u16(vshrq_n_u16(a_.neon_u16, 8));
int16x8_t a_even = vreinterpretq_s16_u16(vbicq_u16(a_.neon_u16, vdupq_n_u16(0xff00)));

/* Sign extend by shifting left then shifting right. */
int16x8_t b_even = vshrq_n_s16(vshlq_n_s16(b_.neon_i16, 8), 8);
int16x8_t b_odd = vshrq_n_s16(b_.neon_i16, 8);

/* multiply */
int16x8_t prod1 = vmulq_s16(a_even, b_even);
int16x8_t prod2 = vmulq_s16(a_odd, b_odd);

/* saturated add */
r_.neon_i16 = vqaddq_s16(prod1, prod2);

【讨论】:

以上是关于霓虹灯等效于 mm_madd_epi16 和 mm_maddubs_epi16的主要内容,如果未能解决你的问题,请参考以下文章

RISC V的任何霓虹灯等效物?

有效使用vmlaq_s16

_mm_srli_si128 等效于 altivec

ARM 机器上的 mm_shuffle_epi8 等效项

等效于 min() 的 rowMeans()

摘要 SAD(绝对差和)的霓虹灯实现总线错误