假设我有两个 vector ,由两个 double
类型的数组表示,每个数组的大小为 2。我想添加相应的位置。所以假设 vector 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位和高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
保存了两个 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
变体显式加载两个压缩 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/