第一个版本通过将值从内存移动到局部变量来进行优化.第二个版本没有.
我原本期望编译器可能会选择在这里进行localValue优化,而不是在循环的每次迭代中从内存中读取和写入值.为什么不呢?
class Example { public: void processSamples(float * x,int num) { float localValue = v1; for (int i = 0; i < num; ++i) { x[i] = x[i] + localValue; localValue = 0.5 * x[i]; } v1 = localValue; } void processSamples2(float * x,int num) { for (int i = 0; i < num; ++i) { x[i] = x[i] + v1; v1 = 0.5 * x[i]; } } float v1; };
processSamples组装成代码如下:
.L4: addss xmm0,DWORD PTR [rax] movss DWORD PTR [rax],xmm0 mulss xmm0,xmm1 add rax,4 cmp rax,rcx jne .L4
processSamples2到此:
.L5: movss xmm0,DWORD PTR [rax] addss xmm0,DWORD PTR example[rip] movss DWORD PTR [rax],xmm1 movss DWORD PTR example[rip],xmm0 add rax,rdx jne .L5
因为编译器不必担心线程(v1不是原子的).难道不能只是假设没有别的东西会看到这个值并继续在循环旋转时将它保存在寄存器中吗?
有关完整装配和一系列可供选择的编译器,请参阅https://godbolt.org/g/RiF3B4!