時代はマルチコア
一つのCPUに見せかけて、
複数のCPUが搭載されているのが今のパソコンの主流
せっかくマルチコアなんだし、
プログラミングもマルチコアを活かしたいということで、
Go言語のgoroutine(並行処理)を試してみた。
これで平行処理もばっちりだ。
と言うわけで、
平行処理の練習と解釈の意味を込めて、ここにメモを残す
本来、プログラミングは書いたコードを上から下に向かって順に実行していくもので、
package main import "fmt" func main() { var s string s = "Hello World!" fmt.Println(s) //Hello World!と実行される }
・main内のコードを実行します
・文字列を表示するためのライブラリを読み込んでおきます
・文字列を入れるためにメモリーを空けておきます。空けた領域をsと名付けます
・sにHello Worldという文字列を入れます
・sに入れた文字列を表示します
こんな感じで上から下にプログラムを実行していく。
これだと実行するのにコアが一つで十分で勿体ない。
なので平行で処理しましょ。
と言うことになる
例えば、
1から順に偶数であるか奇数であるかを調べる処理を作ってみる。
まずは普通に書くと
package main import "fmt" func main() { var i int //1~10まで順に調べる for { //10になったらやめる if i == 10 { break } //偶数の場合 if i%2 == 0 { fmt.Println("偶数です") //奇数の場合 } else { fmt.Println("奇数です") } i++ } }
こんな感じ
これを計算する処理と文字を表示する処理に分けてみる。
この時にchannelという互いの処理を繋ぐ変数を用意しておく必要がある。
計算する処理の方をsenderとし、
結果を受け取り表示するreceiverとしておく
とりあえず、senderとreceiverは置いといて、
先にchannelを用意して、senderとreceiverに突っ込む
func main() { //偶数の時はchが結果を受け取り、奇数の時はch2が結果を受け取るchannelを用意する ch := make(chan int) ch2 := make(chan int) go sender(ch, ch2) receiver(ch, ch2) }
関数名の前にgoと付けて実行すると、他のスレッドを用意して、平行で処理を開始する。
senderで計算した結果を受け取る処理を次の行で実行する。
ここまで書いた上で、senderとreceiverの処理を書いてみると
package main import "fmt" func sender(ch chan int, ch2 chan int) { var i int for { //偶数の場合 if i%2 == 0 { //結果をreceiverに送る ch <- i //奇数の場合 } else { //結果をreceiverに送る ch2 <- i } i++ } } func receiver(ch chan int, ch2 chan int) { //何回実行したか? var c int for { c++ select { //偶数の結果を受け取った時 case <-ch: fmt.Println("偶数です") //奇数の結果を受け取った時 case <-ch2: fmt.Println("奇数です") } //結果を10回受け取ったら終了 if c == 10 { break } } } func main() { ch := make(chan int) ch2 := make(chan int) go sender(ch, ch2) receiver(ch, ch2) }
こんな感じ
senderでは計算してreceiverに結果を送る。
この時にchannelを使うんだけど、
それをch := make(chan int)で用意する。
(ch2も同様に用意)
それらを各関数に入れて、処理を開始する
senderではreceiverに結果を送らなければならないので、
計算結果を ch <- iという形で<-でchに入れる
一方、receiverではchに入っている値を受け取らなければならないので、
<- chと書いて値を受け取る。
(receiverのchはsenderからの値が送信されるまで待機してくれる)
今回はあえて、偶数であればch、奇数であればch2にして、
receiverの方のselect文で
case <- ch: つまり、偶数のchannelを受け取った時に処理、
case <- ch2: 奇数のchannelを受け取った時の処理の様に分けて書いてみた。
このコードを実行してみると、
偶数です 奇数です 偶数です 奇数です 偶数です 奇数です 偶数です 奇数です 偶数です 奇数です
こうなった。
まぁ、まったくgoroutineが活かされてないけど、
とりあえずマルチコアっぽい処理は書けた。