【问题标题】:For loop performance much slower when using int64 instead of int32使用 int64 而不是 int32 时,循环性能要慢得多
【发布时间】:2020-03-26 00:27:42
【问题描述】:

我正在尝试找出有关性能的最佳做法。 我注意到为 for 循环指定整数类型可能会极大地影响性能(在我的情况下是 x2 倍)。

我的问题是,是否应该是使用 int64 会比使用 int32 慢得多,或者我的代码中缺少某些内容?

我正在使用的代码:

a.go

package main

import (
    "fmt"
    "time"
    "runtime"
    "strconv"
)

func main() {
    start := time.Now()
    var x1 int // later change all int to int32 or int64 

    for i := int(0); i <= int(1000000000); i++  {
        x1 = x1 + i
    }
        t := time.Now()
        elapsed := t.Sub(start)

    fmt.Println(x1)
    fmt.Println(elapsed)
    fmt.Println(runtime.Compiler, runtime.GOARCH, runtime.GOOS)
    fmt.Println(strconv.IntSize)
}

使用 x1 的 int32 输出

C:\...>go build a.go
C:\...>a

-243309312
238.3333ms
gc amd64 windows
64

使用 x1 的 int64 输出

C:\...>go build a.go
C:\...>a

500000000500000000
467.7835ms
gc amd64 windows
64

更新

我尝试了@Giulio Micheloni 的建议,得到了更准确的基准。

goos: windows
goarch: amd64
BenchmarkInt64-12       1000000000           0.234 ns/op           0 B/op          0 allocs/op
PASS
ok      _/c_/.../.../Desktop    0.402s
Success: Benchmarks passed.

goos: windows
goarch: amd64
BenchmarkInt32-12       1000000000           0.231 ns/op           0 B/op          0 allocs/op
PASS
ok      _/c_/.../.../Desktop    0.403s
Success: Benchmarks passed.

【问题讨论】:

  • 这种情况是否持续发生?
  • @GiulioMicheloni 是的
  • 我会运行这样的基准测试 (play.golang.org/p/OgsrVVWJeuq) 并确保 for 循环的迭代次数不在等式中。您能告诉我们上述基准测试的结果吗?我在我的机器上运行了这些,两种整数大小都得到了相似的结果: Int32-16 0.44ns ± 0% Int64-16 0.45ns ± 1%
  • @GiulioMicheloni 在您发表评论和 peterSO 的帖子之后,我明白了问题所在。现在,我忍不住要问这个烦人的问题;为什么 go 代码比它的 Java 等效代码慢两倍(反问)。

标签: performance for-loop go int


【解决方案1】:

无意义的微基准会产生无意义的结果。


The Go Programming Language Specification

Numeric types

int32   set of all signed 32-bit integers 
        (-2147483648 to 2147483647)
int64   set of all signed 64-bit integers 
        (-9223372036854775808 to 9223372036854775807)

Arithmetic operators

整数溢出

对于有符号整数,操作 +、-、*、/ 和


溢出!

package main

import (
    "fmt"
    "math"
    "runtime"
    "strconv"
    "time"
)

func main() {
    start := time.Now()
    var x1 int32 // later change all int to int32 or int64

    for i := int32(0); i <= int32(1000000000); i++ {

        if int64(x1)+int64(i) > math.MaxInt32 {
            fmt.Println("Overflow:", x1, "+", i, "=", x1+i)
            break
        }

        x1 = x1 + i
    }
    t := time.Now()
    elapsed := t.Sub(start)

    fmt.Println(x1)
    fmt.Println(elapsed)
    fmt.Println(runtime.Compiler, runtime.GOARCH, runtime.GOOS)
    fmt.Println(strconv.IntSize)
}

游乐场:https://play.golang.org/p/bdhB4ABf7jY

输出:

Overflow: 2147450880 + 65536 = -2147450880
gc amd64 linux
64

【讨论】:

  • @Kingindanord,在做微基准测试时,请 1) 不要依赖挂钟计时器,使用股票包testing 的基准测试能力; 2) 确保还使用benchcmp 包来比较不同基准测试运行的结果; 3) 确保不测量基准测试的任何设置和拆卸代码; 4) 大量阅读 Go 中的基准测试。
猜你喜欢
  • 1970-01-01
  • 2011-06-03
  • 2022-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多