LoginSignup
0
0

More than 5 years have passed since last update.

プログラミング言語Goを読みながらメモ(第九章)

Posted at

プログラミング言語 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ルーチンとスレッド。

百万段のパイプライン

練習問題に「ひとつの値がパイプライン全体を伝わっていくのに、どのくらいの時間を要するでしょうか。」という問題があったので、測ってみた。

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ルーチンを作れとも言われたけど、百万でも限界に達していないので気にしないことにした。

ピンポン

続いてまた練習問題
「二つのバッファなしチャネルを介して卓球のようにメッセージを(略)一秒で何回の通信を行うことができるでしょうか。」

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 を変えると実行時間がどう変わるか。

go
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章のメモはここまで。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0