開発環境
- macOS Mojave - Apple (OS)
- Emacs (Text Editor)
- Windows 10 Pro (OS)
- Visual Studio Code (Text Editor)
- Go (プログラミング言語)
並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング (Clay Breshears(著)、千住 治郎(翻訳)、オライリージャパン)の6章(並列和とプリフィックススキャン)、6.1(並列和)、6.1.2(より現実的なアルゴリズム)をC言語(Windowsスレッド、POSIXスレッド、Pthreadライブラリ、OpenMPライブラリ等)ではなくGo言語(go文、goroutine、channel等)で取り組んでみる。
コード
main_test.go
package main
import "testing"
var want = 55
var intSlice = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
func TestSummationSequential(t *testing.T) {
got := summationSequential(intSlice)
if got != want {
t.Errorf("summationSequential({%#v}) got %v, want %v",
intSlice, got, want)
}
}
func TestSummationConcurrent(t *testing.T) {
got := summationConcurrent(intSlice)
if got != want {
t.Errorf("summationConcurrent({%#v}) got %v, want %v",
intSlice, got, want)
}
}
main.go
package main
import (
"fmt"
"log"
"os"
"runtime"
"strconv"
"sync"
"time"
)
func main() {
numSlice := []int{}
max, err := strconv.Atoi(os.Args[1])
if err != nil {
log.Fatal(err)
}
for i := 1; i <= max; i++ {
numSlice = append(numSlice, i)
}
t1 := time.Now().UnixNano()
sum1 := summationSequential(numSlice)
t1 = time.Now().UnixNano() - t1
t2 := time.Now().UnixNano()
sum2 := summationConcurrent(numSlice)
t2 = time.Now().UnixNano() - t2
fmt.Printf("逐次アルゴリズム: %v %vミリ秒\n", sum1, t1/int64(time.Millisecond))
fmt.Printf("並行アルゴリズム: %v %vミリ秒\n", sum2, t2/int64(time.Millisecond))
}
func summationSequential(numSlice []int) int {
sum := 0
for _, x := range numSlice {
sum += x
}
return sum
}
func summationConcurrent(numSlice []int) int {
numCPU := runtime.NumCPU()
channelInt := make(chan int, numCPU)
lenNumSlice := len(numSlice)
lenPartial := lenNumSlice / numCPU
var wg sync.WaitGroup
for i := 0; i < numCPU; i++ {
wg.Add(1)
go func(j int) {
defer wg.Done()
var end int
if j == (numCPU - 1) {
end = lenNumSlice
} else {
end = lenPartial * (j + 1)
}
sum := 0
for i := lenPartial * j; i < end; i++ {
sum += numSlice[i]
}
channelInt <- sum
}(i)
}
sum := 0
go func() {
wg.Wait()
close(channelInt)
}()
for i := range channelInt {
sum += i
}
return sum
}
入出力結果(Bash、cmd.exe(コマンドプロンプト)、Terminal)
$ go test
# _/.../go/並行コンピューティング技法/ch6/sample1 [_/.../go/並行コンピューティング技法/ch6/sample1.test]
./main_test.go:9:9: undefined: summationSequential
./main_test.go:18:9: undefined: summationConcurrent
FAIL _/.../go/並行コンピューティング技法/ch6/sample1 [build failed]
$ go test
# _/.../go/並行コンピューティング技法/ch6/sample1 [_/.../go/並行コンピューティング技法/ch6/sample1.test]
./main_test.go:18:9: undefined: summationConcurrent
FAIL _/.../go/並行コンピューティング技法/ch6/sample1 [build failed]
$ go test
--- FAIL: TestSummationConcurrent (0.00s)
main_test.go:20: summationConcurrent({[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}) got 0, want 55
FAIL
exit status 1
FAIL _/.../go/並行コンピューティング技法/ch6/sample1 0.005s
$ go test
PASS
ok _/.../go/並行コンピューティング技法/ch6/sample1 0.005s
$ go run main.go 1000000
逐次アルゴリズム: 500000500000 0ミリ秒
並行アルゴリズム: 500000500000 0ミリ秒
$ go run main.go 10000000
逐次アルゴリズム: 50000005000000 6ミリ秒
並行アルゴリズム: 50000005000000 3ミリ秒
$ go run main.go 100000000
逐次アルゴリズム: 5000000050000000 68ミリ秒
並行アルゴリズム: 5000000050000000 37ミリ秒
$
0 コメント:
コメントを投稿