【发布时间】:2019-12-09 01:08:20
【问题描述】:
我正在尝试将每个字节乘以两个 m128i 字节(8 位有符号整数)。
这里的问题是溢出。我的解决方案是将这些 8 位有符号整数存储为 16 位有符号整数,相乘,然后将整个内容打包成一个 16 x 8 位整数的m128i。
这是我制作的__m128i mulhi_epi8(__m128i a, __m128i b) 仿真:
inline __m128i mulhi_epi8(__m128i a, __m128i b)
{
auto a_decomposed = decompose_epi8(a);
auto b_decomposed = decompose_epi8(b);
__m128i r1 = _mm_mullo_epi16(a_decomposed.first, b_decomposed.first);
__m128i r2 = _mm_mullo_epi16(a_decomposed.second, b_decomposed.second);
return _mm_packs_epi16(_mm_srai_epi16(r1, 8), _mm_srai_epi16(r2, 8));
}
decompose_epi8以非simd方式实现:
inline std::pair<__m128i, __m128i> decompose_epi8(__m128i input)
{
std::pair<__m128i, __m128i> result;
// result.first => should contain 8 shorts in [-128, 127] (8 first bytes of the input)
// result.second => should contain 8 shorts in [-128, 127] (8 last bytes of the input)
for (int i = 0; i < 8; ++i)
{
result.first.m128i_i16[i] = input.m128i_i8[i];
result.second.m128i_i16[i] = input.m128i_i8[i + 8];
}
return result;
}
此代码运行良好。我现在的目标是实现这个 for 循环的 simd 版本。我查看了Intel Intrinsics Guide,但我找不到这样做的方法。我想 shuffle 可以解决问题,但我无法将其概念化。
【问题讨论】:
-
试试
_mm_unpacklo_epi8和_mm_unpackhi_epi8 -
@Lawrence 我试试看,谢谢
-
@Lawrence
_mm_unpacklo_epi8对签名解包没有多大帮助。使用 SSE4.1_mm_cvtepi8_epi16可能是一种选择。 -
@Lawrence,实际上,
_mm_unpack{lo,hi}_epi8可以工作,因为您可以将数据字节解压缩到每个 16 位字的上半部分(并使用_mm_mulhi_epi16进行乘法运算)。我认为您仍然需要移动(或巧妙地置换)乘法结果,因为我认为_mm_packs_epi16的变体不会向右移动而不是饱和。
标签: c++ intel sse simd intrinsics