【问题标题】:How to set all elements in a __m256d to, say, the 3rd element of another __m256d?如何将 __m256d 中的所有元素设置为另一个 __m256d 的第三个元素?
【发布时间】:2023-12-31 16:25:01
【问题描述】:

使用 4 个打包的 float (__m128),我可以使用 SSE 内在函数

__m128 X;
__m128 H = _mm_shuffle_ps(X,X,_MM_SHUFFLE(3,3,3,3));

H的所有元素设置为X的第三个元素(这是最快的方法吗?)

现在,我想对 4 个打包的 double (__m256d) 做同样的事情。我天真地编码

__m256d X;
__m256d H = _mm256_shuffle_pd(X,X,_MM_SHUFFLE(3,3,3,3));

但这并不正确!相反,它设置 H={X[1],X[1],X[3],X[3]}。

那么,怎么做才对呢?

编辑

使用 Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz

【问题讨论】:

  • 256 位向量没有等价物。您需要使用两个 shuffle/permute instrinsics,因为一个只能在 128 位块中置换,另一个不能跨 128 位边界置换。
  • @Mysticial 好。那么你能提供所需的代码(作为答案)吗?否则,我会自己弄清楚(并回答我自己的问题)。
  • 也许稍后。我有课。

标签: sse avx


【解决方案1】:

这并不总是最优的,但询问你的编译器它认为什么可能是一个很好的提示。

#include <x86intrin.h>
__m256d f(__m256d x){
  __m256i m={3,3,3,3};
  return __builtin_shuffle(x,m);
}

使用 gcc-4.8,这会生成:

vpermilpd   $15, %ymm0, %ymm0
vperm2f128  $17, %ymm0, %ymm0, %ymm0

clang 有一个不同的内置用于洗牌,我不知道其他编译器是否有。

【讨论】:

    【解决方案2】:

    好的,在 Mystical 的 cmets 之后,我可以自己解决:

    template<int K>
    inline __mm256d pick_single(__m256d x)
    {
       __m256 t = _mm256_permute2f128_pd(x,x, K&2?49:32);
       return _mm256_permute_pd(t,K&1?15:0);
    }
    

    产生所需的结果。感谢您的帮助,神秘主义者!

    【讨论】:

      最近更新 更多