我正在移植SSE SIMD代码以使用256位AVX扩展,并且似乎找不到任何混合/随机/移动高128位和低128位的指令。
支持故事:
我真正想要的是VHADDPS
/ _mm256_hadd_ps
,就像HADDPS
/ _mm_hadd_ps
一样,只有256位字。不幸的是,它就像对HADDPS
的两次调用一样,独立地对低字和高字进行操作。
答案 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。