私は、一般的な並行/並列プログラミングに進んでいます。 goroutinesを試してみるために、私は単純に1億のランダムなものを生成する小さなテストプログラムを作りました。int
- 最初は1つのゴルーチンで、次に多くのゴルーチンでruntime.NumCPU()
。Goで同時に乱数を生成
しかし、私は一貫してより多くのゴルーチンを使用してパフォーマンスを悪化させます。私は自分のプログラムデザインや、ゴルーチン/チャンネル/その他の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