猿问

Goroutines - 为什么我只看到最后的并行执行

设置

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


func f(from string) { // Bench

    // Loop for i < 40 -> fib(i)

}


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

    // Fibonacci implementation

}


func main() {


    go f("|||") // <- Should alternate

    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()' 到第一秒后收敛。为什么?什么是更好的测试?


心有法竹
浏览 167回答 2
2回答

桃花长相依

这里有很多事情在起作用。Go 运行时可以自由地安排你的 goroutines 以任何顺序和任何它喜欢的持续时间运行。因此,您应该获得“并排”执行的假设并不完全有效。此外,很可能您还没有设置 GOMAXPROCS,这意味着运行时默认使用 CPU 的单个核心。如果您设置 GOMAXPROCS > 1,则运行时可以选择在多个内核线程上调度您的 goroutine,而内核又可以将这些线程调度为在 CPU 的多个内核上运行。这可能会给您带来您期望的输出。

幕布斯7119047

除了 Seth Hoenig 的有用回答之外,并发性和并行性之间存在重要区别。Goroutines 为您提供并发性,这意味着您正在描述理论上同时发生的活动,但只是在抽象意义上。并行是指事情真正同时发生。你的假设是你会立即看到并行性。习惯于使用 OS 线程的人自然会想到并行性——更快的速度通常是所希望的目标。Goroutines不是操作系统线程,而是允许您设计并发系统,这些系统实际上可能会或可能不会以并行方式执行。目标更多是关于设计的清晰度而不是提高性能……但是您只需一点技巧就可以实现两者。
随时随地看视频慕课网APP

相关分类

Go
我要回答