现在我通过观看开始学习 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/