プログラミング言語 Go を読みながらメモ。
第一章 : https://qiita.com/Nabetani/items/077c6b4d3d1ce0a2c3fd
第二章 : https://qiita.com/Nabetani/items/d053304698dfa3601116
第三章 : https://qiita.com/Nabetani/items/2fd9c372fcd8383955a5
第四章 : https://qiita.com/Nabetani/items/59bfd00dc3323883a07f
第五章 : https://qiita.com/Nabetani/items/4b785f1c9b0b26d48475
第六章 : https://qiita.com/Nabetani/items/1c100394a65af6506187
第七章 : https://qiita.com/Nabetani/items/6553ad253af77661e915
第八章 : https://qiita.com/Nabetani/items/3b2e3964159cc292fe00
で。
第9章は前半わりと普通なスレッドの話だった。
sync.Once
とか あったけどね。
「並列的で待たされないキャッシュ」のところはしっかり理解できていないけど先に進むことにした。
そして 9.8 goルーチンとスレッド。
百万段のパイプライン
練習問題に「ひとつの値がパイプライン全体を伝わっていくのに、どのくらいの時間を要するでしょうか。」という問題があったので、測ってみた。
package main
import (
"fmt"
"time"
)
const nofChans = 1000000
func main() {
var chs [nofChans]chan int
for i := 0; i < nofChans; i++ {
chs[i] = make(chan int)
}
for i := 0; i < nofChans-1; i++ {
go func(i int) {
val := <-chs[i]
chs[i+1] <- (val + 1)
}(i)
}
start := time.Now()
fmt.Println("start : ", start)
chs[0] <- 1
fmt.Println(<-chs[nofChans-1])
ended := time.Now()
fmt.Println("ended : ", time.Now())
fmt.Println(ended.Sub(start)) // 814.117133ms
chanTime := ended.Sub(start).Seconds() * 1000 * 1000 / nofChans
fmt.Printf("%.3f[μs]\n", chanTime) // 0.801[μs]
}
こんな感じ。百万段のパイプラインを1秒弱で伝わった。
chan
一個あたり1マイクロ秒ぐらいで伝わるらしい。
スレッドで似たようなことを書く方法が良くわからない。比べたいんだけどなぁ。
メモリの限界までgoルーチンを作れとも言われたけど、百万でも限界に達していないので気にしないことにした。
ピンポン
続いてまた練習問題
「二つのバッファなしチャネルを介して卓球のようにメッセージを(略)一秒で何回の通信を行うことができるでしょうか。」
package main
import (
"fmt"
"time"
)
func main() {
c0 := make(chan int)
c1 := make(chan int)
rt := 0
go func() {
for {
rt++
n := <-c0
c1 <- n + 1
}
}()
go func() {
for {
n := <-c1
c0 <- n + 1
}
}()
timer := time.NewTimer(time.Second)
c0 <- 1
<-timer.C
fmt.Println(rt) // 2186179
}
手元のマシンで2百万往復ぐらい。
GOMAXPROCS
重い計算をたくさんさせて、GOMAXPROCS を変えると実行時間がどう変わるか。
package main
import (
"math"
)
const nof_chans = 10000
const loop = 100000
func main() {
var res [nof_chans]chan float64
for i := 0; i < nof_chans; i++ {
res[i] = make(chan float64)
}
for i := 0; i < nof_chans; i++ {
go func(i int) {
r := 0.0
for c := 0; c < loop; c++ {
r = math.Sin(r + float64(i))
}
res[i] <- r
}(i)
}
for i := 0; i < nof_chans; i++ {
<-res[i]
}
}
何の意味もない計算ですいません。
で。結果は下表。
GOMAXPROCS | real | user |
---|---|---|
1 | 31.03 | 30.87 |
2 | 16.16 | 32.06 |
3 | 10.74 | 31.82 |
4 | 8.16 | 32.04 |
5 | 6.67 | 32.61 |
6 | 5.68 | 32.99 |
7 | 4.95 | 33.27 |
8 | 4.49 | 33.39 |
9 | 4.46 | 33.4 |
10 | 4.55 | 33.39 |
100 | 4.43 | 33.41 |
1000 | 4.64 | 34.21 |
マシンは MacBook Pro (Retina, 15-inch, Mid 2015)。コア数4。
表を見るとコア数が 8 に見えるけど、ハイパースレッディングとかそういうことかな。
9章のメモはここまで。