英文:
Why doesn't the Go statement execute in parallel?
问题
我正在测试这段Go代码在我的VirtualBox上的Ubuntu 11.4上运行。
package main
import ("fmt";"time";"big")
var c chan *big.Int
func sum(start, stop, step int64) {
bigStop := big.NewInt(stop)
bigStep := big.NewInt(step)
bigSum := big.NewInt(0)
for i := big.NewInt(start); i.Cmp(bigStop) < 0; i.Add(i, bigStep) {
bigSum.Add(bigSum, i)
}
c <- bigSum
}
func main() {
s := big.NewInt(0)
n := time.Nanoseconds()
step := int64(4)
c = make(chan *big.Int, int(step))
stop := int64(100000000)
for j := int64(0); j < step; j++ {
go sum(j, stop, step)
}
for j := int64(0); j < step; j++ {
s.Add(s, <-c)
}
n = time.Nanoseconds() - n
fmt.Println(s, float64(n)/1000000000.)
}
Ubuntu可以访问我所有的4个核心。我通过同时运行几个可执行文件和系统监视器来检查这一点。
但是当我尝试运行这段代码时,它只使用一个核心,并没有获得任何并行处理的好处。
我做错了什么?
英文:
I'm testing this Go code on my VirtualBoxed Ubuntu 11.4
package main
import ("fmt";"time";"big")
var c chan *big.Int
func sum( start,stop,step int64) {
bigStop := big.NewInt(stop)
bigStep := big.NewInt(step)
bigSum := big.NewInt(0)
for i := big.NewInt(start);i.Cmp(bigStop)<0 ;i.Add(i,bigStep){
bigSum.Add(bigSum,i)
}
c<-bigSum
}
func main() {
s := big.NewInt( 0 )
n := time.Nanoseconds()
step := int64(4)
c = make( chan *big.Int , int(step))
stop := int64(100000000)
for j:=int64(0);j<step;j++{
go sum(j,stop,step)
}
for j:=int64(0);j<step;j++{
s.Add(s,<-c)
}
n = time.Nanoseconds() - n
fmt.Println(s,float64(n)/1000000000.)
}
Ubuntu has access to all my 4 cores. I checked this with simultaneous run of several executables and System Monitor.
But when I'm trying to run this code, it's using only one core and is not gaining any profit of parallel processing.
What I'm doing wrong?
答案1
得分: 24
你可能需要查看Go FAQ中的并发部分,特别是这两个问题,并确定哪个(如果不是两个都是)适用于你的情况:
为什么我的多goroutine程序不使用多个CPU?
您必须设置GOMAXPROCS shell环境变量或使用类似命名的函数来允许运行时支持利用多个操作系统线程。
执行并行计算的程序应该从增加GOMAXPROCS中受益。但是,请注意并发不等于并行。
为什么使用GOMAXPROCS > 1有时会使我的程序变慢?
这取决于您的程序的性质。包含多个goroutine并且在通道上花费大量时间进行通信的程序在使用多个操作系统线程时会遇到性能下降。这是因为在线程之间发送数据涉及到显著的上下文切换开销。
Go的goroutine调度器还不够好。将来,它应该能够识别这种情况并优化其对操作系统线程的使用。目前,GOMAXPROCS应该根据每个应用程序的情况进行设置。
有关此主题的更多详细信息,请参阅名为并发不等于并行的演讲。
英文:
You probably need to review the Concurrency section of the Go FAQ, specifically these two questions, and work out which (if not both) apply to your case:
> Why doesn't my multi-goroutine program
> use multiple CPUs?
>
> You must set the GOMAXPROCS shell environment
> variable or use the similarly-named function
> of the runtime package to allow the run-time
> support to utilize more than one OS thread.
>
> Programs that perform parallel computation
> should benefit from an increase in GOMAXPROCS.
> However, be aware that concurrency is not parallelism.
>
> Why does using GOMAXPROCS > 1
> sometimes make my program slower?
>
> It depends on the nature of your
> program. Programs that contain several
> goroutines that spend a lot of time
> communicating on channels will
> experience performance degradation
> when using multiple OS threads. This
> is because of the significant
> context-switching penalty involved in
> sending data between threads.
>
> Go's goroutine scheduler is not as
> good as it needs to be. In future, it
> should recognize such cases and
> optimize its use of OS threads. For
> now, GOMAXPROCS should be set on a
> per-application basis.
>
> For more detail on this topic see the
> talk entitled Concurrency is not Parallelism.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论