In golang my go routines are using all cores, but only between 50 and 75% of each core

huangapple go评论102阅读模式
英文:

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 (
	&quot;math/rand&quot;
	&quot;runtime&quot;
	&quot;time&quot;
)

func DoSomeCPU(done &lt;-chan bool) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	k := 0
	for i := 0; i &lt; 1000000; i++ {
		j := i*i + 2
		k += i * r.Intn(j)
	}
	_ = k
	&lt;-done
}

func main() {
	numCPU := runtime.NumCPU()
	runtime.GOMAXPROCS(numCPU)
	done := make(chan bool, 2*numCPU)
	for {
		done &lt;- true
		go DoSomeCPU(done)
	}
}

What results do you get when you run this code?

huangapple
  • 本文由 发表于 2016年2月14日 02:58:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/35384033.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定