26

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

背后的故事:

我真正想要的是VHADDPS/表现_mm256_hadd_ps得像HADDPS/ _mm_hadd_ps,只有 256 位字。不幸的是,它就像两个分别HADDPS对低位和高位单词进行操作的调用。

4

3 回答 3

29

使用 VPERM2F128,可以交换低 128 位和高 128 位(以及其他排列)。内在函数用法看起来像

x = _mm256_permute2f128_ps( x , x , 1)

第三个参数是一个控制字,它给用户很大的灵活性。有关详细信息,请参阅英特尔内部指南

于 2011-08-28T03:06:32.940 回答
3
x = _mm256_permute4x64_epi64(x, 0b01'00'11'10);

在这里阅读。并在线尝试!

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

正如@PeterCordes 在 Zen2 / Zen3 CPU 上的速度方面所评论的那样, _mm256_permute2x128_si256(x, x, i)是最好的选择,尽管它有 3 个参数,而我建议的函数_mm256_permute4x64_epi64(x, i)有 2 个参数。在 Zen1 和 KNL/KNM(以及 Bulldozer 系列挖掘机)上,我建议的_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。

于 2021-05-21T20:48:01.750 回答
2

我知道这样做的唯一方法是使用_mm256_extractf128_si256and _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);
于 2011-08-27T15:42:22.777 回答