两个类似的汇编代码.实质性的差异

Gil*_*esz 3 optimization x86

我有常春藤桥CPU.以下代码每次迭代需要3个周期:

L1:    
    movapd xmm1, [rsi+rax] ; X[i], X[i+1]
    mulpd xmm1, xmm2
    movapd xmm0, [rdi+rax] ; Y[i], Y[i+1]
    subpd xmm0, xmm1
    movapd [rdi+rax], xmm0 ; Store result
    add rax, 16
    cmp rax, rcx
    jl L1
Run Code Online (Sandbox Code Playgroud)

以下每次迭代需要9个周期:

L1:
    movapd xmm1, [rsi+rax] ; X[i], X[i+1]
    mulpd xmm1, xmm2
    movapd xmm0, [rdi+rax] ; Y[i], Y[i+1]
    add rax, 16
    subpd xmm0, xmm1
    movapd [rdi+rax], xmm0 ; Store result
    cmp rax, rcx
    jl L1
Run Code Online (Sandbox Code Playgroud)

唯一的区别是order(add rax, 16).并且它导致程序慢3倍.为什么差异如此之大?

Chr*_*odd 5

主要原因是它将结果存储在不同的位置,这也恰好是循环的下一次迭代读取的位置.

这样做会干扰CPU的无序执行 - 由于数据依赖性,在当前迭代完成之前,循环的下一次迭代无法启动.

我想如果你将存储指令更改为存储回同一位置,第二个循环将再次变得更快:

movapd [rdi+rax-16], xmm0 ; Store result
Run Code Online (Sandbox Code Playgroud)