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传递(通过指针)到结果数组?
内在函数返回计算结果,因此您可以将其存储在变量中或将其用作另一个参数.
这里要注意的一件重要事情是,大多数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)
"存储结果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变量进行操作,就好像+和*用int或float类型.通常这些编译为对寄存器进行操作的asm指令(或者如果它结合了加载和添加内部函数,则可能是内存源操作数),但将所有这些留给编译器是使用内在函数的关键.
您确实希望编写代码以便可以高效编译:如果超过16个__m128变量一次"存活",编译器将不得不溢出/重新加载它们.