【问题标题】:Goroutines don't work in parallelGoroutines 不能并行工作
【发布时间】: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


【解决方案1】:

你不应该预测 goroutine 的时间表。通过运行您提供的示例,我得到了这个输出。

direct : 0
direct : 1
direct : 2
goroutine : 0
goroutine : 1
goroutine : 2
going
done

如果我在 main 函数的开头添加runtime.GOMAXPROCS(4),并在我的 i5 Qcore 桌面 ubuntu 上运行它,它会输出

direct : 0
direct : 1
direct : 2
goroutine : 0
goroutine : 1
goroutine : 2
going

done

我认为它并不总是产生相同的输出。所以我们应该假设goroutine可以并行,如果你需要控制顺序,请添加锁。

【讨论】:

  • 我也得到了相同的输出。这个例子的作者怎么能得到他得到的——这就是问题所在。也许他只是假设并编写了“compile-in-mind”输出
  • 当然不是in mind。如果你在 main 函数的最开始添加runtime.GOMAXPROCS(4),你会得到direct : 0 direct : 1 direct : 2 goroutine : 0 goroutine : 1 going goroutine : 2 done
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-22
  • 1970-01-01
  • 2020-11-18
  • 2017-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多