果然,我的 Golang 只使用一个 CPU 是错误的

尝试了一下使用多线程的Go语言编程,因为它可以轻松地利用多个CPU,但结果只有一个CPU达到了100%。

只使用一个CPU

package main

import (
  "fmt"
  "sync"
  "time"
)

func main() {
  fmt.Println("start")
  var wg sync.WaitGroup
  for _, a := range []string{"1", "2"} {
    wg.Add(1)
    go func(str string) {
      i := 0
      fmt.Println("I'm " + str)
      time.Sleep(1) // 時分割なので2番目が開始するまで待つ
      for {
          i++;
      }
      wg.Done()
    }(a)
  }
  wg.Wait()
  fmt.Println("end")
}
$ go run calc.go &
start
I'm 1
I'm 2

$ mpstat -P ALL 2
平均値:   CPU    %usr  %idle
平均値:     0  100.00   0.00
平均値:     1    0.25  99.50

是什么导致了这个结果?

将GOMAXPROCS的初始值设为1,这意味着默认情况下会将一个核心分时执行(并行处理),如果要使用多个CPU进行并行处理,则需要将CPU的数量设为GOMAXPROCS的值。

package main

import (
  "fmt"
  "sync"
  "time"
  "runtime"
)

func main() {
  fmt.Println("start")
  fmt.Printf("NumCPU=%d\n", runtime.NumCPU())
  runtime.GOMAXPROCS(runtime.NumCPU())

  var wg sync.WaitGroup
  for _, a := range []string{"1", "2"} {
    wg.Add(1)
    go func(str string) {
      i := 0
      fmt.Println("I'm " + str)
      time.Sleep(1)
      for {
          i++;
      }
      wg.Done()
    }(a)
  }
  wg.Wait()
  fmt.Println("end")
}
$ go run calc2.go
NumCPU=2
I'm 1
I'm 2
$ mpstat -P ALL 2
平均値:   CPU    %usr   %idle
平均値:     0  100.00   0.00
平均値:     1  100.00   0.00

并行处理和并行处理

calc.go和calc2.go的处理方式分别是并发处理和并行处理。

在《龙珠》中进行类比说明,
并行处理就像是孙悟空的多重残像拳,悟空以超高速切换不同位置,看起来像是多个人,但实际上只有一个人。
而并列处理就像是天津饭的四身之拳,天津饭真的变成了四个人。

由于并行处理将一个CPU按时间分割运行,所以第二个CPU没有被使用,一直处于闲置状态。

请参阅

来看看 – Go语言的并发与并行性模式 – Qiita
http://qiita.com/hayajo/items/4cd75f87e35e60ae11a9#并行性模式

根据CPU数量限制并行处理数量 | SOTA
http://deeeet.com/writing/2014/07/30/golang-parallel-by-cpu/

为什么没有多核支持?

为什么不支持多核处理器?

前往- sync.WaitGroup的正确使用方法- Qiita
http://qiita.com/ruiu/items/dba58f7b03a9a2ffad65

作为一个只做过动态语言的人,我在38天里学会了如何使用Go语言编写代码 – Qiita
http://qiita.com/suin/items/22662f43b6a6e8728798

在golang中进行并行处理 – golang并行处理-堆栈溢出

在 Github 上的 astaxie/build-web-application-with-golang 倉庫的 master 分支中的 02.7.md 文件。

阅读关于并行和并列的《并行计算技术》一文 – M-Tea
http://www.m-tea.info/2011/03/concurrent-parallel-01.html

广告
将在 10 秒后关闭
bannerAds