|
|
51CTO旗下网站
|
|
移动端

10.4.1 多核并行化

《Go语言编程入门与实战技巧》第10章并发编程,本章Go语言里的并发指的是能让某个函数独立于其他函数运行的能力。当一个函数创建为协程(goroutine)时,Go语言会将其视为一个独立的工作单元,这个单元会被调度到可用的逻辑处理器上执行。本节为大家介绍多核并行化。

作者:黄靖钧来源:电子工业出版社|2018-09-23 09:53

10.4  并发进阶

10.4.1  多核并行化

在执行一些"昂贵"的计算任务时,我们希望能够尽量利用现代服务器普遍具备的多核特性尽量将任务并行化,从而达到降低总计算时间的目的。此时需要了解CPU核心的数量,并有针对性地分解计算任务到多个goroutine中去并行运行。

下面模拟一个完全可以并行的计算任务,计算n个整型数的总和。可以将所有整型数分成m份,m即CPU的个数。让每个CPU开始计算分给它的那份计算任务,最后将每个CPU的计算结果再做一次累加,这样就可以得到所有n个整型数的总和:

  1. type Vector []float64  
  2.  
  3. // 分配给每个CPU的计算任务  
  4. func (v Vector) DoSome(i, n int, u Vector, c chan int) {  
  5.     for ; i < n; i++ {  
  6.         v[i] += u.Op(v[i])  
  7.     }  
  8.     c <- 1 // 发信号告诉任务管理者我已经计算完成了  
  9. }  
  10.  
  11. const NCPU = 8 // 假设总共有8核  
  12. func (v Vector) DoAll(u Vector) {  
  13.     c :make(chan int, NCPU) // 用于接收每个CPU的任务完成信号  
  14.     for i :0; i < NCPU; i++ {  
  15.         go v.DoSome(i*len(v)/NCPU, (i+1)*len(v)/NCPU, u, c)  
  16.     }  
  17.  
  18.     // 等待所有CPU的任务完成  
  19.     for i :0; i < NCPU; i++ {  
  20.         <-c // 获取到一个数据,表示一个CPU计算完成了  
  21.     }  
  22.     // 到这里表示所有计算已经结束  
  23. }  

这两个函数看起来设计非常合理。DoAll()会根据CPU核心的数目对任务进行分割,然后开辟多个goroutine并行执行这些计算任务。

是否可以将总的计算时间降到接近原来的1/n呢?答案是不一定。如果使用Benchmark方法,会发现总的执行时间没有明显缩短。再去观察CPU运行状态,你会发现尽管有8个CPU核心,但在计算过程中其实只有一个CPU核心处于繁忙状态,这是会让很多Go语言初学者迷惑的问题。

官方的答案是,这是当前版本的Go语言编译器还不能很智能地去发现和利用多核的优势。虽然确实创建了多个goroutine,并且从运行状态看这些goroutine也都在并行运行,但实际上所有这些goroutine都运行在同一个CPU核心上,在一个goroutine得到时间片执行的时候,其他goroutine都会处于等待状态。从这一点可以看出,虽然goroutine简化了写并行代码的过程,但实际上整体运行效率并不真正高于单线程程序。

在Go语言升级到默认支持多CPU的某个版本之前,可以先通过设置环境变量GOMAXPROCS的值来控制使用多少个CPU核心。具体操作方法是通过直接设置环境变量GOMAXPROCS的值,或者在代码中启动goroutine之前先调用以下这个语句以设置使用8个CPU核心:

  1. runtime.GOMAXPROCS(16) 

到底应该设置多少个CPU核心呢?其实runtime包中还提供了另外一个函数NumCPU()来获取核心数。可以看到,Go语言其实已经感知到所有的环境信息,下一版本中完全可以利用这些信息将goroutine调度到所有CPU核心上,从而最大化地利用服务器的多核计算能力。抛弃GOMAXPROCS只是个时间问题。


喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书会第9群:808517103

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

基于Eclipse的开源框架技术与实战

当前,开源框架层出不穷,它为用户提供了通用的解决方案,同时也增加了用户的学习难度。开源是一把“双刃剑”,一方面它共享了资源,提供了...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊