如何在256位AVX(YMM)寄存器中交换低128位和高128位

时间:2011-08-26 20:08:21

标签: x86 simd avx

我正在移植SSE SIMD代码以使用256位AVX扩展,并且似乎找不到任何混合/随机/移动高128位和低128位的指令。

支持故事:

我真正想要的是VHADDPS / _mm256_hadd_ps,就像HADDPS / _mm_hadd_ps一样,只有256位字。不幸的是,它就像对HADDPS的两次调用一样,独立地对低字和高字进行操作。

3 个答案:

答案 0 :(得分:17)

使用VPERM2F128,可以交换低128位和高位128位(以及其他排列)。内在的是

x = _mm256_permute2f128_ps( x , x , 1)

第三个参数是一个控制字,为用户提供了很大的灵活性。英特尔online documentation似乎完全没有解释控制字结构是什么,但可下载的Intel Instrinsic Guide应用程序提供了更好的解释。

答案 1 :(得分:2)

我知道这样做的唯一方法是使用_mm256_extractf128_si256_mm256_set_m128i。例如。交换256位向量的两半:

__m128i v0h = _mm256_extractf128_si256(v0, 0);
__m128i v0l = _mm256_extractf128_si256(v0, 1);
__m256i v1 = _mm256_set_m128i(v0h, v0l);

答案 2 :(得分:2)

x = _mm256_permute4x64_epi64(x, 0b01'00'11'10);

阅读它here。还有Try it online!

注意:此指令需要 AVX2(不仅仅是 AVX1)。

As commented by @PeterCordes 在 Zen2 / Zen3 CPU 上速度明智 _mm256_permute2x128_si256(x, x, i) 是最好的选择,尽管与我建议的函数 _mm256_permute4x64_epi64(x, i) 相比它有 3 个参数有 2 个参数.在 Zen1 和 KNL/KNM(以及推土机系列挖掘机)上,我建议的 _mm256_permute4x64_epi64(x, i) 效率更高。在其他 CPU(包括主流 Intel)上,这两种选择是相同的。

如前所述,_mm256_permute2x128_si256(x, y, i)_mm256_permute4x64_epi64(x, i) 都需要 AVX2,而 _mm256_permute2f128_si256(x, i) 只需要 AVX1。