是否有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(。