Home > Backend Development > Golang > Golang math execution slow when using code

Golang math execution slow when using code

王林
Release: 2024-02-05 21:39:03
forward
929 people have browsed it

使用代码时 Golang 数学执行缓慢

问题内容

问题:使用 math 包中的代码比使用 math 包慢得多。

下面的代码是从数学模块复制的,但是 math.Sqrt 的执行速度比 sqrt 快得多。我的问题是:为什么,可以做什么?

示例:(注意,感兴趣的函数不是 math.Sqrt。我想编写函数组合的自定义版本。)

package main

import (
    "fmt"
    "math"
    "unsafe"
)

const (
    uvnan    = 0x7FF8000000000001
    uvinf    = 0x7FF0000000000000
    uvneginf = 0xFFF0000000000000
    uvone    = 0x3FF0000000000000
    mask     = 0x7FF
    shift    = 64 - 11 - 1
    bias     = 1023
    signMask = 1 << 63
    fracMask = 1<<shift - 1
)

func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) }
func Float64frombits(b uint64) float64 { return *(*float64)(unsafe.Pointer(&b)) }
func sqrt(x float64) float64 {
    // special cases
    ix := Float64bits(x)
    // normalize x
    exp := int((ix >> shift) & mask)
    if exp == 0 { // subnormal x
        for ix&(1<<shift) == 0 {
            ix <<= 1
            exp--
        }
        exp++
    }
    exp -= bias // unbias exponent
    ix &^= mask << shift
    ix |= 1 << shift
    if exp&1 == 1 { // odd exp, double x to make it even
        ix <<= 1
    }
    exp >>= 1 // exp = exp/2, exponent of square root
    // generate sqrt(x) bit by bit
    ix <<= 1
    var q, s uint64               // q = sqrt(x)
    r := uint64(1 << (shift + 1)) // r = moving bit from MSB to LSB
    for r != 0 {
        t := s + r
        if t <= ix {
            s = t + r
            ix -= t
            q += r
        }
        ix <<= 1
        r >>= 1
    }
    // final rounding
    if ix != 0 { // remainder, result not exact
        q += q & 1 // round according to extra bit
    }
    ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent
    return Float64frombits(ix)
}

func main() {
    n_iter := 100000000
    var x float64
    var y float64
    for i := 0; i < n_iter; i++ {
        y = math.Sqrt(2426.1)
    }
    fmt.Printf("Done\n") // Much, much faster

    for i := 0; i < n_iter; i++ {
        x = sqrt(2426.1)
    }
    fmt.Printf("Done\n")
    fmt.Printf("%f/%f\n", x, y)
}
Copy after login


正确答案


检查 math.Sqrt 的生成代码。使用 -S 标志构建此 main.go

package main

import (
    "fmt"
    "math"
    "math/rand"
)

func main() {
    x := rand.Float64()
    y := math.Sqrt(x)
    fmt.Println(y)
}
Copy after login

生成程序集:go build -gcflags='-S' main.go

...
        0x000e 00014 (./main.go:10)     PCDATA  $1, $0
        0x000e 00014 (./main.go:10)     CALL    math/rand.Float64(SB)
        0x0013 00019 (/home/user/go/pkg/mod/golang.org/<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="8afee5e5e6e9e2ebe3e4cafcbaa4baa4bba7ede5bba4b8bba4bfa4e6e3e4fff2a7ebe7eebcbe">[email&#160;protected]</a>/src/math/sqrt.go:94)    SQRTSD  X0, X0
        0x0017 00023 (./main.go:12)     MOVQ    X0, AX
        0x001c 00028 (./main.go:11)     XCHGL   AX, AX
...
Copy after login

可以看到,实际调用的是SQRTSD机器指令。

它受 cmd/compile/internal/ssagen/ssa.go 配置:在平台 sys.I386、sys.AMD64、sys.ARM、sys.ARM64、sys.Loong64、sys.MIPS、sys. MIPS64、sys.PPC64、sys.RISCV64、sys.S390X、sys.Wasm 编译器插入 SQRT 操作码。

您还可以检查许多其他被汇编替换的函数。

顺便说一句。在示例中,我在随机参数上调用 math.Sqrt ,因为对于文字值,编译器会计算平方根本身并编译为实际值。

这里是math.Sqrt(2.0)的汇编代码

0x0014 00020 (./main.go:11)     MOVQ    $4609047870845172685, AX
0x001e 00030 (./main.go:11)     PCDATA  $1, $1
0x001e 00030 (./main.go:11)     NOP
0x0020 00032 (./main.go:11)     CALL    runtime.convT64(SB)
0x0025 00037 (./main.go:11)     LEAQ    type:float64(SB), CX
Copy after login

4609047870845172685 是 64 位表示形式的实际 sqrt(2)

The above is the detailed content of Golang math execution slow when using code. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template