SSE2内部函数在哪里存储结果? 我将C++中的第一步移动到SSE2中。我现在学到的本质是: __m128d _mm_add_pd (__m128d a, __m128d b)

SSE2内部函数在哪里存储结果? 我将C++中的第一步移动到SSE2中。我现在学到的本质是: __m128d _mm_add_pd (__m128d a, __m128d b),c++,sse,simd,intrinsics,sse2,C++,Sse,Simd,Intrinsics,Sse2,文档中说:在a和b中添加压缩双精度(64位)浮点元素,并将结果存储在dst中 但我从未将dstdst传递给该函数。那么,如果我没有传递,它如何向结果数组添加两个double I pass(通过指针)?描述“将结果存储在dst”有点误导。本征函数将向量相加的结果作为类型为\uuu m128d的值返回 __m128d arg1 = ...; __m128d arg2 = ...; __m128d result = _mm_add_pd(arg1, arg2); 如果调用变量dst而不是result

文档中说:在a和b中添加压缩双精度(64位)浮点元素,并将结果存储在dst中

但我从未将dst
dst
传递给该函数。那么,如果我没有传递,它如何向结果数组添加两个double I pass(通过指针)?

描述“将结果存储在
dst
”有点误导。本征函数将向量相加的结果作为类型为
\uuu m128d
的值返回

__m128d arg1 = ...;
__m128d arg2 = ...;
__m128d result = _mm_add_pd(arg1, arg2);
如果调用变量
dst
而不是
result
,则代码符合描述。(但你可以随意称呼它。)

底层SSE指令将操作结果存储在其选择的XMM寄存器中。编译器将进行寄存器分配(如果寄存器用完,甚至存储/重新加载C向量变量,或者围绕一个函数调用来对向量寄存器进行破坏)

内部函数对C变量进行操作,就像
+
*
使用
int
float
类型一样。通常,这些编译为asm指令在寄存器上操作(或者如果它结合了load和add内在函数,则可能是内存源操作数),但将所有这些留给编译器是使用内在函数的重点


不过,您确实希望编写代码,使其能够高效编译:如果同时有16个以上的
\uuum128
变量处于“活动”状态,编译器将不得不溢出/重新加载它们。

内部函数返回计算结果,因此您可以将其存储在变量中或将其用作另一个参数

这里需要注意的一点是,大多数SIMD指令并不直接在内存上运行,但您需要显式加载(
\u mm\u load(u)\u pd
)并存储(
\u mm\u store(u)\u pd
)双值,就像您在汇编中所做的那样。中间值很可能存储在SSE寄存器中,或者如果使用的寄存器太多,则存储在堆栈上

如果你想把两个双数组求和,你可以做如下的事情

double a[N];
double b[N];
double c[N];
for (int i = 0; i < N; i += 2) {  // We load two doubles every time
    auto x = _mm_loadu_pd(a + i); // We don't know anything about alignment
    auto y = _mm_loadu_pd(b + i); // So I assume the load is unaligned
    auto sum = _mm_add_pd(x, y);  // Compute the vector sum
    _mm_storeu_pd(c + i, sum);    // The store is unaligned as well
}
双a[N];
双b[N];
双c[N];
对于(inti=0;i
但是
\uuu m128d
不是一种
typedef-double
指针吗?如果我不分配
结果
数组,该代码如何工作?@markzzz它不是指针或
类型定义
,它是一种不透明类型,编译器知道如何处理。这就是我提到的抽象概念。编译器知道,
ADDPD
输出进入
xmm1
,从那里它将管理值,但是它需要基于您对C中的变量所做的操作。因此我不理解
\um128d
是什么。那么呢?GCC和MSVC也这样做吗?C++标准?有文档吗?与这个问题不完全相关,只是为了精确:ADDPD指令可以将其结果存储到任何xmm寄存器中,而不仅仅是xmm1。在链接文档中使用xmm1有点误导。物理上作为堆栈变量的xmm128d只是XMM硬件寄存器的代理。编译器负责调度指令并跟踪寄存器文件,因此您实际上不知道或不关心它映射到哪个寄存器。对于x64,可用的
XMM
比x86多。英特尔和MSVC也认为>M128D < /代码>是一种结构,因此您可以使用它来将16字节对齐的内存转换为相同的“类型”,但是Gcc/CLAN不支持这一点,并将代码< >代码M128D < /C>作为不透明类型。另见。