将16位值的__m256i(饱和)压缩为8位值的___m128i



是否有AVX或AVX2操作将16x16位无符号int(uint16_t(值的__m256i转换为16x8位无签名int(uint8_t(的__m128i(采用饱和的低位字节(?

_mm256_packus_epi16(),但它使用来自第一个输入的前8个字节,然后使用来自第二个输入的后8个字节。。。导致8个字节的组无序。

还有一些AVX512操作似乎可以满足需要,但我不能依赖AVX512,它在许多目标机器上都不存在。。。

不,您不能在AVX/AVX2的单个指令中做到这一点。

有_mm256_packus_epi16((,但它使用来自第一个输入的前8个字节,然后使用来自第二个输入的第一个8字节,然后再使用来自第一和第二输入的第二个8字节。。。导致8个字节的组无序。

以下是如何正确安排(AVX2(:

static inline __m128i convert(__m256i data) {
__m128i lo_lane = _mm256_castsi256_si128(data);
__m128i hi_lane = _mm256_extracti128_si256(data, 1);
return _mm_packus_epi16(lo_lane, hi_lane);
}

根据Skylake上的uops.info,_mm256_extracti128_si256在p5上为1µop,_mm_packus_epi16在p5中为1µop。这意味着这个代码块的吞吐量应该是2个周期(每两个周期转换一次(。

您可以使用_mm256_extractf128_si256瞄准AVX。域交叉可能会花费额外的延迟(但吞吐量应该是相同的AFAIK(。

最新更新