NEON:将 int8x16_t 拆包成一对 int16x8 并将一对 int16x8_t 打包成 int8x16_t
Posted
技术标签:
【中文标题】NEON:将 int8x16_t 拆包成一对 int16x8 并将一对 int16x8_t 打包成 int8x16_t【英文标题】:NEON: Unpacking int8x16_t into a pair of int16x8 & packing a pair of int16x8_t into a 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,如果它可以满足您的要求,它可能比首先进行符号扩展更有效。
【参考方案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
【讨论】:
感谢您的回答!真的很有帮助以上是关于NEON:将 int8x16_t 拆包成一对 int16x8 并将一对 int16x8_t 打包成 int8x16_t的主要内容,如果未能解决你的问题,请参考以下文章
arm_neon.h 是不是缺少所有 float16_t 类型?
如何在 Neon 中将 uint32x4_t 转换为 uint8x16_t?