X86 打包(带饱和)_m256i的16位值到_m128i的8位值?

X86 打包(带饱和)_m256i的16位值到_m128i的8位值?,x86,simd,avx,avx2,X86,Simd,Avx,Avx2,是否有AVX或AVX2操作将16x16位无符号int(uint16_t)值的\uuuum256i转换为16x8位无符号int(uint8_t)值的\uuuuum128i(采用饱和较低字节) 有\u mm256\u packus\u epi16()但它使用第一次输入的前8个字节,然后使用第二次输入的前8个字节,然后使用第一次和第二次输入的第二个8个字节。。。导致8个字节的组顺序混乱 还有一些AVX512操作似乎可以执行所需的操作,但我不能依赖AVX512,它在许多目标机器上都不存在…不,不能在AV

是否有AVX或AVX2操作将16x16位无符号int(uint16_t)值的
\uuuum256i
转换为16x8位无符号int(uint8_t)值的
\uuuuum128i
采用饱和较低字节)

\u mm256\u packus\u epi16()
但它使用第一次输入的前8个字节,然后使用第二次输入的前8个字节,然后使用第一次和第二次输入的第二个8个字节。。。导致8个字节的组顺序混乱


还有一些AVX512操作似乎可以执行所需的操作,但我不能依赖AVX512,它在许多目标机器上都不存在…

不,不能在AVX/AVX2的单个指令中执行

有_mm256_packus_epi16(),但它使用第一个输入的前8个字节,然后使用第二个输入的前8个字节,然后使用第一个和第二个输入的第二个8个字节。。。导致8个字节的组顺序混乱

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

根据Skylake上的
\u mm256\u extracti128\u si256
在p5上为1µop,而
\u mm\u packus\u epi16
在p5上为1µop。这意味着这个代码块的吞吐量应该是2个周期(每两个周期一次转换)


您可以使用
\u mm256\u extractf128\u si256
以AVX为目标。有可能域交叉会花费额外的延迟(但吞吐量应该是相同的)。

可以
\u mm256\u permute4x64\u epi64
或另一个洗牌操作修复之后的顺序吗?我想你的意思是
\u m256i
<代码>\uuum256是一个单精度浮点向量。太棒了!!谢谢大家!@AlexanderNovikov:如果您有大量数据需要以这种方式处理,通常最好在两个输入上使用
\u mm256\u packus\u epi16
,然后
\u mm256\u permute4x64\u epi64
修复lane pack中的craptastic AVX2造成的混乱。对于一个32字节的向量,2次洗牌显然比对于两个16字节的向量,4次洗牌要好,就像你从中得到的那样(AMD Zen1上的情况除外,
vextract128
非常便宜,而车道交叉256位洗牌非常昂贵)我在上的回答显示了如何在一对
\uuuuum256i
16x16位上使用pack+vpermq fixup,以正确的顺序获得一个
\uuuuum256i
32x8位。
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);
}