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)
对于您的具体问题,您根本不需要使用渠道。
\n\n然而,除非你createIndividual花一些时间进行计算,否则并行运行时,goroutines 之间的上下文切换总是会慢得多。
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}\nRun 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\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
3073 次 |
| 最近记录: |