gpt4 book ai didi

go - 为什么这个Go程序这么慢?

转载 作者:行者123 更新时间:2023-12-01 21:15:34 28 4
gpt4 key购买 nike

我只是阅读了Go的一些简短教程,并编写了一个简单的程序筛。 Sieve使用sieve算法来打印所有小于10000的质数,这会创建很多go例程。我得到了正确的结果,但是程序非常慢(在我的计算机上为5秒)。我还编写了实现相同算法的lua脚本和python脚本,并且运行速度更快(两者在我的计算机上均为1秒左右)。

注意,这样做的目的是要了解go例程与其他语言(例如lua)中的协程相比的性能。实现效率很低,一些评论指出,这不是实现Eratosthenes筛网的正确方法。是的,这是故意的。其他一些答复指出,速度缓慢是由打印I/O引起的。所以我注释掉了打印行。

我的问题是为什么我在Go中实现的筛分程序这么慢?
这是代码:

package main

import (
"fmt"
"sync"
)


type Sieve struct {
id int;
msg_queue chan int;
wg *sync.WaitGroup;
}


func NewSieve(id int) *Sieve {
sieve := new(Sieve)
sieve.id = id
sieve.msg_queue = make(chan int)
sieve.wg = new(sync.WaitGroup)
sieve.wg.Add(1)
return sieve
}


func (sieve *Sieve) run() {
defer sieve.wg.Done()

myprime := <-sieve.msg_queue
if myprime == 0 {
return
}
// fmt.Printf("Sieve (%d) is for prime number %d.\n", sieve.id, myprime)

next_sieve := NewSieve(sieve.id + 1)
go next_sieve.run()
for {
number := <-sieve.msg_queue
if number == 0 {
next_sieve.msg_queue <- number;
next_sieve.wg.Wait()
return
} else if number % myprime != 0 {
// fmt.Printf("id: %d, number: %d, myprime: %d, number mod myprime: %d\n", sieve.id, number, myprime, number % myprime)
next_sieve.msg_queue <- number
}
}
}


func driver() {
first := NewSieve(2)
go first.run()
for n := 2; n <= 10000; n++ {
first.msg_queue <- n
}
first.msg_queue <- 0
first.wg.Wait()
}


func main() {
driver()
}

作为比较,这是sieve.lua的代码
function sieve(id)
local myprime = coroutine.yield()
// print(string.format("Sieve (%d) is for prime number %d", id, myprime))

local next_sieve = coroutine.create(sieve)
coroutine.resume(next_sieve, id + 1)

while true do
local number = coroutine.yield()
if number % myprime ~= 0 then
// print(string.format("id: %d, number: %d, myprime: %d, number mod myprime: %d", id, number, myprime, number % myprime))
coroutine.resume(next_sieve, number)
end
end
end


function driver()
local first = coroutine.create(sieve)
coroutine.resume(first, 2)
local n
for n = 2, 10000 do
coroutine.resume(first, n)
end
end

driver()

最佳答案

毫无意义的微基准测试将产生毫无意义的结果。

您正在定时打印I/O。

您需要花费少量的时间去执行例程和 channel 开销。

这是Go中的质数筛选程序。

输出:

$ go version
go version devel +46be01f4e0 Sun Oct 13 01:48:30 2019 +0000 linux/amd64
$ go build sumprimes.go && time ./sumprimes
5736396
29.96µs
real 0m0.001s
user 0m0.001s
sys 0m0.000s
sumprimes.go:
package main

import (
"fmt"
"time"
)

const (
prime = 0x00
notprime = 0xFF
)

func oddPrimes(n uint64) (sieve []uint8) {
sieve = make([]uint8, (n+1)/2)
sieve[0] = notprime
p := uint64(3)
for i := p * p; i <= n; i = p * p {
for j := i; j <= n; j += 2 * p {
sieve[j/2] = notprime
}
for p += 2; sieve[p/2] == notprime; p += 2 {
}
}
return sieve
}

func sumPrimes(n uint64) uint64 {
sum := uint64(0)
if n >= 2 {
sum += 2
}
for i, p := range oddPrimes(n) {
if p == prime {
sum += 2*uint64(i) + 1
}
}
return sum
}

func main() {
start := time.Now()

var n uint64 = 10000
sum := sumPrimes(n)
fmt.Println(sum)

fmt.Println(time.Since(start))
}

关于go - 为什么这个Go程序这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58369885/

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