Performance Go运行时是否在每次迭代中评估for循环条件?

Performance Go运行时是否在每次迭代中评估for循环条件?,performance,go,compiler-optimization,Performance,Go,Compiler Optimization,以下是《Go编程语言》一书中的代码片段: t:=0.0时的;t

以下是《Go编程语言》一书中的代码片段:

t:=0.0时的
;t

似乎for循环条件
t
中的表达式必须在for循环的每次迭代之前求值。或者,编译器是否通过预先计算表达式的结果(假设在迭代过程中没有任何变量发生变化)来对此进行优化?上述编码风格是否会影响性能?

它似乎没有经过优化,也没有列在“”中

如中所述

gc编译器不执行任何循环优化。该编译器的主要目标之一是快速编译。虽然改进的优化总是有用的,但它必须符合这一目标

但这本可以改变的。“”中说明了一种很好的技术,可以查看go程序生成的汇编代码。
另请参见最近的2016年“”文章。
和“”也有帮助:请参阅

您可以看到始终计算的“
t
”部分

.L2:
        movsd   xmm0, QWORD PTR [rbp-24]
        addsd   xmm0, xmm0
        movsd   xmm1, QWORD PTR .LC2[rip]
        mulsd   xmm0, xmm1
        ucomisd xmm0, QWORD PTR [rbp-8]
        seta    al
        test    al, al

这实际上取决于Go版本,但Go版本go1.7 windows/amd64确实会计算一次该值

Go代码:

var cycles = 10.0
var res = 1000.0
for t := 0.0; t < cycles*2*math.Pi; t += res {
}
f64_404f6a7a2955385e
是一个预先计算的双精度值,等于
10*2*math.Pi
62.8318530718

转到编译器,这样这些优化将不断改进,因为它们从中受益匪浅。目前,SSA仅在amd64上提供:

编译器工具链 此版本包括用于64位x86的新代码生成后端 系统,根据2015年的提案,该提案正在开发中 从那时起新的后端基于SSA,可生成更紧凑、更灵活的 高效的代码,并为优化提供更好的平台,例如 边界检查消除

:

编译器工具链 Go 1.7为64位x86系统引入了新的编译器后端。围棋 1.8,该后端已得到进一步开发,目前已用于所有 架构


当前Go编译器不会将循环不变计算移到循环之外

编译器的过程列表可以在这里看到

在@creker的示例中,编译器执行常量折叠,而不是循环不变的代码运动

作为旁注,几个月前我确实为Go编译器通过了LICM


在通常使用的Go基准上,这并不能极大地提高性能。(我谴责糟糕的寄存器分配:P)

这似乎比我的答案更准确+1当前编译器是否与1.7或1.8 beta版本相同2?这是否意味着我的答案比克雷克的更准确?在1.7中?在1.8中仍然是这样吗?是的,适用于所有版本,包括master branch.OK。这似乎证实了我在回答中提到的+1.
var cycles = 10.0
var res = 1000.0
for t := 0.0; t < cycles*2*math.Pi; t += res {
}
movsd   [rsp+58h+var_20], xmm0
mov     [rsp+58h+var_18], 0
mov     [rsp+58h+var_10], 0
lea     rax, qword_494500
mov     [rsp+58h+var_58], rax
lea     rax, [rsp+58h+var_20]
mov     [rsp+58h+var_50], rax
mov     [rsp+58h+var_48], 0
call    runtime_convT2E
mov     rax, [rsp+58h+var_40]
mov     rcx, [rsp+58h+a] ; a
mov     [rsp+58h+var_18], rax
mov     [rsp+58h+var_10], rcx
lea     rax, [rsp+58h+var_18]
mov     [rsp+58h+var_58], rax
mov     [rsp+58h+var_50], 1
mov     [rsp+58h+var_48], 1
call    fmt_Println
movsd   xmm0, cs:$f64_408f400000000000
movsd   xmm1, [rsp+58h+t]
addsd   xmm0, xmm1
movsd   [rsp+58h+t], xmm0
movsd   xmm1, cs:$f64_404f6a7a2955385e
ucomisd xmm1, xmm0
ja      loc_401083