2016-08-19 74 views
0

昨天我發佈了一個幾乎相同的代碼的問題,詢問如何在一個可變參數函數中使這個併發。解決之後,我預計該程序的運行時間幾乎與使用一個生成器的時間相同,而且與30+相同。它似乎並不如此。爲什麼這麼慢用goroutines?

我看到的時代是一臺發電機,大約5ms。用下面的代碼,150ms。 (由於某些原因,play.golang顯示0)。

爲什麼它慢?我的期望是,在多個門廳的情況下,這需要很長的時間。有什麼事情可以做起來呢?

package main 

import (
    "fmt" 
    "sync" 
    "time" 
) 

func main() { 
    t := time.Now() 
    _ = fanIn(
     generator(4, 5, 6, 7), 
     generator(1, 2, 6, 3, 7), 
     generator(12, 15, 33, 40, 10), 
     generator(18, 13, 20, 40, 15), 
     generator(100, 200, 64000, 3121, 1237), 
     generator(4, 5, 6, 7), 
     generator(1, 2, 6, 3, 7), 
     generator(12, 15, 33, 40, 10), 
     generator(18, 13, 20, 40, 15), 
     generator(100, 200, 64000, 3121, 1237), 
     generator(4, 5, 6, 7), 
     generator(1, 2, 6, 3, 7), 
     generator(12, 15, 33, 40, 10), 
     generator(18, 13, 20, 40, 15), 
     generator(100, 200, 64000, 3121, 1237), 
     generator(4, 5, 6, 7), 
     generator(1, 2, 6, 3, 7), 
     generator(12, 15, 33, 40, 10), 
     generator(18, 13, 20, 40, 15), 
     generator(100, 200, 64000, 3121, 1237), 
     generator(4, 5, 6, 7), 
     generator(1, 2, 6, 3, 7), 
     generator(12, 15, 33, 40, 10), 
     generator(18, 13, 20, 40, 15), 
     generator(100, 200, 64000, 3121, 1237), 
     generator(4, 5, 6, 7), 
     generator(1, 2, 6, 3, 7), 
     generator(12, 15, 33, 40, 10), 
     generator(18, 13, 20, 40, 15), 
     generator(100, 200, 64000, 3121, 1237), 
     generator(4, 5, 6, 7), 
     generator(1, 2, 6, 3, 7), 
     generator(12, 15, 33, 40, 10), 
     generator(18, 13, 20, 40, 15), 
     generator(100, 200, 64000, 3121, 1237), 
    ) 

    fmt.Println(time.Now().Sub(t)) 
} 

func generator(nums ...int) <-chan int { 
    out := make(chan int, 10) 
    go func() { 
     defer close(out) 
     for _, v := range nums { 
      out <- v 
     } 
    }() 
    return out 
} 

func fanIn(in ...<-chan int) <-chan int { 
    var wg sync.WaitGroup 
    out := make(chan int, 10) 
    wg.Add(len(in)) 

    go func() { 
     for _, v := range in { 
      go func(ch <-chan int) { 
       defer wg.Done() 
       for val := range ch { 
        out <- val 
       } 
      }(v) 
     } 

    }() 
    go func() { 
     wg.Wait() 
     close(out) 
    }() 
    return out 
} 
+1

什麼是你的圍棋版本,有多少CPU內核你有,對我來說是小於1ms。 – 2016-08-19 18:29:19

+0

我已經去版本go1.6.2達爾文/ amd64,MBP 2.9 GHz英特爾酷睿i5。 –

+0

另外,我用'跑步'而不是安裝,我認爲這是最慢的。測試不是爲了讓它跑得快,而是要看看我是否可以以相同的速度運行多臺發電機。只是FYI。 –

回答

2

go rungo build之間的差別不大(編譯時間):
17ms(2個芯)和3ms(8芯)與go1.7 amd64

go rungo build之間差:
951.0543ms-934.0535ms = 17.0008ms(on 2 Cores)
575.3447ms-572.3914ms = 2.9533ms(8芯)

8個磁芯和與go build 2個纖芯之間的區別:
934.0535ms-572.3914ms = 361.6621ms

爲了獲得良好的基準統計,使用大量的樣品。
嘗試更新到最新的Go版本(1.7)。

嘗試此工作示例代碼,和你的結果與這些輸出比較:

package main 

import (
    "fmt" 
    "math/rand" 
    "sync" 
    "time" 
) 

func main() { 
    t := time.Now() 
    cs := make([]<-chan int, 1000) 
    for i := 0; i < len(cs); i++ { 
     cs[i] = generator(rand.Perm(10000)...) 
    } 
    ch := fanIn(cs...) 
    fmt.Println(time.Now().Sub(t)) 

    is := make([]int, 0, len(ch)) 
    for v := range ch { 
     is = append(is, v) 
    } 
    fmt.Println("len=", len(is)) 
} 

func generator(nums ...int) <-chan int { 
    out := make(chan int, len(nums)) 
    go func() { 
     defer close(out) 
     for _, v := range nums { 
      out <- v 
     } 
    }() 
    return out 
} 

func fanIn(in ...<-chan int) <-chan int { 
    var wg sync.WaitGroup 
    out := make(chan int, 10) 
    wg.Add(len(in)) 

    go func() { 
     for _, v := range in { 
      go func(ch <-chan int) { 
       defer wg.Done() 
       for val := range ch { 
        out <- val 
       } 
      }(v) 
     } 

    }() 
    go func() { 
     wg.Wait() 
     close(out) 
    }() 
    return out 
} 

輸出用2根芯線(go run):

951.0543ms 
len= 10000000 

輸出用2根芯線(go build):

934.0535ms 
len= 10000000 

帶有8個內核的輸出(使用go run):

575.3447ms 
len= 10000000 

輸出與8根芯線(go build):

572.3914ms 
len= 10000000 
+0

@ nathan-hyland我希望這會有所幫助。 – 2016-08-19 19:27:27