从 __m256 中选择元素子集?

Posted

技术标签:

【中文标题】从 __m256 中选择元素子集?【英文标题】:Select subset of elements from __m256 ? 【发布时间】:2016-09-08 06:25:16 【问题描述】:

我有一个__m256,用来存放8个浮点数,里面的元素是这样的:

__m256 v = 0,1,2,3,4,5,6,7;

现在我想获得另一个 __m256 值,例如:

__m256 dst = 0,1,2,4,5,6,x,x;

x 这里的意思是我不在乎。

我不熟悉 SIMD,有人可以帮忙吗?或者给我一些提示?

谢谢!

【问题讨论】:

详细信息取决于您用于访问 SIMD 指令的库。我猜__m256 表示一些英特尔的东西。 @Cheersandhth.-Alf 是的,我在支持 AVX2 的 Intel CPU 上使用 GCC。 也许看看英特尔的文档,然后呢?我很确定也必须有教程。我从来没有研究过这些东西。 你打算如何处理结果?如果您在打包和填充的 vec3 格式之间进行复制,则可以只使用 128b 加载/存储,并将存储重叠一个元素。如果您可以使用 AVX2,那么加载/随机播放/存储重叠的两个元素可能会更快,就像您提议的那样。 【参考方案1】:

您可以使用 AVX2 内在 _mm256_permutevar8x32_ps。它可以帮助您对 256 位向量中的元素进行混洗。请参阅下面的示例:

__m256 a =  10, 20, 30, 40, 50, 60, 70, 80 ;
__m256i k = _mm256_setr_epi32(0, 1, 2, 4, 5, 6, 0, 0);
__m256 b = _mm256_permutevar8x32_ps(a, k);

【讨论】:

【参考方案2】:

您需要一条能够在 128 位通道上运行的指令。不幸的是,大多数 AVX/AVX2 shuffle/permute 指令只能在 256 位 AVX 向量的两个 128 位通道内运行,但也有一些没有此限制。在这种特殊情况下,您要查找的内在函数是 _mm256_permutevar8x32_ps:

#include <stdio.h>
#include <immintrin.h>

int main(void)

    __m256 v0 = _mm256_setr_ps(0, 1, 2, 3, 4, 5, 6, 7);
    __m256i vperm = _mm256_setr_epi32(0, 1, 2, 4, 5, 6, 0, 0);

    __m256 v1 = _mm256_permutevar8x32_ps(v0, vperm);

    float f0[8], f1[8];

    _mm256_storeu_ps(f0, v0);
    _mm256_storeu_ps(f1, v1);

    printf("v0: %g %g %g %g %g %g %g %g\n", f0[0], f0[1], f0[2], f0[3], f0[4], f0[5], f0[6], f0[7]);
    printf("v1: %g %g %g %g %g %g %g %g\n", f1[0], f1[1], f1[2], f1[3], f1[4], f1[5], f1[6], f1[7]);

    return 0;

编译测试:

$ gcc -Wall -mavx2 blackball.c 
$ ./a.out 
v0: 0 1 2 3 4 5 6 7
v1: 0 1 2 4 5 6 0 0

【讨论】:

以上是关于从 __m256 中选择元素子集?的主要内容,如果未能解决你的问题,请参考以下文章

有符号 32 位元素的 AVX __m256i 整数除法

将向量的特定元素广播到另一个向量

tyvj P4877 _1.组合数

编程之美_集合

基于布尔掩码将元素移动到 SIMD 寄存器的左侧

算法—— 集合的子集