C语言 SSE加载和添加

xfyts7mz  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(116)

假设我有两个向量,由两个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位和高64位中,还是会用第二个load替换寄存器?如何将两个double放在同一个寄存器中,以便在之后调用add_ps

mf98qq94

mf98qq941#

我想你想要的是这个

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时,它将第一个double值放入寄存器的低64位,第二个放入寄存器的高64位。因此,在上面的加载之后,x1保存两个doublei0[0]i0[1]x2也类似)。对_mm_add_pd的调用垂直地添加了x1x2中的相应元素,因此在添加之后,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_pd短一个字节,因此从指令高速缓存感测(以及潜在的指令解码;我不是现代x86处理器所有复杂性的Maven)。上面使用_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中。

k3bvogb1

k3bvogb12#

_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);

相关问题