亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Go按位運算性能之謎

Go按位運算性能之謎

Go
慕碼人2483693 2023-03-21 17:21:08
在對從字節數組到 s 的轉換性能進行基準測試時uint32,我注意到從最低有效位開始時轉換運行得更快:package blahimport (    "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=.時每次迭代獲得 0.27 納米,計算第二種方式時每次迭代獲得 0.68 納米。為什么將數字放在一起時從最低有效位開始的速度是原來的兩倍?valuevalue|
查看完整描述

1 回答

?
幕布斯6054654

TA貢獻1876條經驗 獲得超7個贊

沒有什么神秘之處。優化!


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 的數組邊界,則必須檢查所有索引的邊界。一次邊界檢查與四次邊界檢查。

維基百科:邊界檢查

維基百科:邊界檢查消除


您還應該閱讀好的代碼,例如 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)

}


查看完整回答
反對 回復 2023-03-21
  • 1 回答
  • 0 關注
  • 87 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號