タグ : Go

Go 勉強会した #0

この前の土・日にコンパイラの授業でGoの勉強会(もとい、ソース読み会)が行われた。
ものすごい濃い2日間だったので、まとめておく。

下準備

資料

  • Go プロジェクトページ
  • How to Install
  • チュートリアル等(English)
    • Install

      hgでリポジトリをclone。How toのページではhttps経由だったけど、Pythonのsslモジュールがないとか起こられたりしたので、http経由だと落とせた。

      hg clone -r release https://go.googlecode.com/hg/ $GOROOT

      インストールは$GOROOT,$GOOARCH,$GOARCHをShellの環境変数にexportして$GOROOT/src/all.bashを実行すればOK。ちなみに、$GOBINを指定しないと~/binに実行ファイルがデフォルトでおかれる。

      gtags

      Goのソース読み会では、プロジェクタでソース映しながら教授の講義とともに進めて行くかんじ。といっても、受講生は3人で学生にバシバシ読ませてたけど。ちなみに、自分の担当はyacc,lexなどの構文解析まわりだったり。

      ソース読み会が初めてな僕に、gtagsなるツールがないと話にならないというアドバイスを先輩からもらったので、早速設定。
      gtags使うと、シンボルとか関数の定義/参照とかをファイルをまたいで飛びまわれるという便利なもの。大きなソースを読むのにはかかせないらしい。

      ソースディレクトリのルートで”gtags -v”を実行するだけで準備完了。結構すぐタグファイルが生成されたりして興奮した。

      Goの特徴とか

      Goの勉強会は、Goの実装を読むことがメインなソース読み会だったのでGoでプログラムを書いたりなどはほとんどしなかった。
      (チュートリアルを高速で読んだり)

      チュートリアルを作成

      • “go”でスレッド生成 : go-routine
      • channelでスレッドとやりとり(joinもchannelで)
      • “;”を(一部)省省略できる
      • 型推論
      • 多値
        • チュートリアル読んで、go-routineで積分近似(台形公式…)を行うプログラム書いてみた。

          package main

          import ("fmt"; "strconv"; "math"; "os")

          func main() {

              if len(os.Args) < 2 {
                  fmt.Println("args: number-of-thread");
                  os.Exit(1)
              }

              /* Setting the environment variable $GOMAXPROCS or calling↓
                 runtime.GOMAXPROCS() will change the number of user threads↓ */


              Thread, err := strconv.Atoi(os.Args[1]);
              n := 10000000;

              if (err != nil) {
                  fmt.Println(err);
                  os.Exit(1)
              }

              var (
                  Pi = 4*math.Atan(1);
                  start, end, result float64  = 0.0, Pi, 0.0;
                  h float64 = (end - start) / float64(n)
              )

              ch := make(chan float64);

              //Function literals are indeed closures
              trap := func(start, end, h float64, n int, ch chan float64, f (func(float64) float64)) {
                  var integral, x float64 = (f(start) + f(end)) / 2., start;

                  for i := 1; i <= n - 1; i++ {
                      x += h;
                      integral += f(x)
                  }
                  integral *= h;
                  ch <- integral
              };

              //Let's go!
              for i := 0; i < Thread; i += 1 {
                  fmt.Printf("- call go-routine %d -\n", i);
                  var local_start = start + float64(i) * float64(n / Thread) * h;
                  var local_end   = local_start + float64(n / Thread) * h;
                  //Function-literal can be argument
                  go trap(local_start, local_end, h, (n / Thread), ch,
                      func(a float64) float64 { return math.Sin(a) })
              }

              fmt.Println("- now calculating with go-routine -");

              for i := 0; i < Thread; i++ { result += <-ch }

              fmt.Printf("- integral f(x) with %f to %f\n number-of-Threads = %d, accuracy = %d \n = %f\n",
                  start, end, Thread, n, result)
          }

          Shellの環境変数$GOMAXPROCSで、同時実行できるgo-routineの数を指定できる。デフォルトでは1

          SHINYA% export GOMAXPROCS=1
          SHINYA% time ./trapezoidal_integrate 2
          - call go-routine 0 -
          - call go-routine 1 -
          - now calculating with go-routine -
          - integral f(x) with 0.000000 to 3.141593
           number-of-Threads = 2, accuracy = 10000000
           = 2.000000
          ./trapezoidal_integrate 2  1.87s user 0.01s system 98% cpu 1.915 total
          SHINYA% export GOMAXPROCS=2
          SHINYA% time ./trapezoidal_integrate 2
          - call go-routine 0 -
          - call go-routine 1 -
          - now calculating with go-routine -
          - integral f(x) with 0.000000 to 3.141593
           number-of-Threads = 2, accuracy = 10000000
           = 2.000000
          ./trapezoidal_integrate 2  1.87s user 0.01s system 178% cpu 1.053 total

          $GOMAXPROCSを2で。ちゃんと2倍の速度が出て満足満足。

          次回は

          ソースに踏み込んで、Goの構文解析周りを報告するよ!(予定)

 
Better Tag Cloud