https://isehara-3lv.sakura.ne.jp/blog/2023/01/12/goの並行処理/
ではWaitGroup使って終了を判定しましたが、Go独自の機能にスレッド間での通信機能channelを使う方法もあります。どちらが良いというのではなくて、目的によって使い分けするんだと思いますが。
以下はリンクの処理と同じく一千万までの素数を求める処理です。40行目付近から下のループ処理でchannelを使って素数をスライスに格納しています。channelが存在しないことはタイマーの一秒待ちで判定しています。
package main
import (
"sync"
"time"
"fmt"
)
//
// to use channel instead of "WaitGroup"
//
// in this case, slower than WaitGroup. Channel may be useful when it takes long processing time and less inforamtion size
//
func main() {
maxNumber := 1000*10000
var mu sync.Mutex
ch := make(chan int)
defer close(ch)
c := 2
oddCh := []int{}
tStart := time.Now()
tStop := time.Now()
for i := 2; i <= maxNumber; i++ {
go func() {
flag := true // if odd number, stay "true"
mu.Lock()
defer mu.Unlock()
for j :=2; j*j <= c ; j++ {
if c%j == 0{
flag = false
break
}
}
if flag == true{
ch <- c
}
c++
}()
}
for i:= 0; i < maxNumber; i++{ // set odd numbers to the slice
setBreak := false
select {
case p := <- ch:
oddCh = append(oddCh, p)
tStop = time.Now()
case <- time.After(time.Second): // to check last "ch" data
fmt.Println("Time Out!")
setBreak = true
}
if setBreak == true{
break
}
}
fmt.Println("len : ", len(oddCh))
el := tStop.Sub(tStart)
fmt.Println(el)
}
実はWaitGroupを使った場合に比較して、処理時間は5倍ぐらいになっています。おそらく渡しているのが素数というint形式データを渡しているだけでオーバーヘッドが大きい。したがってchannelを使うのに細かなデータをやり取りするには向かないんだろうと思います。
いずれにしろこのような簡単な処理では、goroutineも使わずにgoの実行環境でマルチコアを使う方が一番高速なのだから、余計なことをやらないのがいちばんのようです。
admin