并行For循环

Phi*_*der 8 concurrency for-loop go

我想使用go例程将for循环并行.我试过使用频道,但没有用.我的主要问题是,我希望在继续之前等待所有迭代完成.这就是为什么简单地写go之前它不起作用.我试图使用频道(我认为是错误的方式),但这使我的代码更慢

func createPopulation(populationSize int, individualSize int) []Individual {
    population := make([]Individual, populationSize)

    //i want this loop to be work parallel
    for i := 0; i < len(population); i++ {
        population[i] = createIndividual(individualSize)
    }

    return population
}

func createIndividual(size int) Individual {
    var individual = Individual{make([]bool, size), 0}

    for i := 0; i < len(individual.gene); i++ {
        if rand.Intn(2)%2 == 1 {
            individual.gene[i] = true
        } else {
            individual.gene[i] = false
        }
    }

    return individual
}
Run Code Online (Sandbox Code Playgroud)

我的结构看起来像这样:

type Individual struct {
    gene []bool
    fitness int
}
Run Code Online (Sandbox Code Playgroud)

Not*_*fer 10

所以基本上goroutine不应该返回一个值,而是将其推向一个通道.如果你想等待所有goroutine完成,你可以只计算goroutines的数量,或使用WaitGroup.在这个例子中,它是一种矫枉过正,因为它的大小是众所周知的,但无论如何它都是很好的做法.这是一个修改过的例子:

package main

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

type Individual struct {
    gene    []bool
    fitness int
}


func createPopulation(populationSize int, individualSize int) []Individual  {

    // we create a slice with a capacity of populationSize but 0 size
    // so we'll avoid extra unneeded allocations
    population := make([]Individual, 0, populationSize)

    // we create a buffered channel so writing to it won't block while we wait for the waitgroup to finish
    ch := make(chan Individual, populationSize)

    // we create a waitgroup - basically block until N tasks say they are done
    wg := sync.WaitGroup{}

    for i := 0; i < populationSize; i++ {

        //we add 1 to the wait group - each worker will decrease it back
        wg.Add(1)

        //now we spawn a goroutine
        go createIndividual(individualSize, ch, &wg)
    }

    // now we wait for everyone to finish - again, not a must.
    // you can just receive from the channel N times, and use a timeout or something for safety
    wg.Wait()

    // we need to close the channel or the following loop will get stuck
    close(ch)

    // we iterate over the closed channel and receive all data from it
    for individual := range ch {

        population = append(population, individual)
    }
    return population

}   

func createIndividual(size int, ch chan Individual, wg *sync.WaitGroup) {

    var individual = Individual{make([]bool, size), 0}

    for i := 0; i < len(individual.gene); i++ {
        if rand.Intn(2)%2 == 1 {
            individual.gene[i] = true
        } else {
            individual.gene[i] = false
        }
    }

    // push the population object down the channel
    ch <- individual
    // let the wait group know we finished
    wg.Done()

}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,但我觉得`population:= make([] Individual,populationSize)`应该是`population:= make([] Individual,0)`在这个例子中,否则`append`语句放置一个空切片长度`populationSize`结尾的新个体.http://play.golang.org/p/6eYlk40Oal (3认同)
  • 已修复以分配具有已知*容量*但仅有0个成员的切片. (3认同)

One*_*One 5

对于您的具体问题,您根本不需要使用渠道。

\n\n

然而,除非你createIndividual花一些时间进行计算,否则并行运行时,goroutines 之间的上下文切换总是会慢得多。

\n\n
type Individual struct {\n    gene    []bool\n    fitness int\n}\n\nfunc createPopulation(populationSize int, individualSize int) (population []*Individual) {\n    var wg sync.WaitGroup\n    population = make([]*Individual, populationSize)\n\n    wg.Add(populationSize)\n    for i := 0; i < populationSize; i++ {\n        go func(i int) {\n            population[i] = createIndividual(individualSize)\n            wg.Done()\n        }(i)\n    }\n    wg.Wait()\n    return\n}\n\nfunc createIndividual(size int) *Individual {\n    individual := &Individual{make([]bool, size), 0}\n\n    for i := 0; i < size; i++ {\n        individual.gene[i] = rand.Intn(2)%2 == 1\n    }\n\n    return individual\n}\n\nfunc main() {\n    numcpu := flag.Int("cpu", runtime.NumCPU(), "")\n    flag.Parse()\n    runtime.GOMAXPROCS(*numcpu)\n    pop := createPopulation(1e2, 21e3)\n    fmt.Println(len(pop))\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
\xe2\x94\x8c\xe2\x94\x80 oneofone@Oa [/tmp]                                                                                                            \n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x9e\x9c go build blah.go; xtime ./blah -cpu 1\n100\n0.13u 0.00s 0.13r 4556kB ./blah -cpu 1\n\xe2\x94\x8c\xe2\x94\x80 oneofone@Oa [/tmp]                                                                                                            \n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x9e\x9c go build blah.go; xtime ./blah -cpu 4\n100\n2.10u 0.12s 0.60r 4724kB ./blah -cpu 4\n
Run Code Online (Sandbox Code Playgroud)\n