你正在使用的Go版本是什么( go version
)?
master:go version devel +cd1976d Tue May 8 19:57:49 2018 +0000 linux/amd64
这个问题在最新版本中是否会重现?
是的
你正在使用什么操作系统和处理器架构( go env
)?
GOARCH="amd64"
GOBIN=""
GOCACHE="/localdisk/itocar/gocache/"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/localdisk/itocar/gopath"
GORACE=""
GOROOT="/localdisk/itocar/golang"
GOTMPDIR=""
GOTOOLDIR="/localdisk/itocar/golang/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build948974604=/tmp/go-build -gno-record-gcc-switches"
你做了什么?
运行strconv/Atof基准测试
你期望看到什么?
性能与1.10相同或更好
你看到了什么?
Atof64Decimal-8 20.9ns ± 1% 20.3ns ± 2% -3.11% (p=0.000 n=10+10)
Atof64Float-8 22.9ns ± 1% 23.1ns ± 2% +0.83% (p=0.042 n=10+10)
Atof64FloatExp-8 56.3ns ± 3% 68.8ns ± 2% +22.11% (p=0.000 n=10+10)
Atof64Big-8 84.0ns ± 1% 94.0ns ± 1% +11.91% (p=0.000 n=10+10)
Atof64RandomBits-8 72.9ns ±15% 80.5ns ±24% +10.47% (p=0.022 n=10+9)
Atof64RandomFloats-8 80.2ns ±25% 91.6ns ±19% +14.27% (p=0.029 n=10+10)
Atof32Decimal-8 20.1ns ± 2% 20.5ns ± 2% +1.59% (p=0.008 n=10+10)
Atof32Float-8 21.5ns ± 3% 21.9ns ± 3% +2.09% (p=0.012 n=10+10)
Atof32FloatExp-8 58.6ns ± 3% 68.2ns ± 2% +16.49% (p=0.000 n=10+10)
Atof32Random-8 93.8ns ± 0% 86.4ns ± 0% -7.83% (p=0.000 n=10+8)
二分查找指向a35ec9a
查看代码后,我发现(*extFloat).Normalize变慢了,可能是因为分支预测很好,而且大多数指令都依赖于分支的结果。
看起来生成CMOV的启发式方法应该进行调整,但我不确定如何操作。当前的阈值很低,进一步降低可能会对其他情况产生性能影响。也许我们应该避免生成长链的依赖CMOV?
5条答案
按热度按时间exdqitrt1#
@rasky
1zmg4dgp2#
比较软件包
strings
在Go tip和Go 1.10.2上的差异:主要回归发生在a35ec9a(1675ns/op -> 3201ns/op)。
jum4pzuy3#
通过粗略的观察,似乎回归基准总是使用固定输入执行代码。例如,如果你查看
Atof64FloatExp
(+22% 的低方差),它是:所以它总是解析相同的数字,因此CPU能够很好地预测接下来会发生什么。同样适用于
SingleMaxSkipping
:所以,是的,如果分支预测得很好,CMOV 可以变慢。@TocarIP 你用于基准测试的确切CPU型号是什么?
另一方面,在随机输入的情况下,它确实更快:
我不确定该怎么办。
PS:@TocarIP FWIW,
(*extFloat).Normalize
应该使用bits.LeadingZeros64
并避免一开始的所有分支:fd3cxomn4#
https://golang.org/cl/113256提到了这个问题:
strconv: simplify (*extFloat).Normalize
vc9ivgsu5#
我使用了i7-6700。同意关于(*extFloat).Normalize的看法。
顺便说一下,在singleMaxSkipping cmov中,只生成了内联的
指令。这是我们想要生成CMOV的情况,同时gcc/clang也生成了CMOV。