SSE加载和添加

问题描述 投票:0回答:2

假设我有两个向量,由两个类型为

double
的数组表示,每个数组的大小为 2。我想添加相应的位置。所以假设向量
i0
i1
,我想将
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

c x86 sse simd intrinsics
2个回答
9
投票

我想你想要的是这样的:

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
时,它将第一个双精度值放入寄存器的低 64 位,将第二个双精度值放入寄存器的高 64 位。因此,在上述加载之后,
x1
保留两个
double
i0[0]
i0[1]
(与
x2
类似)。对
_mm_add_pd
的调用将
x1
x2
中的相应元素垂直相加,因此相加后,
sum
i0[0] + i1[0]
保留在其低 64 位中,将
i0[1] + i1[1]
保留在其高 64 位中。

编辑:我应该指出,使用

_mm_load_pd
代替
_mm_load_ps
没有任何好处。正如函数名称所示,
pd
变体显式加载两个压缩双精度数,
ps
版本加载四个压缩单精度浮点数。由于这些纯粹是逐位内存移动,并且它们都使用 SSE 浮点单元,因此使用
_mm_load_ps
加载
double
数据不会有任何损失。而且,
_mm_load_ps
有一个好处:它的指令编码比
_mm_load_pd
短一个字节,因此从指令缓存意义上(以及潜在的指令解码)它更有效;我不是所有复杂问题的专家现代 x86 处理器)。上面使用
_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

强制转换没有隐含任何功能;它只是使编译器将 SSE 寄存器的内容重新解释为保存双精度数而不是浮点数,以便可以将其传递到双精度算术函数

_mm_add_pd


3
投票

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

相反,您想要

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

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

v0 = _mm_add_pd(v0, v1);
© www.soinside.com 2019 - 2024. All rights reserved.