gpt4 book ai didi

go - Go 中令人困惑的并发和性能问题

转载 作者:IT王子 更新时间:2023-10-29 01:41:03 24 4
gpt4 key购买 nike

现在我通过观看开始学习 Go 语言 this great course .需要明确的是,多年来我只写 PHP,并发/并行对我来说是新的,所以我对此有点困惑。

在本类(class)中,有一个任务是创建一个程序来计算 100 次阶乘。我更进一步,为了比较性能,我将其更改为 10000,出于某种原因,顺序程序的运行速度与并发相同甚至更快。

在这里我将提供 3 种解决方案:我的、教师的和顺序的

我的解决方案:

package main

import (
"fmt"
)

func gen(steps int) <-chan int{
out := make(chan int)
go func() {
for j:= 0; j <steps; j++ {
out <- j
}
close(out)
}()
return out
}

func factorial(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- fact(n)
}
close(out)
}()
return out
}

func fact(n int) int {
total := 1
for i := n;i>0;i-- {
total *=i
}
return total
}

func main() {
steps := 10000
for i := 0; i < steps; i++ {
for n:= range factorial(gen(10)) {
fmt.Println(n)
}
}
}

执行时间:

  • 真正的 0m6,356s
  • 用户 0m3,885s
  • 系统 0m0,870s

教师解答:包主

import (
"fmt"
)

func gen(steps int) <-chan int{
out := make(chan int)
go func() {
for i := 0; i < steps; i++ {
for j:= 0; j <10; j++ {
out <- j
}
}
close(out)
}()
return out
}

func factorial(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- fact(n)
}
close(out)
}()
return out
}

func fact(n int) int {
total := 1
for i := n;i>0;i-- {
total *=i
}
return total
}

func main() {
steps := 10000
for n:= range factorial(gen(steps)) {
fmt.Println(n)
}
}

执行时间:

  • 实际 0m2,836s
  • 用户 0m1,388s
  • 系统 0m0,492s

顺序:

package main

import (
"fmt"
)

func fact(n int) int {
total := 1
for i := n;i>0;i-- {
total *=i
}
return total
}

func main() {
steps := 10000
for i := 0; i < steps; i++ {
for j:= 0; j <10; j++ {
fmt.Println(fact(j))
}
}
}

执行时间:

  • 实际 0m2,513s
  • 用户 0m1,113s
  • 系统 0m0,387s

因此,如您所见,顺序解决方案最快,老师的解决方案第二,我的解决方案第三。

第一个问题:为什么顺序解法最快?第二,为什么我的解决方案这么慢?如果我在我的解决方案中理解正确,我将在 gen 中创建 10000 个 goroutines和 10000 里面 factorial在教师解决方案中,他只在 gen 中创建了 1 个 goroutine和 1 在 factorial .我这么慢是因为我创建了太多不需要的 goroutines?

最佳答案

这是并发性和并行性之间的区别 - 你的,你的老师和顺序在设计中逐渐减少并发,但它们的并行程度取决于 CPU 内核的数量,并且存在与并发相关的设置和通信成本。代码中没有异步调用,因此只有并行才能提高速度。

这值得一看:https://blog.golang.org/concurrency-is-not-parallelism

此外,即使使用并行内核,加速也将取决于工作负载的性质 - 谷歌阿姆达尔定律进行解释。

关于go - Go 中令人困惑的并发和性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49937803/

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