疑似乱数生成器 spiegel-im-spiegel/mt をリリースした
ついカッとなって書いた。 反省はしていない。
Mersenne Twister の Go 言語実装はいくつかあるのだが,やっぱ他人が作る道具は使いにくいよね,というわけで自分で書いてしまった(笑) spiegel-im-spiegel/mt の特徴は以下の通り。
使い方は以下を参照のこと。
一応,ベンチマークテストもしてみた。
package main
import (
"math/rand"
"testing"
"time"
"github.com/spiegel-im-spiegel/mt"
"github.com/spiegel-im-spiegel/mt/mt19937"
)
const count = 10000000
func BenchmarkRandomALFG(b *testing.B) {
rnd := rand.NewSource(time.Now().UnixNano()).(rand.Source64)
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
}
}
func BenchmarkRandomMT19917(b *testing.B) {
rnd := mt19937.NewSource(time.Now().UnixNano())
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
}
}
func BenchmarkRandomALFGRand(b *testing.B) {
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
}
}
func BenchmarkRandomMT19917Rand(b *testing.B) {
rnd := rand.New(mt19937.NewSource(time.Now().UnixNano()))
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
}
}
func BenchmarkRandomALFGLocked(b *testing.B) {
b.ResetTimer()
for i := 0; i < count; i++ {
rand.Uint64()
}
}
func BenchmarkRandomMT19917Locked(b *testing.B) {
rnd := mt.New(mt19937.NewSource(time.Now().UnixNano()))
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
}
}
テスト対象は以下の通り。
テスト名 | 対象 |
---|---|
BenchmarkRandomALFG |
math/rand 標準アルゴリズム1 |
BenchmarkRandomMT19917 |
mt /mt19937 パッケージ |
BenchmarkRandomALFGRand |
math/rand (rand .Rand ラッパ) |
BenchmarkRandomMT19917Rand |
mt /mt19937 (rand .Rand ラッパ) |
BenchmarkRandomALFGLocked |
math/rand Sync バージョン |
BenchmarkRandomMT19917Locked |
mt /mt19937 + mt .PRNG |
このベンチマークテストの実行結果は以下の通り。
$ go test -bench Random -benchmem
goos: linux
goarch: amd64
pkg: github.com/spiegel-im-spiegel/mt/benchmark
BenchmarkRandomALFG-4 1000000000 0.0492 ns/op 0 B/op 0 allocs/op
BenchmarkRandomMT19917-4 1000000000 0.0651 ns/op 0 B/op 0 allocs/op
BenchmarkRandomALFGRand-4 1000000000 0.0749 ns/op 0 B/op 0 allocs/op
BenchmarkRandomMT19917Rand-4 1000000000 0.0846 ns/op 0 B/op 0 allocs/op
BenchmarkRandomALFGLocked-4 1000000000 0.176 ns/op 0 B/op 0 allocs/op
BenchmarkRandomMT19917Locked-4 1000000000 0.192 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/spiegel-im-spiegel/mt/benchmark 7.081s
というわけで math/rand のほうが若干速いかな。 乱数としての性能は別の機会に。
参考図書
- プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
- Alan A.A. Donovan (著), Brian W. Kernighan (著), 柴田 芳樹 (翻訳)
- 丸善出版 2016-06-20
- 単行本(ソフトカバー)
- 4621300253 (ASIN), 9784621300251 (EAN), 4621300253 (ISBN), 9784621300251 (ISBN)
- 評価
著者のひとりは(あの「バイブル」とも呼ばれる)通称 “K&R” の K のほうである。この本は Go 言語の教科書と言ってもいいだろう。
- 数学ガール/乱択アルゴリズム
- 結城 浩 (著)
- SBクリエイティブ 2011-02-25 (Release 2014-03-12)
- Kindle版
- B00I8AT1FO (ASIN)
- 評価
工学ガール,リサちゃん登場!
-
math/rand パッケージに実装されている擬似乱数生成器はラグ付フィボナッチ法(Lagged Fibonacci Generator)のバリエーションらしい。 ↩︎