【问题标题】:NEON: Unpacking int8x16_t into a pair of int16x8 & packing a pair of int16x8_t into a int8x16_tNEON:将 int8x16_t 拆包成一对 int16x8 并将一对 int16x8_t 打包成 int8x16_t
【发布时间】:2019-08-05 17:39:23
【问题描述】:

我正在为我制作的算法的 arm64 实现 NEON 版本。

我面临的问题是:

- 如何将 int8x16 解压缩为两个 int16x8_t,这意味着字节有点“投射”到短裤?
- 如何将这两个 @987654326 打包@回到int8x16_t

我尝试这样做的原因是对几个矢量化短裤应用操作,不会溢出,最后将结果打包回int8x16_t

这是我针对这个问题的 SSE2 实现:

SSE2 开箱:

__m128i a1 = _mm_srai_epi16(_mm_unpacklo_epi8(input, input), 8);
__m128i a2 = _mm_srai_epi16(_mm_unpackhi_epi8(input, input), 8);

SSE2 包装:

__m128i output = _mm_packs_epi16(a1, a2);

【问题讨论】:

  • 您可能已经知道这一点,但对于 x86 SSE4.1,您将使用 pmovsx (cvtepi8_epi16(input)) 作为下半部分。您正在实施的操作是“符号扩展”,因此为将来的搜索者提及这一点很有帮助。
  • @PeterCordes 是的,我知道,但感谢您的精确,它总能提供帮助!
  • 相关:Loading 8-bit values using NEON/ARM 表明 ARM SIMD 具有扩展的 add/sub,如果它可以满足您的要求,它可能比首先进行符号扩展更有效。

标签: c++ arm simd intrinsics neon


【解决方案1】:

你可以做到,例如像这样的内在函数:

#include <stdint.h>
#include <arm_neon.h>

void func(int8_t *buf) {
    int8x16_t vec = vld1q_s8(buf); // load 16x int8_t
    int16x8_t short1 = vmovl_s8(vget_low_s8(vec)); // cast the first 8x int8_t to int16_t
    int16x8_t short2 = vmovl_s8(vget_high_s8(vec)); // cast the last 8x int8_t to int16_t
    short1 = vaddq_s16(short1, short1); // Do operation on int16
    short2 = vaddq_s16(short2, short2);
    vec = vcombine_s8(vmovn_s16(short1), vmovn_s16(short2)); // Cast back to int8_t and combine the two vectors
    vst1q_s8(buf, vec); // Store
}

【讨论】:

  • 感谢您的回答!真的很有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多