golang runtime實現多核並行任務

hongmingover發表於2018-11-01

golang runtime實現多核並行任務

 

    首先我們需要明確一下並行跟併發的區別,併發一般是被核心通過時間片或者中斷來控制的,遇到io阻塞或者時間片用完的時會轉移執行緒的使用權。一個核的情況下不可能有並行的情況,因為同一時間只有一個任務在排程。  

 

該文章寫的有些亂,歡迎來噴 ! 另外文章後續不斷更新中,請到原文地址檢視更新。

http://xiaorui.cc/2016/03/05/golang-runtime%E5%AE%9E%E7%8E%B0%E5%A4%9A%E6%A0%B8%E5%B9%B6%E8%A1%8C%E4%BB%BB%E5%8A%A1/

 

    Golang預設所有的任務都在一個cpu核裡,如果想使用多核來跑goroutine的任務,需要配置runtime.GOMAXPROCS。 GOMAXPROCS的數目根據自己任務量分配就可以了,有個前提是不要大於你的cpu核數。 並行比較適合那種cpu密集型計算,如果是IO密集型使用多核的化會增加cpu切換的成本。

 

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

package main

//xiaorui.cc

 

import (

"fmt"

"runtime"

)

 

func test(c chan bool, n int) {

 

x := 0

for i := 0; i < 1000000000; i++ {

x += i

}

println(n, x)

if n == 10 {

c <- true

}

}

 

func main() {

runtime.GOMAXPROCS(3)

c := make(chan bool)

 

for i := 0; i < 200; i++ {

go test(c, i)

}

 

<-c

 

fmt.Println("main end...")

 

}

 

 

對於經常使用python multiprocessing多程式模組來跑多核多工的我來說,不再有GIL全域性鎖是個很美妙的事情。   我們通過top可以看到上面的例項程式碼跑到了cpu 270% . 跟我們上面配置的runtime.GOMAXPROCS(3)相對應。 

對於goroutine任務的終止也是有技巧的,他不能像多程式那樣,直接給kill掉。  他只能是通過類似flag訊號控制,每個goroutine執行的函式邏輯裡都要判斷flag標示位是否為stop狀態。

 

需要特意說明一點是,你在測試併發的時候,往往會把一個函式寫成死迴圈並做計算,你雖然這段函式用go關鍵詞併發了,但是你會發現他無法執行後面的邏輯。你需要做的是配置多核,或者是time.Sleep()。  這是為什麼 ? Golang是自己管理調整goroutine,如果你的一個func始終不釋放資源,那麼其他的goroutine不會去搶奪資源。 當然這樣的場景只有在測試時候遇到,正常場景下不可能沒有中斷和堵塞的情況。 

 

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

package main

 

import (

"fmt"

"runtime"

_ "time"

)

 

var (

flag = false

str  string

)

 

func xiaorui() {

flag = true

str = "setup flag to true"

}

 

func main() {

runtime.GOMAXPROCS(1)

go xiaorui()

//time.Sleep(1 * time.Second)

       // 理論來說,當我在xiaorui()把flag 改為true後,後面的邏輯會退出.

for {

if flag {

break

}

}

fmt.Println(str)

}

 

 

 

我們不斷的調整的runtime.GOMAXPROCS(num) ,會發現執行的速度越來越快,但不要超過你的cpu數,因為那是徒勞的。 同樣的程式碼我用python multiprocessing pool也實現了一份,我在MAC和線上伺服器做過測試,效能要遠高於python。

相關文章