在AMD Phenom II上,微小的SSE addpd循环比标量略慢?

zeb*_*h49 4 c c++ assembly gcc sse

是的,我读的SIMD代码运行速度比标量代码慢.不,这不是真的重复.

我一直在使用2D数学的东西,并且在将我的代码库从C移植到C++的过程中.我用C打了一些墙,这意味着我真的需要多态,但这是另一个故事.无论如何,我刚才考虑过这个,但它提供了一个使用2D矢量类的绝佳机会,包括常见数学运算的SSE实现.是的,我知道那里有图书馆,但我想亲自去试一下,了解发生了什么,我不会使用比这更复杂的东西+=.

我的实现是通过<immintrin.h>,一个

union {
    __m128d ss;
    struct {
        double x;
        double y;
    }
}
Run Code Online (Sandbox Code Playgroud)

SSE似乎很慢,所以我查看了它生成的ASM输出.在用指针修复一些愚蠢的东西后,我最终得到了以下几组指令,循环运行了十亿次:(处理器是3.7GHz的AMD Phenom II)

SSE启用:1.1到1.8秒(变化)

add      $0x1, %eax
addpd    %xmm0, %xmm1
cmp      $0x3b9aca00, %eax
jne      4006c8
Run Code Online (Sandbox Code Playgroud)

SSE禁用:1.0秒(相当不变)

add      $0x1, %eax
addsd    %xmm0, %xmm3
cmp      $0x3b9aca00, %eax
addsd    %xmm2, %xmm1
jne      400630
Run Code Online (Sandbox Code Playgroud)

我可以从中得出的唯一结论是,addsd速度快于addpd,并且流水线操作意味着额外指令可以通过更快速地部分重叠的能力来补偿.

所以我的问题是:这是否值得,在实践中它实际上会有所帮助,或者我应该不打扰愚蠢的优化并让编译器在标量模式下处理它?

Joe*_*cou 7

这需要更多的循环展开,并且可能需要缓存预取.您的算术密度非常低:1次操作用于2次内存操作,因此您需要尽可能多地将这些内容堵塞在管道中.

另外,不要直接使用union而是使用__m128d,并使用_mm_load_pd从数据中填充__m128.联合中的_m128会生成错误的代码,其中所有元素都在进行堆栈寄存器堆栈跳舞,这是有害的.