gpt4 book ai didi

performance - Go按位运算性能之谜

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

在对从字节数组到 uint32 的转换性能进行基准测试时,我注意到从最低有效位开始时转换运行得更快:

package blah

import (
"testing"
"encoding/binary"
"bytes"
)

func BenchmarkByteConversion(t *testing.B) {
var i uint32 = 3419234848
buf := new(bytes.Buffer)
_ = binary.Write(buf, binary.BigEndian, i)
b := buf.Bytes()

for n := 0; n < t.N; n++ {
// Start with least significant bit: 0.27 nanos
value := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[2])<<16 | uint32(b[0])<<24

// Start with most significant bit: 0.68 nanos
// value := uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
_ = value
}
}

当我运行 go test -bench=. 时,以第一种方式计算 value 时每次迭代获得 0.27 纳米,而计算 时每次迭代获得 0.68 纳米值 第二种方式。为什么 | 将数字放在一起时,从最低有效位开始的速度是原来的两倍?

最佳答案

没有什么神秘的。优化!

package blah

import (
"bytes"
"encoding/binary"
"testing"
)

func BenchmarkByteConversionLeast(t *testing.B) {
var i uint32 = 3419234848
buf := new(bytes.Buffer)
_ = binary.Write(buf, binary.BigEndian, i)
b := buf.Bytes()

for n := 0; n < t.N; n++ {
// Start with least significant bit: 0.27 nanos
value := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[2])<<16 | uint32(b[0])<<24
_ = value
}
}

func BenchmarkByteConversionMost(t *testing.B) {
var i uint32 = 3419234848
buf := new(bytes.Buffer)
_ = binary.Write(buf, binary.BigEndian, i)
b := buf.Bytes()

for n := 0; n < t.N; n++ {
// Start with most significant bit: 0.68 nanos
value := uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
_ = value
}
}

输出:

go test silly_test.go -bench=.
goos: linux
goarch: amd64
BenchmarkByteConversionLeast-4 2000000000 0.72 ns/op
BenchmarkByteConversionMost-4 2000000000 1.80 ns/op

这应该是显而易见的。边界检查消除。


只需使用常识。如果检查索引 3、2、1 和 0 的数组边界,则可以在 3 处停止检查,因为显然 2、1 和 0 也是有效的。如果检查索引 0、1、2 和 3 的数组边界,则必须检查所有索引的边界。一次边界检查与四次边界检查。

Wikipedia: Bounds checking

Wikipedia: Bounds-checking elimination


您还应该阅读优秀的代码,例如 Go 标准库。例如,

func (littleEndian) PutUint64(b []byte, v uint64) {
_ = b[7] // early bounds check to guarantee safety of writes below
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
}

关于performance - Go按位运算性能之谜,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51972759/

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