将 16 位值的 __m256i 打包(饱和)到 8 位值的 __m128i?
Pack (with saturation) __m256i of 16-bit values to __m128i of 8-bit values?
是否有 AVX 或 AVX2 操作将 16x16 位无符号整数 (uint16_t) 值的 __m256i
转换为 16x8 位无符号整数 (uint8_t 的 __m128i
]) 值( 以低字节饱和)?
有 _mm256_packus_epi16()
但它使用第一个输入的前 8 个字节,然后是第二个输入的前 8 个字节,然后是第一个和第二个输入的第二个 8 字节...导致 8 个字节为一组乱序。
还有一些 AVX512 ops 似乎可以满足需要,但我不能依赖 AVX512,它在许多目标机器上都不存在...
不,你不能在 AVX/AVX2 的一条指令中做到这一点。
There is _mm256_packus_epi16() but it uses first 8 bytes from first input, then first 8 bytes from second input, and then second 8 bytes from first and second input... resulting in groups of 8 bytes being out of order.
正确安排的方法如下 (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)。
是否有 AVX 或 AVX2 操作将 16x16 位无符号整数 (uint16_t) 值的 __m256i
转换为 16x8 位无符号整数 (uint8_t 的 __m128i
]) 值( 以低字节饱和)?
有 _mm256_packus_epi16()
但它使用第一个输入的前 8 个字节,然后是第二个输入的前 8 个字节,然后是第一个和第二个输入的第二个 8 字节...导致 8 个字节为一组乱序。
还有一些 AVX512 ops 似乎可以满足需要,但我不能依赖 AVX512,它在许多目标机器上都不存在...
不,你不能在 AVX/AVX2 的一条指令中做到这一点。
There is _mm256_packus_epi16() but it uses first 8 bytes from first input, then first 8 bytes from second input, and then second 8 bytes from first and second input... resulting in groups of 8 bytes being out of order.
正确安排的方法如下 (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)。