如何使用 SSE 内在函数将 16 个 8 位整数除以 4(或将它们右移 2)?
不幸的是,没有针对 8 位元素的 SSE 移位指令。如果元素是 8 位无符号,那么您可以使用 16 位移位并屏蔽掉不需要的高位,例如
v = _mm_srli_epi16(v, 2);
v = _mm_and_si128(v, _mm_set1_epi8(0x3f));
对于 8 位 signed 元素,它有点麻烦,但仍然是可能的,尽管它可能更容易解压缩到 16 位,进行移位,然后打包回 8 位。
如果您的 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
(v+2)/4
如果您根本不想舍入(即整数除法),您可以从 v 中减去 1。
在大多数情况下,小的舍入误差不值得再执行另一条指令。另外,您应该将零常数移出函数。