假设我有两个 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 位,还是会用第二个 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
variety 显式加载两个打包的 double 和 ps
version 加载四个打包的单精度 float 。由于这些纯粹是逐位内存移动,并且它们都使用 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 而不是 float ,以便它可以传递给 double 算术函数 _mm_add_pd
.
关于c - SSE加载和添加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9255027/