登录
首页 >  Golang >  Go问答

在Go基准测试中为什么同一份代码的执行结果会有差异?

来源:stackoverflow

时间:2024-03-13 20:18:29 152浏览 收藏

今天golang学习网给大家带来了《在Go基准测试中为什么同一份代码的执行结果会有差异?》,其中涉及到的知识点包括等等,无论你是小白还是老手,都适合看一看哦~有好的建议也欢迎大家在评论留言,若是看完有所收获,也希望大家能多多点赞支持呀!一起加油学习~

问题内容

我对 golang 系统包“math/bits”进行了基准测试。它很快。 我对从“math/bits”复制的相同代码进行了基准测试,速度慢了大约 3 倍。

我想知道在编译、链接或基准测试时用户代码和系统代码有什么区别?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// x_test.go
package x_test
 
import (
    "math/bits"
    "testing"
)
 
// copied from "math/bits"
const debruijn64 = 0x03f79d71b4ca8b09
 
var input uint64 = debruijn64
var output int
 
const m0 = 0x5555555555555555 // 01010101 ...
const m1 = 0x3333333333333333 // 00110011 ...
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
const m3 = 0x00ff00ff00ff00ff // etc.
const m4 = 0x0000ffff0000ffff
 
func onescount64(x uint64) int {
    const m = 1<<64 - 1
    x = x>>1&(m0&m) + x&(m0&m)
    x = x>>2&(m1&m) + x&(m1&m)
    x = (x>>4 + x) & (m2 & m)
    x += x >> 8
    x += x >> 16
    x += x >> 32
    return int(x) & (1<<7 - 1)
}
 
// copied from "math/bits" end
 
 
func benchmarkmine(b *testing.b) {
    var s int
    for i := 0; i < b.n; i++ {
        s += onescount64(uint64(i))
    }
    output = s
}
 
func benchmarkgo(b *testing.b) {
    var s int
    for i := 0; i < b.n; i++ {
        s += bits.onescount64(uint64(i))
    }
    output = s
}

运行它会显示不同的结果:

1
2
3
4
5
go test x_test.go  -bench=.
goos: darwin
goarch: amd64
BenchmarkMine-4         500000000                3.32 ns/op
BenchmarkGo-4           2000000000               0.96 ns/op

这两个基准测试应该会产生相似的结果。但事实并非如此。


解决方案


深入研究Go源代码后,我发现在编译过程中,Go用指令实现替换了math/bits:OnesCount64: go/src/cmd/compile/internal/gc/ssa.go:3428 :makeOnesCountAMD64

当调用 math/bits.OnesCount64 时,它实际上使用了 math/bits 中的代码。

到这里,我们也就讲完了《在Go基准测试中为什么同一份代码的执行结果会有差异?》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>