gpt4 book ai didi

Go 并发 : Chudnovky's algorithm, 比同步慢

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

最近在 friend 的推荐下开始学习围棋。到目前为止,我很喜欢它,但我写了(我认为会是)轻量级并发的完美示例,并得到了令人惊讶的结果......所以我怀疑我做错了什么,或者我是误解了 goroutines 的成本。我希望这里的一些 gophers 可以提供见解。

我使用 goroutines 和简单的同步执行在 Go 中编写了 Chudnovsky 的算法。我假设,每个计算都独立于其他计算,同时运行至少会快一点。

注意:我在第 5 代 i7 上运行它,所以如果 goroutine 像我被告知的那样被多路复用到线程上,这应该是并发的并行的。

 package main

import (
"fmt"
"math"
"strconv"
"time"
)

func main() {
var input string
var sum float64
var pi float64
c := make(chan float64)

fmt.Print("How many iterations? ")
fmt.Scanln(&input)
max,err := strconv.Atoi(input)

if err != nil {
panic("You did not enter a valid integer")
}
start := time.Now() //start timing execution of concurrent routine

for i := 0; i < max; i++ {
go chudnovskyConcurrent(i,c)
}

for i := 0; i < max; i++ {
sum += <-c
}
end := time.Now() //end of concurrent routine
fmt.Println("Duration of concurrent calculation: ",end.Sub(start))
pi = 1/(12*sum)
fmt.Println(pi)

start = time.Now() //start timing execution of syncronous routine
sum = 0
for i := 0; i < max; i++ {
sum += chudnovskySync(i)
}
end = time.Now() //end of syncronous routine
fmt.Println("Duration of synchronous calculation: ",end.Sub(start))
pi = 1/(12*sum)
fmt.Println(pi)
}

func chudnovskyConcurrent(i int, c chan<- float64) {
var numerator float64
var denominator float64
ifloat := float64(i)
iun := uint64(i)
numerator = math.Pow(-1, ifloat) * float64(factorial(6*iun)) * (545140134*ifloat+13591409)
denominator = float64(factorial(3*iun)) * math.Pow(float64(factorial(iun)),3) * math.Pow(math.Pow(640320,3),ifloat+0.5)
c <- numerator/denominator
}

func chudnovskySync(i int) (r float64) {
var numerator float64
var denominator float64
ifloat := float64(i)
iun := uint64(i)
numerator = math.Pow(-1, ifloat) * float64(factorial(6*iun)) * (545140134*ifloat+13591409)
denominator = float64(factorial(3*iun)) * math.Pow(float64(factorial(iun)),3) * math.Pow(math.Pow(640320,3),ifloat+0.5)
r = numerator/denominator
return
}

func factorial(n uint64) (res uint64) {
if ( n > 0 ) {
res = n * factorial(n-1)
return res
}

return 1
}

这是我的结果:

How many iterations? 20
Duration of concurrent calculation: 573.944µs
3.1415926535897936
Duration of synchronous calculation: 63.056µs
3.1415926535897936

最佳答案

您正在进行的计算太简单了,无法在单独的 goroutine 中进行每一项计算。与实际计算相比,您在运行时(创建 goroutine、多路复用、调度等)浪费的时间更多。你想做的更适合 GPU,例如,你有大量的并行执行单元,可以在瞬间完成这些简单的计算。但是您需要其他语言和 API 才能做到这一点。

您可以做的是为每个硬件执行线程创建软件执行线程。您希望将 max 变量分成大块并并行执行它们。这是一个非常简单的例子,只是为了说明这个想法:

package main

import (
"fmt"
"math"
"strconv"
"time"
"runtime"
)

func main() {
var input string
var sum float64
var pi float64
c := make(chan float64, runtime.GOMAXPROCS(-1))
fmt.Print("How many iterations? ")
fmt.Scanln(&input)
max,err := strconv.Atoi(input)

if err != nil {
panic("You did not enter a valid integer")
}
start := time.Now() //start timing execution of concurrent routine

for i := 0; i < runtime.GOMAXPROCS(-1); i++ {
go func(i int){
var sum float64
for j := 0; j < max/runtime.GOMAXPROCS(-1); j++ {
sum += chudnovskySync(j + i*max/runtime.GOMAXPROCS(-1))
}
c <- sum
}(i)
}

for i := 0; i < runtime.GOMAXPROCS(-1); i++ {
sum += <-c
}
end := time.Now() //end of concurrent routine
fmt.Println("Duration of concurrent calculation: ",end.Sub(start))
pi = 1/(12*sum)
fmt.Println(pi)

start = time.Now() //start timing execution of syncronous routine
sum = 0
for i := 0; i < max; i++ {
sum += chudnovskySync(i)
}
end = time.Now() //end of syncronous routine
fmt.Println("Duration of synchronous calculation: ",end.Sub(start))
pi = 1/(12*sum)
fmt.Println(pi)
}

func chudnovskySync(i int) (r float64) {
var numerator float64
var denominator float64
ifloat := float64(i)
iun := uint64(i)
numerator = math.Pow(-1, ifloat) * float64(factorial(6*iun)) * (545140134*ifloat+13591409)
denominator = float64(factorial(3*iun)) * math.Pow(float64(factorial(iun)),3) * math.Pow(math.Pow(640320,3),ifloat+0.5)
r = numerator/denominator
return
}

func factorial(n uint64) (res uint64) {
if ( n > 0 ) {
res = n * factorial(n-1)
return res
}

return 1
}

这是结果

$ go version
go version go1.5.2 windows/amd64

$ go run main.go
GOMAXPROCS = 4
How many iterations? 10000
Duration of concurrent calculation: 932.8916ms
NaN
Duration of synchronous calculation: 2.0639744s
NaN

关于Go 并发 : Chudnovky's algorithm, 比同步慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36104038/

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