開発環境
- macOS Mojave - Apple (OS)
- Emacs (Text Editor)
- Windows 10 Pro (OS)
- Visual Studio Code (Text Editor)
- Go (プログラミング言語)
並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング (Clay Breshears(著)、千住 治郎(翻訳)、オライリージャパン)の5章(スレッドライブラリ)、5.2(明示的スレッドライブラリ)、5.2.1(Pthread)をC言語(POSIXスレッド、Pthreadライブラリ、OpenMPライブラリ等)ではなくGo言語(go文、goroutine、channel等)で取り組んでみる。
コード
sample1_test.go
package main import "fmt" func ExamplePi1() { fmt.Printf("%.2f", pi1()) // Output: 3.14 } func ExamplePi2() { fmt.Printf("%.2f", pi2()) // Output: 3.14 }
sample1.go
package main import ( "fmt" "runtime" "sync" "time" ) func main() { t := time.Now().UnixNano() p1 := pi1() fmt.Printf( "逐次処理: %vミリ秒\n", (time.Now().UnixNano()-t)/int64(time.Millisecond)) t = time.Now().UnixNano() p2 := pi2() fmt.Printf( "並行処理: %vミリ秒\n", (time.Now().UnixNano()-t)/int64(time.Millisecond)) fmt.Println("逐次処理: π ≒", p1) fmt.Println("並行処理: π ≒", p2) } func pi1() float64 { const numRects = 10e8 partialHeight := 0.0 for i := 0; i < numRects; i++ { x := (float64(i) + 0.5) / numRects partialHeight += 4.0 / (1.0 + x*x) } return partialHeight * 1 / numRects } func pi2() float64 { const numRects = 10e8 numCPU := runtime.NumCPU() areaChannel := make(chan float64, numCPU) var wg sync.WaitGroup for i := 0; i < numCPU; i++ { wg.Add(1) go func(i int) { defer wg.Done() partialHeight := 0.0 for j := i; j < numRects; j += numCPU { x := (float64(j) + 0.5) / numRects partialHeight += 4.0 / (1.0 + x*x) } areaChannel <- partialHeight * 1 / numRects }(i) } go func() { wg.Wait() close(areaChannel) }() areaTotal := 0.0 for area := range areaChannel { areaTotal += area } return areaTotal }
入出力結果(Bash、cmd.exe(コマンドプロンプト)、Terminal)
$ go test # _/Users/.../go/並行コンピューティング技法/ch5/sample1 [_/Users/.../go/並行コンピューティング技法/ch5/sample1.test] ./sample1_test.go:6:21: undefined: pi1 ./sample1_test.go:11:21: undefined: pi2 FAIL _/Users/.../go/並行コンピューティング技法/ch5/sample1 [build failed] $ go test PASS ok _/Users/.../go/並行コンピューティング技法/ch5/sample1 3.356s $ go run sample1.go 逐次処理: 2547ミリ秒 並行処理: 667ミリ秒 逐次処理: π ≒ 3.141592653589971 並行処理: π ≒ 3.141592653589768 $
並行処理の方が速いことを確認出来た。結果が違うのは、浮動小数点数の計算の順番が逐次処理と並行処理で異なる可能性があるから、その途中で丸め誤差が発生してるのかも。
syncパッケージの構造体MutexとそのLockメソッド、Unlockメソッドを使えばグローバル変数を使用した、より本著のC言語のコードに近く書けるけど、最初にチャンネルを利用したくなったから少し異なる書き方で書いてみた。どちらがGopherらしいのかはまだよく分かってない。
0 コメント:
コメントを投稿