作者热门文章
- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一个相当简单的 Go 程序,旨在计算随机斐波那契数,以测试我在我编写的工作池中观察到的一些奇怪行为。 当我分配一个线程时,程序在 1.78 秒内完成。当我分配 4 时,它在 9.88 秒内完成。
代码如下:
var workerWG sync.WaitGroup
func worker(fibNum chan int) {
for {
var tgt = <-fibNum
workerWG.Add(1)
var a, b float64 = 0, 1
for i := 0; i < tgt; i++ {
a, b = a+b, a
}
workerWG.Done()
}
}
func main() {
rand.Seed(time.Now().UnixNano())
runtime.GOMAXPROCS(1) // LINE IN QUESTION
var fibNum = make(chan int)
for i := 0; i < 4; i++ {
go worker(fibNum)
}
for i := 0; i < 500000; i++ {
fibNum <- rand.Intn(1000)
}
workerWG.Wait()
}
如果我将 runtime.GOMAXPROCS(1)
替换为 4
,该程序的运行时间将增加四倍。
这是怎么回事?为什么向工作池添加更多可用线程会减慢整个池的速度?
我个人的理论是,这与 worker 的处理时间小于线程管理的开销有关,但我不确定。我的保留是由以下测试引起的:
当我用以下代码替换 worker
函数时:
for {
<-fibNum
time.Sleep(500 * time.Millisecond)
}
一个可用线程和四个可用线程都需要相同的时间。
最佳答案
我修改了你的程序,如下所示:
package main
import (
"math/rand"
"runtime"
"sync"
"time"
)
var workerWG sync.WaitGroup
func worker(fibNum chan int) {
for tgt := range fibNum {
var a, b float64 = 0, 1
for i := 0; i < tgt; i++ {
a, b = a+b, a
}
}
workerWG.Done()
}
func main() {
rand.Seed(time.Now().UnixNano())
runtime.GOMAXPROCS(1) // LINE IN QUESTION
var fibNum = make(chan int)
for i := 0; i < 4; i++ {
go worker(fibNum)
workerWG.Add(1)
}
for i := 0; i < 500000; i++ {
fibNum <- rand.Intn(100000)
}
close(fibNum)
workerWG.Wait()
}
rand.Intn(1000)
更改为 rand.Intn(100000)
在我的机器上产生:
$ time go run threading.go (GOMAXPROCS=1)
real 0m20.934s
user 0m20.932s
sys 0m0.012s
$ time go run threading.go (GOMAXPROCS=8)
real 0m10.634s
user 0m44.184s
sys 0m1.928s
这意味着在您的原始代码中,执行的工作与同步( channel 读/写)相比可以忽略不计。速度变慢的原因是必须跨线程而不是一个线程进行同步,并且它们之间只执行非常少量的工作。
从本质上讲,与计算高达 1000 的斐波那契数相比,同步的成本很高。这就是人们倾向于不鼓励微基准的原因。增加这个数字可以提供更好的视角。但更好的想法是对正在完成的实际工作进行基准测试,即包括 IO、系统调用、处理、处理、写入输出、格式化等。
编辑:作为实验,我将 GOMAXPROCS 设置为 8 的 worker 数量增加到 8,结果是:
$ time go run threading.go
real 0m4.971s
user 0m35.692s
sys 0m0.044s
关于multithreading - 为什么这个程序在分配的线程越少时运行得越快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32600873/
我是一名优秀的程序员,十分优秀!