저는 일반적으로 동시/병렬 프로그래밍에 익숙합니다. goroutines을 시험해보기 위해 (그리고 잘하면 성능상의 이점을 확인하기 위해), 나는 단일 goroutine에서 처음으로 1 억 개의 무작위 int
을 생성하는 작은 테스트 프로그램을 작성한 다음 runtime.NumCPU()
에 의해보고 된 많은 goroutines .Go에서 동시 발생 난수 생성
그러나 하나의 goroutines를 사용하는 것보다 더 많은 goroutines를 사용하여 지속적으로 성능이 저하됩니다. 내 프로그램 디자인이나 goroutines/채널/다른 Go 기능을 사용하는 방식에서 중요한 무엇인가를 놓치고 있다고 가정합니다. 모든 의견을 많이 주시면 감사하겠습니다.
아래 코드를 첨부합니다.
package main
import "fmt"
import "time"
import "math/rand"
import "runtime"
func main() {
// Figure out how many CPUs are available and tell Go to use all of them
numThreads := runtime.NumCPU()
runtime.GOMAXPROCS(numThreads)
// Number of random ints to generate
var numIntsToGenerate = 100000000
// Number of ints to be generated by each spawned goroutine thread
var numIntsPerThread = numIntsToGenerate/numThreads
// Channel for communicating from goroutines back to main function
ch := make(chan int, numIntsToGenerate)
// Slices to keep resulting ints
singleThreadIntSlice := make([]int, numIntsToGenerate, numIntsToGenerate)
multiThreadIntSlice := make([]int, numIntsToGenerate, numIntsToGenerate)
fmt.Printf("Initiating single-threaded random number generation.\n")
startSingleRun := time.Now()
// Generate all of the ints from a single goroutine, retrieve the expected
// number of ints from the channel and put in target slice
go makeRandomNumbers(numIntsToGenerate, ch)
for i := 0; i < numIntsToGenerate; i++ {
singleThreadIntSlice = append(singleThreadIntSlice,(<-ch))
}
elapsedSingleRun := time.Since(startSingleRun)
fmt.Printf("Single-threaded run took %s\n", elapsedSingleRun)
fmt.Printf("Initiating multi-threaded random number generation.\n")
startMultiRun := time.Now()
// Run the designated number of goroutines, each of which generates its
// expected share of the total random ints, retrieve the expected number
// of ints from the channel and put in target slice
for i := 0; i < numThreads; i++ {
go makeRandomNumbers(numIntsPerThread, ch)
}
for i := 0; i < numIntsToGenerate; i++ {
multiThreadIntSlice = append(multiThreadIntSlice,(<-ch))
}
elapsedMultiRun := time.Since(startMultiRun)
fmt.Printf("Multi-threaded run took %s\n", elapsedMultiRun)
}
func makeRandomNumbers(numInts int, ch chan int) {
source := rand.NewSource(time.Now().UnixNano())
generator := rand.New(source)
for i := 0; i < numInts; i++ {
ch <- generator.Intn(numInts*100)
}
}
좋아요, 모든 것이 합리적입니다. 나는 그것이 채널 사용과 관련된 비용과 관련이있을 것이라고 추측했다. (나는 작업 단위와 관련된 통신 오버 헤드에 관해서는 생각하지 않았지만 오히려 채널의 혼잡 가능성에 관해서 생각했다. 또는 그런 것). 명확하고 교육적인 연습에 많은 감사드립니다! – Karl