SSE2 内在函数在哪里存储结果?

Where do SSE2 intrinsics store results?

我正在向 C++ 中的 SSE2 迈出第一步。 Here's 我现在正在学习的内在知识:

__m128d _mm_add_pd (__m128d a, __m128d b)

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

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

描述"store the results in dst"有点误导。内在函数 returns 向量相加的结果作为 __m128d.

类型的值
__m128d arg1 = ...;
__m128d arg2 = ...;
__m128d result = _mm_add_pd(arg1, arg2);

如果您调用变量 dst 而不是 result,那么您的代码符合描述。 (但你可以随便叫它。)

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

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

您确实希望编写代码以使其 可以 高效编译,但是:如果超过 16 个 __m128 变量同时是 "alive",编译器将不得不 spill/reload 它们。

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

这里要注意的一件重要事情是,大多数 SIMD 指令不直接在内存上操作,但您需要显式加载 (_mm_load(u)_pd) 和存储 (_mm_store(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
}