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

发布于 2024-12-01 09:54:07 字数 268 浏览 1 评论 0原文

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

背景故事:

我真正想要的是 VHADDPS/_mm256_hadd_ps 表现得像 HADDPS/_mm_hadd_ps,只有 256比特的话。不幸的是,它就像对 HADDPS 的两次调用,独立作用于低位字和高位字。

I am porting SSE SIMD code to use the 256 bit AVX extensions and cannot seem to find any instruction that will blend/shuffle/move the high 128 bits and the low 128 bits.

The backing story:

What I really want is VHADDPS/_mm256_hadd_ps to act like HADDPS/_mm_hadd_ps, only with 256 bit words. Unfortunately, it acts like two calls to HADDPS acting independently on the low and high words.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

酒解孤独 2024-12-08 09:54:07

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

x = _mm256_permute2f128_ps( x , x , 1)

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

Using VPERM2F128, one can swap the low 128 and high 128 bits ( as well as other permutations). The instrinsic function usage looks like

x = _mm256_permute2f128_ps( x , x , 1)

The third argument is a control word which gives the user a lot of flexibility. See the Intel Instrinsic Guide for details.

枯寂 2024-12-08 09:54:07
x = _mm256_permute4x64_epi64(x, 0b01'00'11'10);

阅读相关内容 此处。并且在线尝试!

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

作为评论 @PeterCordes Zen2 / Zen3 CPU 上的速度 _mm256_permute2x128_si256(x, x, i) 是最好的选择,尽管与函数 _mm256_permute4x64_epi64(x, i) 有两个参数。

在 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。

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

Read about it here. And Try it online!

Note: This instruction needs AVX2 (not just AVX1).

As commented by @PeterCordes speed-wise on Zen2 / Zen3 CPUs _mm256_permute2x128_si256(x, x, i) is the best option, even though it has 3 arguments compared to function _mm256_permute4x64_epi64(x, i) suggested by me having 2 arguments.

On Zen1 and KNL/KNM (and Bulldozer-family Excavator), _mm256_permute4x64_epi64(x, i) suggested by me is more efficient. On other CPUs (including mainstream Intel), both choices are equal.

As already said both _mm256_permute2x128_si256(x, y, i) and _mm256_permute4x64_epi64(x, i) need AVX2, while _mm256_permute2f128_si256(x, i) needs just AVX1.

寂寞清仓 2024-12-08 09:54:07

据我所知,执行此操作的唯一方法是使用 _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);

The only way that I know of doing this is with _mm256_extractf128_si256 and _mm256_set_m128i. E.g. to swap the two halves of a 256 bit vector:

__m128i v0h = _mm256_extractf128_si256(v0, 0);
__m128i v0l = _mm256_extractf128_si256(v0, 1);
__m256i v1 = _mm256_set_m128i(v0h, v0l);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文