代码之家  ›  专栏  ›  技术社区  ›  tomriddle_1234

如何使用并行for循环中的通道

go
  •  -5
  • tomriddle_1234  · 技术社区  · 7 年前
    func parallelSum (c chan int){
      sum := 0
      for i :=1 ; i< 100;i++{
        go func(i int){
            sum += i
        }(i)
      }
        time.Sleep(1*time.Second)
        c <- sum
    }
    

    我正在尝试学习并行能力来加速像OpenMP这样的东西。下面是一个在Go中进行总结并行循环的例子,这个函数作为goroutine运行。

    sum

    goroutine 4 [chan receive]:
    main.parallelSumError(0xc0000180c0)
        /home/tom/src/goland_newproject/main.go:58 +0xb4 //line 58 : temp := <-sum
    created by main.main
        /home/tom/src/goland_newproject/main.go:128 +0x2ca //line 128: go parallelSumError(pcr), the calling function
    

    那么这里有什么问题?似乎求和不是并行for循环的好例子,但实际上我想知道如何在并行for循环中使用通道。

    func parallelSum (c chan int){
        sum := make(chan int)
        for i :=1 ; i< 100;i++{
            go func(i int){
                temp := <- sum //error here why?
                temp += i
                sum <- temp
            }(i)
        }
        time.Sleep(1*time.Second)
        temp := <-sum
        c <- temp
    }
    

    两者的主要功能相同

    func main(){
        pc := make(chan int)
        go parallelSum(pc) 
        result = <- pc
        fmt.Println("parallel result:", result)
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Egorikas    7 年前

    我不喜欢通过渠道求和的想法。我宁愿用古典风格的 sync.Mutex atomic.AddUint64 . 但是,至少,我让你的代码起作用了。 temp 变量)。还有,还有 sync.WaitGroup

    package main
    
    import (
    "fmt"
    "sync"
    )
    
    func main() {
        pc := make(chan int)
        go parallelSum(pc)
        result := <- pc
        fmt.Println("parallel result:", result)
    }
    
    
    func parallelSum (c chan int){
        sum := make(chan int)
    
    
        wg := sync.WaitGroup{}
        wg.Add(100)
    
        for i :=1 ; i <= 100;i++{
            go func(i int){
                temp := <- sum
                temp += i
                wg.Done()
    
                sum <- temp
            }(i)
        }
    
        sum <- 0
    
        wg.Wait()
        temp := <- sum
        c <- temp
    }
    
        2
  •  1
  •   agastalver    7 年前

    当使用围棋程序时(即。 go foo() . 在这件事上,正如你提到的,渠道是golang处理沟通的方式。

    package main
    
    import (
        "fmt"
        "runtime"
    )
    
    func main() {
        numCPU := runtime.NumCPU()
        sumc := make(chan int, numCPU)
        valuec := make(chan int)
        endc := make(chan interface{}, numCPU)
    
        // generate go routine per cpu
        for i := 0; i < numCPU; i++ {
            go sumf(sumc, valuec, endc)
        }
    
        // generate values and pass it through the channels
        for i := 0; i < 100; i++ {
            valuec <- i
        }
    
        // tell go routines to end up when they are done
        for i := 0; i < numCPU; i++ {
            endc <- nil
        }
    
        // sum results
        sum := 0
        for i := 0; i < numCPU; i++ {
            procSum := <-sumc
            sum += procSum
        }
    
        fmt.Println(sum)
    }
    
    func sumf(sumc, valuec chan int, endc chan interface{}) {
        sum := 0
        for {
            select {
            case i := <-valuec:
                sum += i
            case <-endc:
                sumc <- sum
                return
            }
        }
    }
    

    希望这能有所帮助。