【发布时间】:2015-07-08 06:39:19
【问题描述】:
给定以下代码:
package main
import (
"fmt"
"runtime"
"time"
)
func f(from string) {
for i := 0; i < 3; i++ {
fmt.Println(from, ":", i)
//runtime.Gosched()
}
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU()*2)
time.Sleep(100)
go f("i am not parallel")
go f("neither me")
var input string
fmt.Scanln(&input)
}
大多数情况下的输出是:
我不平行:0
我不平行:1
我不平行:2
我都没有:0
我都没有:1
不是我:2
有时:
我也没有:0
我都没有:1
我都没有:2
我不平行:0
我不平行:1
我不平行:2
当 runtime.Gosched() 未注释时,一切似乎都正常。
我尝试将 GOMAXPROCS 编号从 2 更改为 NumCPU、goroutine 数量、周期:没有一个可以让它并行工作。
为什么会有这么奇怪的行为?
编辑: 好的,似乎上下文切换是一项繁重的工作,并且在没有合理问题的情况下不会经常完成。我仍然无法理解的一件事 - 为什么人们 get it to work 没有任何睡眠指令?
【问题讨论】:
-
您只需连续执行 3 个 println,而不会出现中间延迟。这项小工作连续完成似乎很合理。尝试在每个 println 之后/之前添加一个睡眠。线程/进程之间的切换不是免费的,因此它不是在每条指令之后完成的。
-
@hoijui 是的,它有效!但在示例中,我发现人们没有使用任何睡眠指令,而是切换了 printlns。此外,我尝试了多达 100 个不睡觉的循环,但它没有用。当我尝试 400 或更多时 - 它会切换但实际上并不经常。也许是硬件相关的问题?
-
我会说它更多的是软件(内核,使用的调度方法)然后是硬件相关的,但是,也是。一般来说,你应该依靠底层系统来正确地进行线程调度,除非你有很好的理由不这样做,并且认为你比编写 OS 内核的人更了解如何进行调度,以提高应用程序的性能。
标签: go parallel-processing goroutine