gpt4 book ai didi

x86 - AVX 中的 AVX2 VPSHUFB 仿真

转载 作者:行者123 更新时间:2023-12-04 11:22:41 28 4
gpt4 key购买 nike

在 AVX 中只有 128 位 PSHUFB

VPSHUFB xmm1, xmm2, xmm3/m128

并且只有 AVX2 具有完整的 PSHUFB对于整个 256 位 AVX 寄存器
VPSHUFB ymm1, ymm2, ymm3/m256

如何使用 AVX 内在函数有效地模拟此指令?

同样在这种特殊情况下,源只有 8 个元素(字节),但这些元素可以在目标的完整 32 个字节内移动。所以只运行 2 x PSHUFB 没问题.

我在 VPSHUFB 中发现的一个问题是否将 16 (0x10) 视为 0,只有 128 及以上填充为零! (设置最高位)是否可以在不添加比较和屏蔽的情况下做到这一点?

最佳答案

正如@MaratDukhan 所注意到的,_mm256_shuffle_epi8 (即 VPSHUFB 用于 ymm-s)不执行完整的 32 字节洗牌。对我来说,实在是太可惜了……

这就是为什么为了在没有 AVX2 的情况下模拟它,您可以简单地将每个寄存器分成两半,对每一半进行置换,然后组合在一起:

//AVX only
__m256i _emu_mm256_shuffle_epi8(__m256i reg, __m256i shuf) {
__m128i reg0 = _mm256_castsi256_si128(reg);
__m128i reg1 = _mm256_extractf128_si256(reg, 1);
__m128i shuf0 = _mm256_castsi256_si128(shuf);
__m128i shuf1 = _mm256_extractf128_si256(shuf, 1);
__m128i res0 = _mm_shuffle_epi8(reg0, shuf0);
__m128i res1 = _mm_shuffle_epi8(reg1, shuf1);
__m256i res = _mm256_setr_m128i(res0, res1);
return res;
}

如果你真的想完全洗牌 32 字节的寄存器,你可以按照 this paper 中的方法进行操作。 .将每一半与每一半混洗,然后将结果混合在一起。如果没有 AVX2,它将是这样的:

//AVX only
__m256i _emu_mm256_shuffle32_epi8(__m256i reg, __m256i shuf) {
__m128i reg0 = _mm256_castsi256_si128(reg);
__m128i reg1 = _mm256_extractf128_si256(reg, 1);
__m128i shuf0 = _mm256_castsi256_si128(shuf);
__m128i shuf1 = _mm256_extractf128_si256(shuf, 1);
__m128i res00 = _mm_shuffle_epi8(reg0, shuf0);
__m128i res01 = _mm_shuffle_epi8(reg0, shuf1);
__m128i res10 = _mm_shuffle_epi8(reg1, shuf0);
__m128i res11 = _mm_shuffle_epi8(reg1, shuf1);
__m128i res0 = _mm_blendv_epi8(res10, res00, _mm_cmplt_epi8(shuf0, _mm_set1_epi8(16)));
__m128i res1 = _mm_blendv_epi8(res11, res01, _mm_cmplt_epi8(shuf1, _mm_set1_epi8(16)));
__m256i res = _mm256_setr_m128i(res0, res1);
return res;
}

如果你确定只有 reg的下半部分使用,那么您可以删除 reg1 的行, res10 , res11 ,并删除比较和混合。事实上,如果您没有 AVX2,坚持使用 SSE 并使用 128 位寄存器可能更有效。

使用 AVX2 可以显着优化一般的 32 字节改组:

//Uses AVX2
__m256i _ext_mm256_shuffle32_epi8(__m256i reg, __m256i shuf) {
__m256i regAll0 = _mm256_permute2x128_si256(reg, reg, 0x00);
__m256i regAll1 = _mm256_permute2x128_si256(reg, reg, 0x11);
__m256i resR0 = _mm256_shuffle_epi8(regAll0, shuf);
__m256i resR1 = _mm256_shuffle_epi8(regAll1, shuf);
__m256i res = _mm256_blendv_epi8(resR1, resR0, _mm256_cmpgt_epi8(_mm256_set1_epi8(16), shuf));
return res;
}

当心 : 代码未测试!

关于x86 - AVX 中的 AVX2 VPSHUFB 仿真,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32533275/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com