英文:
In golang my go routines are using all cores, but only between 50 and 75% of each core
问题
我正在使用go语言的go1.5.3 linux/amd64版本。我有一个执行数学运算的go例程,需要一些时间。每个go例程都是独立运行的,不需要阻塞。
我的系统有12个核心。如果我生成12个go例程,它只会占用所有核心的平均使用率达到31%。如果我使用24个go例程,它会将所有核心的平均使用率提升到49%。如果我使用240个,它会达到77%。2400个则为76%。
显然,rand.Intn(j)操作是导致速度变慢的原因。如果没有这个操作,核心将以100%的速度运行。
如何在使用随机数生成器的情况下让程序使用所有核心达到100%的利用率?
英文:
I am using version go1.5.3 linux/amd64 of the go language. I have a go routine that performs a mathematical operation that takes some time. Each go routine acts independently and does not have to block.
My systems has 12 cores. If I spawn 12 go routines, it only takes the average use of all cores up to 31%. If I use 24 go routines, it brings the average use of all cores up to 49%. If I use 240, i get 77%. 2400 gives me 76%.
Apparently, the rand.Intn(j) operation is what is slowing it down. Without it, the cores will run at 100%.
func DoSomeMath() int {
k := 0
for i := 0; i < 1000; i++ {
j := i*i + 2
k += i * rand.Intn(j)
}
return k
}
How can I get the program to use all the cores at 100% while using an RNG?
答案1
得分: 1
主要原因是全局的rand.*
使用了互斥锁,所以在任何给定的时刻,你只能生成一个随机数。
@peterSO的答案之所以有效是因为现在没有互斥锁,每个例程都有一个生成器,但是如果2个或更多的goroutine在完全相同的纳秒开始,可能会出现重复的状态,尽管这种情况很少见。
点击这里查看全局rand在内部是如何工作的。
英文:
The main reason is, the global rand.*
uses a mutex, so at any given point, you can only generate one random number at a time.
The reason @peterSO's answer works is because there's no mutex now and it's 1 generator per routine, however you can end up with duplicate state if 2 or more goroutines start at the exact nano second, although unlikely.
Look here to see how the global rand works under the hood.
答案2
得分: 0
要转述一下,有谎言、该死的谎言和基准测试。
尽管被要求,但您仍然没有发布重现问题所需的代码:如何创建一个最小、完整和可验证的示例。
这是一个可重现的基准测试,使用了一个伪随机数生成器,应该能够将您的CPU推向接近100%:
package main
import (
"math/rand"
"runtime"
"time"
)
func DoSomeCPU(done <-chan bool) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
k := 0
for i := 0; i < 1000000; i++ {
j := i*i + 2
k += i * r.Intn(j)
}
_ = k
<-done
}
func main() {
numCPU := runtime.NumCPU()
runtime.GOMAXPROCS(numCPU)
done := make(chan bool, 2*numCPU)
for {
done <- true
go DoSomeCPU(done)
}
}
当您运行此代码时,您会得到什么结果?
英文:
To paraphrase, there are lies, damn lies, and benchmarks.
Despite being asked, you still haven't posted the code necessary to reproduce your issue: How to create a Minimal, Complete, and Verifiable example.
Here's a reproducible benchmark, which uses a PRNG, that should drive your CPUs to close to 100%:
package main
import (
"math/rand"
"runtime"
"time"
)
func DoSomeCPU(done <-chan bool) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
k := 0
for i := 0; i < 1000000; i++ {
j := i*i + 2
k += i * r.Intn(j)
}
_ = k
<-done
}
func main() {
numCPU := runtime.NumCPU()
runtime.GOMAXPROCS(numCPU)
done := make(chan bool, 2*numCPU)
for {
done <- true
go DoSomeCPU(done)
}
}
What results do you get when you run this code?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论