19794


Goroutineを使って下記プログラムを作成しました。(Playgroundで実行できませんがローカルではできます)  
<https://play.golang.org/p/5IdzS4FAtp>

しかし、これはでスタックしてしまいます。  
このようなプログラムをスタックせずに実行するにはどうすればいいのでしょうか。

プログラム

[code]

    package main
    
    import "fmt"
    import "runtime"
    
    func main() {
        runtime.GOMAXPROCS(runtime.NumCPU())
        msgCh := make(chan string)
        count := 0.0
        for i := 0; i < 255; i++ {
            go first(msgCh)
        }
    
    L:
        for {
            select {
            case msg := <-msgCh:
                count++
                fmt.Printf("%f:%s\n", count, msg)
                if count == 4294967296 {
                    break L
                }
            default:
            }
        }
    
    }
    
    func first(msgCh chan string) {
        for i := 0; i < 255; i++ {
            go second(msgCh)
        }
    }
    
    func second(msgCh chan string) {
        for i := 0; i < 255; i++ {
            go third(msgCh)
        }
    }
    
    func third(msgCh chan string) {
        for i := 0; i < 255; i++ {
            msgCh <- "Hello"
        }
    }
    
[/code]


CC BY-SA 3.0
2015-12-08T13:15:54.823
19765
2015-12-09T05:57:42.813
2015-12-08T13:24:57.700
7232
7232
question
go goroutine
GoのGoroutine について教えて下さい。


Channelを閉じてないので永久にblockしてます。計算が終わった時点でchannelを閉じてやりましょう。

[code]

    package main
    
    import (
        "fmt"
        "runtime"
    )
    
    func main() {
        msgCh := make(chan string)
        count := 0.0
        for i := 0; i < 2; i++ {
            go first(msgCh)
        }
    
        done := false
        for {
            select {
            case msg, ok := <-msgCh:
                if !ok {
                    done = true
                    break
                }
                count++
                fmt.Printf("%f:%s\n", count, msg)
                if count == 16 {
                    close(msgCh)
                }
            }
    
            if done {
                break
            }
        }
    
    }
    
    func first(msgCh chan string) {
        for i := 0; i < 2; i++ {
            go second(msgCh)
        }
    }
    
    func second(msgCh chan string) {
        for i := 0; i < 2; i++ {
            go third(msgCh)
        }
    }
    
    func third(msgCh chan string) {
        for i := 0; i < 2; i++ {
            msgCh <- "Hello"
        }
    }
    
[/code]


CC BY-SA 3.0
2015-12-08T18:04:45.580
19773
2015-12-08T18:04:45.580
226
19765
answer


質問欄にあるプログラムを以下の環境で実行してみました。

  * CPU: Intel(R) Xeon(R) CPU E5-2640 v3 @ 2.60GHz 
  * コア数: 8 (with Hyper-Threading)
  * メモリ: 64 GB
  * OS: CentOS Linux 7.0
  * Golang version: devel +b2963a5

まず、メモリの使用量なのですが、最大で 41 GB にもなります。lightweight とはいえ、255*255*255 個の goroutine
を生成していますので仕方のない事なのでしょう。また、途中までの経過時間から線形外挿すると実行時間は 250 分程度(4時間強)になるかと思われます。

そんなわけで goroutine の最大同時実行数を 255 として、かつ、channel を `[255]string` 型にして channel
に対する入出力の回数を減らしてみました。

[code]

    package main
    
    import (
      "fmt"
      "os"
    )
    import "runtime"
    
    const msgLen int = 255
    
    type helloString [msgLen]string
    type helloChannel chan helloString
    
    func main() {
      runtime.GOMAXPROCS(runtime.NumCPU())
      msgCh := make(helloChannel)
    
      for i := 0; i < msgLen*msgLen; i++ {
        for j := 0; j < msgLen; j++ {
          go third(msgCh)
        }
    
        for j := 0; j < msgLen; j++ {
          for k, msg := 0, <-msgCh; k < msgLen; k++ {
            fmt.Printf("%d: %s\n", i*msgLen*msgLen+j*msgLen+k, msg[k])
          }
        }
      }
      close(msgCh)
    }
    
    func third(msgCh helloChannel) {
      var hello helloString
      for i := 0; i < msgLen; i++ {
        hello[i] = "Hello"
      }
      msgCh <- hello
    }
    
[/code]

最大メモリ使用量は 30 MB 弱、実行時間は 47分 でした。

# まぁ、あまり効果はないですね。。。


CC BY-SA 3.0
2015-12-09T05:57:42.813
19794
2015-12-09T05:57:42.813
19765
answer