随机播放 AVX 寄存器中的元素

Posted

技术标签:

【中文标题】随机播放 AVX 寄存器中的元素【英文标题】:Shuffle elements in AVX register 【发布时间】:2017-03-05 12:09:47 【问题描述】:

我有一个向量,其双精度值存储在 AVX 寄存器中,其元素为 a0,a1,a2,a3。现在,我想创建三个新向量(也应该存储为__m256d 变量),比如说 b、c 和 d,包含以下元素:

b = a0,a1,a0,a0
c = a1,a2,a2,a1
d = a2,a3,a3,a2

如何使用 AVX 做到这一点?

【问题讨论】:

您的意思是仅使用 AVX1?如果可以使用AVX2,效率更高:b = _mm256_permute4x64_pd(a, _MM_SHUFFLE(0,1,0,0)); 【参考方案1】:

看看编译器是如何做到的,使用gcc 向量扩展-march=core-avx2

#include <stdint.h>

typedef double v4df __attribute__((vector_size(32)));
typedef uint64_t v4u64 __attribute__((vector_size(32)));

void foo(v4df a, v4df *b, v4df *c, v4df *d)

  *b = __builtin_shuffle(a, (v4u64)0, 1, 0, 0);
  *c = __builtin_shuffle(a, (v4u64)1, 2, 2, 1);
  *d = __builtin_shuffle(a, (v4u64)2, 3, 3, 2);

gcc-4.8.4 -march=core-avx2 -O3 产生:

vpermpd $4, %ymm0, %ymm1
vmovapd %ymm1, (%rdi)
vpermpd $105, %ymm0, %ymm1
vpermpd $190, %ymm0, %ymm0
vmovapd %ymm1, (%rsi)
vmovapd %ymm0, (%rdx)
vzeroupper
ret

gcc-4.8.4 -march=corei7-avx -O3 产生:

vinsertf128 $1, %xmm0, %ymm0, %ymm1
vpermilpd   $2, %ymm1, %ymm1
vmovapd %ymm1, (%rdi)
vperm2f128  $33, %ymm0, %ymm0, %ymm1
vshufpd $9, %ymm1, %ymm0, %ymm1
vmovapd %ymm1, (%rsi)
vperm2f128  $49, %ymm0, %ymm0, %ymm0
vpermilpd   $6, %ymm0, %ymm0
vmovapd %ymm0, (%rdx)
vzeroupper
ret

【讨论】:

以上是关于随机播放 AVX 寄存器中的元素的主要内容,如果未能解决你的问题,请参考以下文章

AVX2:AVX 寄存器中 8 位元素的 CountTrailingZeros

如何将 AVX512 寄存器 zmm26 中的 QuadWord 写入 rax 寄存器?

测试 256 位 YMM AVX 寄存器元素是不是等于或小于零的最有效方法

当使用带有 AVX-512 加载和存储的屏蔽寄存器时,是不是会因对屏蔽元素的无效访问而引发错误?

从填充为 0 的数组加载到 256 位 AVX2 寄存器

我可以正确比较 avx 中的零寄存器吗?