使用 SSE 将 8 位整数除以 4(或移位)

问题描述 投票:0回答:2

如何使用 SSE 内在函数将 16 个 8 位整数除以 4(或将它们右移 2)?

c++ x86 sse simd intrinsics
2个回答
6
投票

不幸的是,没有针对 8 位元素的 SSE 移位指令。如果元素是 8 位无符号,那么您可以使用 16 位移位并屏蔽掉不需要的高位,例如

v = _mm_srli_epi16(v, 2);
v = _mm_and_si128(v, _mm_set1_epi8(0x3f));

对于 8 位 signed 元素,它有点麻烦,但仍然是可能的,尽管它可能更容易解压缩到 16 位,进行移位,然后打包回 8 位。


0
投票

如果您的 8 位整数是无符号的,您可以使用:

static inline __m128i divBy4(__m128i v)
{
  const __m128i zeros = _mm_set1_epi8(0);
  __m128i vHalf = _mm_avg_epu8(zeros, v); // (0 + v) / 2 = v / 2
  __m128i vQuarter = _mm_avg_epu8(zeros, vHalf); // (0 + (v/2)) / 2 = v/4
  return vQuarter;
}

请注意计算实际上是:

(0 + v + 1) / 2 = (v + 1)/2

(0 + (v + 1)/2  + 1) / 2 = (v + 3)/4

因此,如果您想要正确的舍入结果,您可以从 vHalf 中减去 1,得到
(v+2)/4

如果您根本不想舍入(即整数除法),您可以从 v 中减去 1。

在大多数情况下,小的舍入误差不值得再执行另一条指令。另外,您应该将零常数移出函数。

© www.soinside.com 2019 - 2024. All rights reserved.