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

mar*_*zzz 3 c++ sse simd intrinsics sse2

我正在用C++将第一步移到SSE2中.这是我现在正在学习的内在:

__m128d _mm_add_pd (__m128d a, __m128d b)
Run Code Online (Sandbox Code Playgroud)

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

但我从未传递dst过这个功能.那么,如果我不传递它,它怎么能添加两个双I传递(通过指针)到结果数组?

Tob*_*zel 6

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

这里要注意的一件重要事情是,大多数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
}
Run Code Online (Sandbox Code Playgroud)


Typ*_*eIA 5

"存储结果dst"的描述有点误导.内部函数返回向量加法的结果作为类型的值__m128d.

__m128d arg1 = ...;
__m128d arg2 = ...;
__m128d result = _mm_add_pd(arg1, arg2);
Run Code Online (Sandbox Code Playgroud)

如果您调用变量dst而不是result,那么您有适合描述的代码.(但你可以随意调用它.)

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

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

您确实希望编写代码以便可以高效编译:如果超过16个__m128变量一次"存活",编译器将不得不溢出/重新加载它们.

  • @markzzz它不是指针或`typedef`,它是一个opaque类型,编译器知道如何处理.这是我提到的抽象.编译器知道`ADDPD`输出进入`xmm1`并从那里它将管理值,但它需要基于你对C中的变量所做的事情. (3认同)