Golang Go语言小程序,多核 CPU 均跑到 100%

发布于 1周前 作者 bupafengyu 来自 Go语言
package main

import ( “math/rand” “runtime” )

func runOneCpu() { for { rand.Intn(10000000) } } func main() { cpunum := runtime.NumCPU() runtime.GOMAXPROCS(cpunum) for i := 0; i < cpunum; i += 1 { go runOneCpu() } for { } }

另外,如果要把跑到特定的百分比,还没有想到怎么整


Golang Go语言小程序,多核 CPU 均跑到 100%

更多关于Golang Go语言小程序,多核 CPU 均跑到 100%的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

15 回复

就像软 PWM 一样,在很短的时间段里面交替满负载 /空闲,比如 70%时间满负载, 30%时间空闲,那么整体看起来就像是 70%的 CPU 占用率。

BTW 还可以根据这个原理在任务管理器上画函数图像呢

更多关于Golang Go语言小程序,多核 CPU 均跑到 100%的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


优越性在哪里?

我拿 go1.4 编译,发现只跑到 75%。
拿 go1.5.1 编译,发现跑到 50%。。。

我在 win10 上面跑,刚开始是 98%左右,后来只有 73%左右,不知道 windows 做了什么优化

不错,回头试试

无线循环太吃资源了

OSX go1.5.1 75% 左右

https://github.com/ysmood/heater

之前冬天写的一个项目,冷的时候跑下,笔记本立马就热起来了。

哈哈哈,,一看就是做硬件出身的

其实不是,只是以前玩过单片机 :-D

go 1.5 之前, GOMAXPROCS 默认为 1 。之后默认为核心数量。 go 1.5 重新实现了 goroutine “调度器”。

由于 goroutine 是在 thread 的基础上进行复用的,所以最终在 cpu 核心上体现的占用率还取决于内核调度器的实现。

我印象里把所有核都完全跑满并不容易
需要用 ORTHOS


出现没有跑满 CPU 的原因是: rand.Intn()方法会调用一个全局对象的方法生成随机数,这个全局方法是有 lock 的,所以会出现 golang 的多个 goroutine 相互竞争, lock 的底层实现,我不是很清楚,但是“ lock 检测不让 CPU 满载”是高并发程序的基本原则。要想让其满载,应该使用 goroutine 独立的计算模块,最简单就是
for {} .
见: https://golang.org/src/math/rand/rand.go#L238
238 func (r *lockedSource) Int63() (n int64) {
239 r.lk.Lock()
240 n = r.src.Int63()
241 r.lk.Unlock()
242 return
243 }

另外作者程序存在两个问题:
1. main 线程调用的计算和其他线程调用的计算不一样, main 线程会占用 100%,而其他线程并不会满负载。其 CPU 的负载结果很难说是平均每个线程的负载情况。
2. Golang 映射的 native 的线程数可以通过 runtime.GOMAXPROCS(cpunum)设置,实际运行中最大的线程数在此基础上+1 ,因为还有 gc 线程。作者为了测试 routineNum 满载,除了 main 线程外,应该再开启 routineNum-1 个 goroutine 。

我做了两个测试,硬件配置: 2CPU, 4 cores per CPU; Golang 配置: runtime.GOMAXPROCS(8):
1.
func main() {
routineNum, err := strconv.Atoi(os.Args(1))

cpunum := runtime.NumCPU()
runtime.GOMAXPROCS(cpunum)
for i := 0; i < routineNum -1 ; i += 1 {
go func() {
for {
rand.Intn(10000000)
}
}()
}
for {
rand.Intn(10000000)
}
}
以下是测试结果
routineNum 1 2 3 4 5 6 7 8
CPU 使用率 100% 120% 201% 210% 220% 240% 266% 290%
#native thread 4 5 6 6 7 8 9 9

2.
func main() {
routineNum, err := strconv.Atoi(os.Args(1))

cpunum := runtime.NumCPU()
runtime.GOMAXPROCS(cpunum)
for i := 0; i < routineNum -1 ; i += 1 {
go func() {
for {
// nothing
}
}()
}
for {
// nothing
}
}
routineNum 1 2 3 4 5 6 7 8
CPU 使用率 100% 199% 299% 399% 496% 597% 697% 790%
#native threads 4 4 5 6 7 8 9 9

所以楼上说 Golang 没有跑到满负载是做了什么优化是错误的,另外不同版本之间的差别只是因为 lock 的性能差别导致;内核调度器的实现不会这么傻,在 core 处于 idle 的时候难道不将计算密集型的线程分配在上面?

所以楼主想实现制定的运行百分比,就应该摒弃采用 rand 计算的方法。而采取独立的计算方法。例如 for 循环满足一定条件就睡觉,当然还得事先计算好一定时间内会计算多少条语句,编程之美第一道题就是这个,作者去脑补吧。^_^

楼上大神😜

针对您提到的Golang(Go语言)小程序在多核CPU上都跑到100%的情况,这通常意味着您的程序有效地利用了系统的并行处理能力。不过,为了确保这是期望的行为且没有过度消耗资源,以下几点建议可供参考:

  1. 确认并发模型:检查您的程序是否使用了Go的goroutines和channels来并发执行任务。确保这些并发任务是有意义的,且没有不必要的并发开销。

  2. 资源监控:使用工具如tophtop或Go的内置pprof工具来监控CPU和内存使用情况。这可以帮助您识别是否有意外的资源消耗。

  3. 优化算法:如果程序逻辑允许,考虑是否有算法优化空间,以减少计算量,尤其是在CPU密集型任务中。

  4. 限制并发度:如果程序确实不需要在所有核心上都满载运行,可以通过限制goroutine的数量或使用同步机制(如sync.WaitGroup)来控制并发级别。

  5. 检查I/O操作:如果程序涉及大量I/O(如网络请求或文件读写),确保这些操作没有成为瓶颈,并考虑使用异步I/O或缓存策略来提高效率。

  6. 代码审查:定期进行代码审查,确保没有无意的死循环或低效的代码结构导致CPU资源被持续占用。

综上所述,多核CPU满载可能是程序高效运行的表现,但也需警惕过度消耗资源的问题。通过上述方法,您可以更好地管理和优化Go程序的性能。

回到顶部