我想你想要的是这样的:
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位到上16位。因此,在上述负荷后,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
。
你当然可以使用'_mm_load_ps',但风险在其上设计了这样一种方式的假设未来处理器性能的下降,有单间域旁路处罚和双精度浮点运算。我知道没有这样的处理器的计划,但这并不是说永远不会实施;这就是为什么有不同的加载操作。诚然,这是一个遥远的可能性,但为什么冒这个险呢? – 2012-02-13 15:32:51
我同意未来的处理器存在性能下降的风险。我建议人们考虑(即衡量)通过在特定应用的基础上使用“MOVPS”而不是“MOVPD”来获得任何性能优势。如果今天使用它是有好处的,并且没有迹象表明即将到来的架构会有这样的惩罚,我会这样做。像这样的负载可以很容易地被抽象化,以允许将来自动切换到不同的实现。 – 2012-02-13 16:41:58