我想使用go例程将for循环并行.我试过使用频道,但没有用.我的主要问题是,我希望在继续之前等待所有迭代完成.这就是为什么简单地写之前它不起作用.我试图使用频道(我认为是错误的方式),但这使我的代码更慢
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 }
我的结构看起来像这样:
type Individual struct { gene []bool fitness int }
解决方法
所以基本上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,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,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() }