Goroutines – 为什么我只在最后看到并行执行的情况

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

Goroutines - why do I see side-by-side execution only towards the end

问题

设置

我写了这个小程序来了解执行线程的工作原理。这是一个简化版本,你可以在github上找到完整的版本。

func f(from string) { // Bench
    // 循环 i < 40 -> fib(i)
}

func fib(n int64) int { // Something non-linear
    // Fibonacci 实现
}

func main() {

    go f("|||") // <- 应该交替执行
    go f("---") // <-

    var input string
    fmt.Scanln(&input)
    fmt.Println("done")
}

关于输出,前两行是:

||| fib(0): 0
--- fib(0): 0

然后一直是 --- 直到:

--- fib(28): 317811

此时 ||| 接管并独自执行直到:

||| fib(29): 514229

在接近结尾时,它们开始并行执行,完整的测试结果在这里

--- fib(36): 14930352
||| fib(36): 14930352
--- fib(37): 24157817
||| fib(37): 24157817
--- fib(38): 39088169
||| fib(38): 39088169
--- fib(39): 63245986
||| fib(39): 63245986

问题

我最初的假设是,使用 go f() 应该会得到一个相对随机的并行执行,但实际上它以不同大小的块交替执行,直到第29次调用 f() 才开始交替执行。为什么会这样?有什么更好的测试方法吗?

英文:

The setup

I wrote this little program to see how threads of execution work. Here's a simplified version, you can find the full one on github

func f(from string) { // Bench
    // Loop for i &lt; 40 -&gt; fib(i)
}

func fib(n int64) int { // Something non-linear
    // Fibonacci implementation
}

func main() {

    go f(&quot;|||&quot;) // &lt;- Should alternate
    go f(&quot;---&quot;) // &lt;-

    var input string
    fmt.Scanln(&amp;input)
    fmt.Println(&quot;done&quot;)
}

As for output, the very first two lines

||| fib( 0 ): 0
--- fib( 0 ): 0

Then it's all --- up to

--- fib( 28 ): 317811

At which point ||| takes over and goes solo up to

||| fib( 29 ): 514229

And towards the end, they start executing "side-by-side", the complete test dump is here

--- fib( 36 ): 14930352
||| fib( 36 ): 14930352
--- fib( 37 ): 24157817
||| fib( 37 ): 24157817
--- fib( 38 ): 39088169
||| fib( 38 ): 39088169
--- fib( 39 ): 63245986
||| fib( 39 ): 63245986

The question

My initial assumption was - with go f() I should get a relatively random side-by-side execution, but instead it alternates in chunks of varying size that converge way after 29 calls to 'f()' to first-second. Why is that so? What could be a better test?

答案1

得分: 3

这里有几个因素在起作用。

Go运行时可以自由地安排goroutine以任何顺序和任何持续时间运行。因此,假设你应该得到“并行”执行并不完全有效。此外,很可能你没有设置GOMAXPROCS,这意味着运行时默认使用CPU的一个核心。如果你设置了GOMAXPROCS > 1,运行时可以选择在多个内核线程上安排你的goroutine,而这些线程又可以由内核安排在CPU的多个核心上运行。这可能会给你期望的输出。

英文:

There are a number of things at play here.

The Go runtime is free to schedule your goroutines to run in whatever order and for whatever duration it pleases. So the assumption that you should get "side-by-side" execution isn't quite valid. Also, most likely you have not set GOMAXPROCS, which means the runtime by default uses a single core of your cpu. If you set GOMAXPROCS > 1, the runtime has the option of scheduling your goroutines on multiple kernel threads, which in turn could be scheduled by the kernel to run on multiple cores of your CPU. This may give you kind of output your are expecting.

答案2

得分: 2

在Seth Hoenig的有益回答之后,并发性和并行性之间存在重要的区别。Goroutines提供了并发性,这意味着你描述的活动在概念上是同时发生的,但只是在抽象意义上。并行性是指事物真正同时发生。你的假设是你会立即看到并行性的发生。

习惯于使用操作系统线程的人自然会考虑并行性-更快的速度通常是期望的目标。Goroutines并不是操作系统线程,而是允许你设计并发系统的工具,这些系统可能实际上并不会以并行方式执行。目标更多地是关于设计的清晰性,而不是改进性能...但只需一点技巧,你可以同时实现两者。

Rob Pike在这个优秀的讲座中详细介绍了这个问题,希望我的总结能对他的讲解有所帮助。

英文:

Further to Seth Hoenig's helpful answer, there is an important difference between concurrency and parallelism. Goroutines give you concurrency, which means you're describing activity that is notionally happaning at the same time, but only in an abstract sense. Parallelism is when things truly happen at the same time. Your assumption is that you will immediately see parallelism in action.

People who are used to working with OS threads naturally think of parallelism - faster speed is often the hoped-for objective. Goroutines are not OS threads, but instead they allow you to design concurrent systems that may or may not actually execute with parallelism. The objective is more about clarity of design than improved performance ... but you can achieve both with just a little skill.

Rob Pike gave an excellent lecture on this, and hope my summary here does him justice.

huangapple
  • 本文由 发表于 2014年3月14日 03:18:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/22388747.html
匿名

发表评论

匿名网友

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

确定