假设我有两个 vector ,由两个 double 类型的数组表示,每个数组的大小为 2。我想添加相应的位置。所以假设 vector 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

谢谢,

最佳答案

我想你想要的是这个:

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 中的相应元素垂直相加,因此相加后, sumi0[0] + i1[0] 保存在其低 64 位,将 i0[1] + i1[1] 保存在其高 64 位。

编辑: 我应该指出使用 _mm_load_pd 而不是 _mm_load_ps 没有任何好处。正如函数名称所示,pd 变体显式加载两个压缩 double 数,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 寄存器的内容重新解释为保存 double 数而不是浮点数,以便将其传递给 double 算术函数 _mm_add_pd

关于c - SSE加载和添加,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9255027/

10-11 15:33