c - SSE加载和添加

标签 c x86 sse simd intrinsics

假设我有两个 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 位,还是会用第二个 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_pdx1中垂直添加对应的元素和 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/

相关文章:

cpu-architecture - 什么是打包和解包和扩展打包数据

C简单程序

c - MbedTLS 和 .NET BouncyCaSTLe 与 Curve25519 的互操作性问题

汇编:__p___argv 的返回值

c++ - 使用 Ivy Bridge 和 Haswell 循环展开以实现最大吞吐量

c - 简化函数

c - ISO C Void * 和函数指针

c - 通过时间延迟增加整数

arrays - 汇编语言中的数组冒泡排序

assembly - cmp 时设置 CF