私は GO の世界に足を踏み入れたばかりなので、いつものように、いくつかの古典を新しい言語で実装して比較しようとしています。
同時実行を使用して、PI のモンテカルロ シミュレーションで奇妙な状況が発生しています。
- を使用してコードをコンパイルする
gc
と、任意の数のイベント値 (nevents
) に対して、すべてのゴルーチンが同時に開始され、すべてが期待どおりに動作するように指定しました ( 「同時実行性が並列処理ではない」場合でも、私は知っています) - を使用してコードをコンパイルすると、 が ~10.000.000 以下
gccgo
の場合は上記のように動作しますが、より大きな値の場合、前のゴルーチンがほぼ終了したときに各ゴルーチンが開始され、この動作はより大きな取得 (~100.000.000 )nevents
nvalues
私は何が欠けていますか?Go との最初の 1 週間です。
コードは次のとおりです。
package main
import ("os"
"fmt"
"log"
"strconv"
"math"
"math/rand"
"time"
)
var (ncpus int = 2
threadspercpu int = 2
ngophers int = ncpus*threadspercpu
rayu float64 = 1.0
)
func montecarlo(returnvalues chan int, gevents int, id int) {
// debug
fmt.Println("goroutine started")
randgen := rand.New(rand.NewSource(time.Now().UnixNano() +
int64(id*id + 1)))
insidecircle := 0
for i := 0; i < gevents; i++ {
if (math.Pow(randgen.Float64(), 2.0) +
math.Pow(randgen.Float64(), 2.0)) < rayu {
insidecircle++
}
}
// debug {
time.Sleep(time.Duration(id)*time.Second)
fmt.Println("goroutine finished")
// }
returnvalues <- insidecircle
}
func main() {
arg := os.Args[1]
nevents64, err := strconv.ParseInt(arg, 10, 32)
if (err != nil || nevents64 < 1) {
log.Fatalf("Invalid number of cases provided: '%s'", arg)
}
nevents := int(nevents64)
returnvalues := make(chan int)
gopherevents := nevents / ngophers
for i := 0; i < ngophers-1; i++ {
go montecarlo(returnvalues, gopherevents, i)
}
remaining := gopherevents + (nevents % ngophers)
go montecarlo(returnvalues, remaining, ngophers-1)
insidecircle_events := 0
for i := 0; i < ngophers; i++ {
insidecircle_events += <- returnvalues
}
fmt.Println("pi: ", (float64(insidecircle_events) /
float64(nevents) * 4))
}
デバッグを容易にするために時間遅延を追加しました。