为了账号安全,请及时绑定邮箱和手机立即绑定

为什么我的 Rust 程序比执行相同按位和 I/O 操作的 Go 程序慢 4 倍?

为什么我的 Rust 程序比执行相同按位和 I/O 操作的 Go 程序慢 4 倍?

Go
MM们 2021-12-27 15:10:06
我有一个 Rust 程序,它实现了对 64 位无符号整数的蛮力奇偶校验:use std::io;use std::io::BufRead;fn parity(mut num: u64) -> u8 {    let mut result: u8 = 0;    while num > 0 {        result = result ^ (num & 1) as u8;        num = num >> 1;    }    result}fn main() {    let stdin = io::stdin();    let mut num: u64;    let mut it = stdin.lock().lines();    // skip 1st line with number of test cases    it.next();    for line in it {        num = line.unwrap().parse().unwrap();        println!("{}", parity(num));    }}当我用包含 1000000 个无符号整数的输入文件提供它时:$ rustc parity.rs$ time cat input.txt | ./parity &> /dev/nullcat input.txt  0.00s user 0.02s system 0% cpu 4.178 total./parity &> /dev/null  3.87s user 0.32s system 99% cpu 4.195 total这里有一个惊喜 - Go 中实际上相同的程序执行速度提高了 4 倍:$ go build parity.go$ time cat input.txt | ./parity &> /dev/nullcat input.txt  0.00s user 0.03s system 3% cpu 0.952 total./parity &> /dev/null  0.63s user 0.32s system 99% cpu 0.955 total这是 Go 中的代码:package mainimport (    "bufio"    "fmt"    "os"    "strconv")func parity(line string) uint64 {    var parity uint64    u, err := strconv.ParseUint(line, 10, 64)    if err != nil {        panic(err)    }    for u > 0 {        parity ^= u & 1        u >>= 1    }    return parity}func main() {    scanner := bufio.NewScanner(os.Stdin)    // skip line with number of cases    if !scanner.Scan() {        // panic if there's no number of test cases        panic("missing number of test cases")    }    for scanner.Scan() {        fmt.Println(parity(scanner.Text()))    }    if err := scanner.Err(); err != nil {        fmt.Fprintln(os.Stderr, "reading standard input:", err)    }}版本:$ rustc --versionrustc 1.7.0$ go versiongo version go1.6 darwin/amd64输入文件示例,第一行包含文件中输入值的数量:8772736924489878378924444773574900194114038350233697550492810622611992794559415389047284462070700118446744073709551615为什么我编写的 Rust 和 Go 程序在性能上有如此巨大的差异?在这种情况下,我预计 Rust 会比 Go 快一点。我的 Rust 代码做错了吗?
查看完整描述

2 回答

?
梵蒂冈之花

TA贡献1900条经验 获得超5个赞

我认为您没有进行优化编译。尝试

$ rustc -O parity.rs


查看完整回答
反对 回复 2021-12-27
?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

您的基准不衡量奇偶校验。它测量输入加奇偶校验加输出。例如,在 Go 中,您可以测量scanner.Scan和strconv.ParseUint和fmt.Println以及奇偶校验。


这是一个 Go 基准测试,它只测量 1000000 次奇偶校验。


parity_test.go:


package parity


import (

    "math/rand"

    "runtime"

    "testing"

)


func parity(n uint64) uint64 {

    var parity uint64

    for n > 0 {

        parity ^= n & 1

        n >>= 1

    }

    return parity

}


func init() { runtime.GOMAXPROCS(1) }


// Benchmark 1000000 parity checks.

func BenchmarkParity1000000(b *testing.B) {

    n := make([]uint64, 1000000)

    for i := range n {

        r := uint64(rand.Uint32())

        n[i] = (r << 32) | r

    }

    p := parity(42)

    b.ResetTimer()

    for i := 0; i < b.N; i++ {

        for _, n := range n {

            p = parity(n)

        }

    }

    b.StopTimer()

    _ = p

}

输出:


$ go test -bench=.

BenchmarkParity1000000        50      34586769 ns/op

$


查看完整回答
反对 回复 2021-12-27
  • 2 回答
  • 0 关注
  • 159 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号