我想使用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()
}