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 变量进行操作,就像 +
和 *
与 int
或 float
类型一样。通常这些编译为对寄存器进行操作的 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
}
我正在向 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 变量进行操作,就像 +
和 *
与 int
或 float
类型一样。通常这些编译为对寄存器进行操作的 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
}