SSE加载和添加

假设我有两个向量由两个double类型的数组表示,每个数组大小为2.我想添加相应的位置。 因此假设向量i0i1 ,我想将i0[0] + i1[0]i0[1] + i1[1]在一起。

由于类型是double ,我需要两个寄存器。 诀窍是将i0[0]i1[0] ,以及i0[1]i1[1]放在另一个中,只需添加寄存器即可。

我的问题是,如果我调用_mm_load_ps(i0[0])然后_mm_load_ps(i1[0]) ,它会将它们分别置于低位和高位64位,还是会用第二次load替换寄存器? 如何将两个双打放在同一个寄存器中,以便我可以在之后调用add_ps

谢谢,

我想你想要的是这个:

 double i0[2]; double i1[2]; __m128d x1 = _mm_load_pd(i0); __m128d x2 = _mm_load_pd(i1); __m128d sum = _mm_add_pd(x1, x2); // do whatever you want to with "sum" now 

当你执行_mm_load_pd ,它将第一个双_mm_load_pd放入寄存器的低64位,第二个放入高16位。 因此,在上面的负载之后, x1保持两个doublei0[0]i0[1] (并且类似于x2 )。 对_mm_add_pd的调用会在x1x2垂直添加相应的元素,因此在sum后, sum在其低64位中保持i0[0] + i1[0]在高64位中保持i0[1] + i1[1]

编辑:我应该指出使用_mm_load_pd而不是_mm_load_ps没有任何好处。 正如函数名称所示, pd种类显式加载两个打包的双精度数, ps版本加载四个打包的单精度浮点数。 由于这些是纯粹的逐位内存移动并且它们都使用SSE浮点单元,因此使用_mm_load_ps加载double数据_mm_load_ps受到惩罚。 并且, _mm_load_ps有一个好处:它的指令编码比_mm_load_pd短一个字节,因此它从指令高速缓存的意义上来说更有效(并且可能是指令解码;我不是现代x86处理器所有复杂function的专家)。 使用_mm_load_ps的上述代码如下所示:

 double i0[2]; double i1[2]; __m128d x1 = (__m128d) _mm_load_ps((float *) i0); __m128d x2 = (__m128d) _mm_load_ps((float *) i1); __m128d sum = _mm_add_pd(x1, x2); // do whatever you want to with "sum" now 

演员没有隐含的function; 它只是让编译器将SSE寄存器的内容重新解释为保持双精度而不是浮点数,以便它可以传递给双精度算术函数_mm_add_pd

_ps前缀是“packed single”的缩写,意味着它用于单精度浮点,而不是双精度。

相反,你想要_mm_load_pd() 。 此函数采用一个16字节对齐的指针指向两个double的数组的第一个成员,并加载它们。 所以你会像这样使用它:

 __m128d v0 = _mm_load_pd(i0); __m128d v1 = _mm_load_pd(i1); v0 = _mm_add_pd(v0, v1);