simd矢量访问

the*_*ast 6 c x86 simd intrinsics sse2

我是SIMD编程的新手,我有一些基本的问题,我现在看了几天后似乎无法弄清楚.

我想要优化的代码基本上是一个简单但很大的算术公式,自动分析coude并行计算独立的乘法/加法应该相当简单,但我读到自动向量化仅适用于循环.

我已多次阅读,因为应该不惜一切代价避免通过联合或其他方式访问矢量中的单个元素,而应该替换为_mm_shuffle_pd(我只处理双打)...

我知道这是一个非常基本的问题,但我似乎并不知道如何将__m128d向量的内容存储为双精度而不将其作为联合访问.此外,与标量代码相比,这样的操作能否带来任何性能提升?

union {
  __m128d v;
  double d[2];
} vec;
union {
  __m128d v;
double d[2];
} vec2;

vec.v = index1;
vec2.v = index2;
temp1 = _mm_mul_pd(temp1, _mm_set_pd(bvec[vec.d[1]], bvec[vec2[1]]));
Run Code Online (Sandbox Code Playgroud)

此外,两个工会看起来很丑陋,但在使用时

union dvec {
  __m128d v;
  double d[2];
} vec;
Run Code Online (Sandbox Code Playgroud)

试图将indexX声明为dvec,编译器抱怨dvec未声明

Ton*_*ion 7

不幸的是,如果你看一下MSDN,它会说:

不应直接访问 __m128d字段.但是,您可以在调试器中看到这些类型.__m128类型的变量映射到XMM [0-7]寄存器.

我不是SIMD的专家,但是这告诉我你正在做的事情不会起作用,因为它不是为了设计的.

编辑:

我刚发现了这个,它说:

仅在赋值的左侧使用__m128,__ m128d和__m128i,作为返回值或作为参数.不要在其他算术表达式中使用它,例如"+"和">>".

它还说:

在聚合中使用__m128,__ m128d和__m128i对象,例如联合(例如,访问浮点元素)和结构.

所以也许你可以使用它们,但只能在工会中使用它们.然而,似乎与MSDN所说的相矛盾.

EDIT2:

这是另一个有趣的资源,它描述了如何使用这些SIMD类型的示例

在上面的链接中,您将找到以下行:

#include <math.h>
#include <emmintrin.h>
double in1_min(__m128d x)
{
    return x[0];
}
Run Code Online (Sandbox Code Playgroud)

在上面我们使用gcc 4.6中的新扩展来通过索引访问高低部分.较旧版本的gcc需要使用union并写入两个双精度数组.这很麻烦,并且在关闭优化时会非常慢.