douzhao5656 2016-01-15 03:15
浏览 5
已采纳

在Go程序中合理使用goroutines

My program has a long running task. I have a list jdIdList that is too big - up to 1000000 items, so the code below doesn't work. Is there a way to improve the code with better use of goroutines?

It seems I have too many goroutines running which makes my code fail to run.

What is a reasonable number of goroutines to have running?

var wg sync.WaitGroup
wg.Add(len(jdIdList))
c := make(chan string)

// just think jdIdList as [0...1000000]
for _, jdId := range jdIdList {
    go func(jdId string) {
        defer wg.Done()
        for _, itemId := range itemIdList {
            // following code is doing some computation which consumes much time(you can just replace them with time.Sleep(time.Second * 1)
            cvVec, ok := cvVecMap[itemId]
            if !ok {
                continue
            }
            jdVec, ok := jdVecMap[jdId]
            if !ok {
                continue
            }
            // long time compute
            _ = 0.3*computeDist(jdVec.JdPosVec, cvVec.CvPosVec) + 0.7*computeDist(jdVec.JdDescVec, cvVec.CvDescVec)
        }
        c <- fmt.Sprintf("done %s", jdId)
    }(jdId)

}

go func() {
    for resp := range c {
        fmt.Println(resp)
    }
}()
  • 写回答

1条回答 默认 最新

  • dpa89292 2016-01-15 03:59
    关注

    It looks like you're running too many things concurrently, making your computer run out of memory.

    Here's a version of your code that uses a limited number of worker goroutines instead of a million goroutines as in your example. Since only a few goroutines run at once, they have much more memory available each before the system starts to swap. Make sure the memory each small computation requires times the number of concurrent goroutines is less than the memory you have in your system, so if the code inside for jdId := range work loop requires less than 1GB memory, and you have 4 cores and at least 4 GB of RAM, setting clvl to 4 should work fine.

    I also removed the waitgroups. The code is still correct, but only uses channels for synchronization. A for range loop over a channel reads from that channel until it is closed. This is how we tell the worker threads when we are done.

    https://play.golang.org/p/Sy3i77TJjA

    runtime.GOMAXPROCS(runtime.NumCPU()) // not needed on go 1.5 or later
    c := make(chan string)
    work := make(chan int, 1) // increasing 1 to a higher number will probably increase performance
    clvl := 4 // runtime.NumCPU() // simulating having 4 cores, use NumCPU otherwise
    var wg sync.WaitGroup
    wg.Add(clvl)
    for i := 0; i < clvl; i++ {
        go func(i int) {
            for jdId := range work {
                time.Sleep(time.Millisecond * 100)
                c <- fmt.Sprintf("done %d", jdId)
            }
            wg.Done()
        }(i)
    }
    
    // give workers something to do
    go func() { 
        for i := 0; i < 10; i++ {
            work <- i
        }
    
        close(work)
    }()
    
    // close output channel when all workers are done
    go func() { 
        wg.Wait()
        close(c)
    }()
    
    count := 0
    for resp := range c {
        fmt.Println(resp, count)
        count += 1
    }
    

    which generated this output on go playground, while simulating four cpu cores.

    done 1 0
    done 0 1
    done 3 2
    done 2 3
    done 5 4
    done 4 5
    done 7 6
    done 6 7
    done 9 8
    done 8 9
    

    Notice how the ordering is not guaranteed. The jdId variable holds the value you want. You should always test your concurrent programs using the go race detector.

    Also note that if you are using go 1.4 or earlier and haven't set the GOMAXPROCS environment variable to the number of cores, you should do that, or add runtime.GOMAXPROCS(runtime.NumCPU()) to the beginning of your program.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥15 键盘指令混乱情况下的启动盘系统重装