gpt4 book ai didi

optimization - 函数调用导致性能下降

转载 作者:数据小太阳 更新时间:2023-10-29 03:33:01 27 4
gpt4 key购买 nike

对于以下函数:

func CycleClock(c *ballclock.Clock) int {
for i := 0; i < fiveMinutesPerDay; i++ {
c.TickFive()
}

return 1 + CalculateBallCycle(append([]int{}, c.BallQueue...))
}

其中 c.BallQueue 定义为 []intCalculateBallCycle 定义为 func CalculateBallCycle(s []int)整数for 循环和 return 语句之间的性能大幅下降。

我写了以下基准测试。第一个基准测试整个函数,第二个基准测试 for 循环,而第三个基准测试 CalculateBallCycle 函数:

func BenchmarkCycleClock(b *testing.B) {
for i := ballclock.MinBalls; i <= ballclock.MaxBalls; i++ {
j := i
b.Run("BallCount="+strconv.Itoa(i), func(b *testing.B) {
for n := 0; n < b.N; n++ {
c, _ := ballclock.NewClock(j)

CycleClock(c)
}
})
}
}

func BenchmarkCycle24(b *testing.B) {
for i := ballclock.MinBalls; i <= ballclock.MaxBalls; i++ {
j := i
b.Run("BallCount="+strconv.Itoa(i), func(b *testing.B) {
for n := 0; n < b.N; n++ {
c, _ := ballclock.NewClock(j)

for k := 0; k < fiveMinutesPerDay; k++ {
c.TickFive()
}
}
})
}
}

func BenchmarkCalculateBallCycle123(b *testing.B) {
m := []int{8, 62, 42, 87, 108, 35, 17, 6, 22, 75, 116, 112, 39, 119, 52, 60, 30, 88, 56, 36, 38, 26, 51, 31, 55, 120, 33, 99, 111, 24, 45, 21, 23, 34, 43, 41, 67, 65, 66, 85, 82, 89, 9, 25, 109, 47, 40, 0, 83, 46, 73, 13, 12, 63, 15, 90, 121, 2, 69, 53, 28, 72, 97, 3, 4, 94, 106, 61, 96, 18, 80, 74, 44, 84, 107, 98, 93, 103, 5, 91, 32, 76, 20, 68, 81, 95, 29, 27, 86, 104, 7, 64, 113, 78, 105, 58, 118, 117, 50, 70, 10, 101, 110, 19, 1, 115, 102, 71, 79, 57, 77, 122, 48, 114, 54, 37, 59, 49, 100, 11, 14, 92, 16}

for n := 0; n < b.N; n++ {
CalculateBallCycle(m)
}
}

使用 123 个球,得到以下结果:

BenchmarkCycleClock/BallCount=123-8                  200           9254136 ns/op
BenchmarkCycle24/BallCount=123-8 200000 7610 ns/op
BenchmarkCalculateBallCycle123-8 3000000 456 ns/op

从这个角度来看,基准之间存在巨大差异。我希望第一个基准测试大约需要 ~8000 ns/op,因为那将是各部分的总和。

Here 是 github 存储库。

编辑:

我发现基准测试的结果和运行程序的结果大不相同。我采用了@yazgazan 发现的内容并修改了 main.go 中的基准函数,有点模仿 main_test.go 中的 BenchmarkCalculateBallCycle123:

func Benchmark() {
for i := ballclock.MinBalls; i <= ballclock.MaxBalls; i++ {
if i != 123 {
continue
}

start := time.Now()

t := CalculateBallCycle([]int{8, 62, 42, 87, 108, 35, 17, 6, 22, 75, 116, 112, 39, 119, 52, 60, 30, 88, 56, 36, 38, 26, 51, 31, 55, 120, 33, 99, 111, 24, 45, 21, 23, 34, 43, 41, 67, 65, 66, 85, 82, 89, 9, 25, 109, 47, 40, 0, 83, 46, 73, 13, 12, 63, 15, 90, 121, 2, 69, 53, 28, 72, 97, 3, 4, 94, 106, 61, 96, 18, 80, 74, 44, 84, 107, 98, 93, 103, 5, 91, 32, 76, 20, 68, 81, 95, 29, 27, 86, 104, 7, 64, 113, 78, 105, 58, 118, 117, 50, 70, 10, 101, 110, 19, 1, 115, 102, 71, 79, 57, 77, 122, 48, 114, 54, 37, 59, 49, 100, 11, 14, 92, 16})

duration := time.Since(start)

fmt.Printf("Ballclock with %v balls took %s;\n", i, duration)
}
}

这给出了输出:

Ballclock with 123 balls took 11.86748ms;

如您所见,总时间为 11.86 毫秒,所有时间都花在了 CalculateBallCycle 函数中。什么会导致基准测试以 456 ns/op 运行,而正在运行的程序以 11867480 ms/op 左右运行?

最佳答案

您写道 CalcualteBallCycle() 通过设计修改 slice 。

我不能说这种方法的正确性,但这就是为什么 BenchmarkCalculateBallCycle123 的基准时间如此不同的原因。

在第一次运行时它做了预期的事情,但在随后的运行中它做了完全不同的事情,因为您传递的是不同的数据作为输入。

对修改后的代码进行基准测试:

func BenchmarkCalculateBallCycle123v2(b *testing.B) {
m := []int{8, 62, 42, 87, 108, 35, 17, 6, 22, 75, 116, 112, 39, 119, 52, 60, 30, 88, 56, 36, 38, 26, 51, 31, 55, 120, 33, 99, 111, 24, 45, 21, 23, 34, 43, 41, 67, 65, 66, 85, 82, 89, 9, 25, 109, 47, 40, 0, 83, 46, 73, 13, 12, 63, 15, 90, 121, 2, 69, 53, 28, 72, 97, 3, 4, 94, 106, 61, 96, 18, 80, 74, 44, 84, 107, 98, 93, 103, 5, 91, 32, 76, 20, 68, 81, 95, 29, 27, 86, 104, 7, 64, 113, 78, 105, 58, 118, 117, 50, 70, 10, 101, 110, 19, 1, 115, 102, 71, 79, 57, 77, 122, 48, 114, 54, 37, 59, 49, 100, 11, 14, 92, 16}
for n := 0; n < b.N; n++ {
tmp := append([]int{}, m...)
CalculateBallCycle(tmp)
}
}

这通过制作 m 的副本来解决此行为,以便 CalculateBallCycle 修改本地副本。

运行时间变得更像其他:

BenchmarkCalculateBallCycle123-8         3000000           500 ns/op
BenchmarkCalculateBallCycle123v2-8 100 10483347 ns/op

关于optimization - 函数调用导致性能下降,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45147353/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com