X86 打包(带饱和)_m256i的16位值到_m128i的8位值?
是否有AVX或AVX2操作将16x16位无符号int(uint16_t)值的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
\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);
}