疑似乱数生成器 spiegel-im-spiegel/mt をリリースした

no extension

ついカッとなって書いた。 反省はしていない。

Mersenne TwisterGo 言語実装はいくつかあるのだが,やっぱ他人が作る道具は使いにくいよね,というわけで自分で書いてしまった(笑) spiegel-im-spiegel/mt の特徴は以下の通り。

  • math/rand 互換で rand.Rand のソースとして利用できる
  • goroutine-safe な構成にできる(mt.PRNG 型を利用した場合)

使い方は以下を参照のこと。

一応,ベンチマークテストもしてみた。

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/randrand.Rand ラッパ)
BenchmarkRandomMT19917Rand mt/mt19937rand.Rand ラッパ)
BenchmarkRandomALFGLocked math/rand Sync バージョン
BenchmarkRandomMT19917Locked mt/mt19937mt.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 のほうが若干速いかな。 乱数としての性能は別の機会に。

参考図書

photo
プログラミング言語Go
アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)
丸善出版 2016-06-20 (Release 2021-07-13)
Kindle版
B099928SJD (ASIN)
評価     

Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想はこちら

reviewed by Spiegel on 2021-05-22 (powered by PA-APIv5)

photo
数学ガール/乱択アルゴリズム
結城 浩 (著)
SBクリエイティブ 2011-02-25 (Release 2014-03-12)
Kindle版
B00I8AT1FO (ASIN)
評価     

工学ガール,リサちゃん登場!

reviewed by Spiegel on 2015-04-19 (powered by PA-APIv5)


  1. math/rand パッケージに実装されている擬似乱数生成器はラグ付フィボナッチ法(Lagged Fibonacci Generator)のバリエーションらしい。 ↩︎