Why does adding concurrency slow down this golang code?

后端 未结 4 1292
天涯浪人
天涯浪人 2020-12-12 19:31

I\'ve got a bit of Go code that I\'ve been tinkering with to answer a little curiosity of mine related to a video game my brother-in-law plays.

Essentially, the cod

4条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-12 19:45

    The issue seems to come from your use of rand.Float64(), which uses a shared global object with a Mutex lock on it.

    Instead, if for each CPU you create a separate rand.New(), pass it through to the interactions(), and use it to create the Float64(), there's a massive improvement.


    Update to show the changes to the new example code in the question that now uses rand.New()

    The test() function was modified to either use a given channel, or return the result.

    func test(n int, c chan []int) []int {
        source := rand.NewSource(time.Now().UnixNano())
        generator := rand.New(source)
        simulations := make([]int, n)
        for i := range simulations {
            for _, v := range simulation(NUMBER_OF_INTERACTIONS, generator) {
                simulations[i] += v
            }   
        }   
        if c == nil {
            return simulations
        }   
        c <- simulations
        return nil 
    }
    

    The main() function was updated to run both tests, and output the timed result.

    func main() {
        rand.Seed(time.Now().UnixNano())
    
        nCPU := runtime.NumCPU()
        runtime.GOMAXPROCS(nCPU)
        fmt.Println("Number of CPUs: ", nCPU)
    
        start := time.Now()
        fmt.Println("Successful interactions: ", len(test(NUMBER_OF_SIMULATIONS, nil)))
        fmt.Println(time.Since(start))
    
        start = time.Now()
        tests := make([]chan []int, nCPU)
        for i := range tests {
            c := make(chan []int)
            go test(NUMBER_OF_SIMULATIONS/nCPU, c)
            tests[i] = c
        }
    
        // Concatentate the test results
        results := make([]int, NUMBER_OF_SIMULATIONS)
        for i, c := range tests {
            start := (NUMBER_OF_SIMULATIONS/nCPU) * i
            stop := (NUMBER_OF_SIMULATIONS/nCPU) * (i+1)
            copy(results[start:stop], <-c)
        }
        fmt.Println("Successful interactions: ", len(results))
        fmt.Println(time.Since(start))
    }
    

    The output is I received:

    > Number of CPUs:  2 
    >
    > Successful interactions:  1000 
    > 1m20.39959s
    >
    > Successful interactions:  1000
    > 41.392299s
    

提交回复
热议问题