runtime: improve fastrand with a better generator

The current generator is a simple LSFR, which showed strong
correlation in higher bits, as manifested by fastrandn().

Change it with xorshift64+, which is slightly more complex,
has a larger state, but has a period of 2^64-1 and is much better
at statistical tests. The version used here is capable of
passing Diehard and even SmallCrush.

Speed is slightly worse but is probably insignificant:

name                old time/op  new time/op  delta
Fastrand-4          0.77ns ±12%  0.91ns ±21%  +17.31%  (p=0.048 n=5+5)
FastrandHashiter-4  13.6ns ±21%  15.2ns ±17%     ~     (p=0.160 n=6+5)
Fastrandn/2-4       2.30ns ± 5%  2.45ns ±15%     ~     (p=0.222 n=5+5)
Fastrandn/3-4       2.36ns ± 7%  2.45ns ± 6%     ~     (p=0.222 n=5+5)
Fastrandn/4-4       2.33ns ± 8%  2.61ns ±30%     ~     (p=0.126 n=6+5)
Fastrandn/5-4       2.33ns ± 5%  2.48ns ± 9%     ~     (p=0.052 n=6+5)

Fixes #21806

Change-Id: I013bb37b463fdfc229a7f324df8fe2da8d286f33
Reviewed-on: https://go-review.googlesource.com/62530
Run-TryBot: Michael Munday <mike.munday@ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Giovanni Bajo 2017-09-09 14:59:06 +02:00 committed by Michael Munday
parent a5d6b41449
commit e7e4a4ffa3
4 changed files with 83 additions and 19 deletions

View file

@ -414,7 +414,9 @@ type m struct {
newSigstack bool // minit on C thread called sigaltstack
printlock int8
incgo bool // m is executing a cgo call
fastrand uint32
fastrand [2]uint32
needextram bool
traceback uint8
ncgocall uint64 // number of cgo calls in total
ncgo int32 // number of cgo calls currently in progress
cgoCallersUse uint32 // if non-zero, cgoCallers in use temporarily
@ -424,14 +426,12 @@ type m struct {
schedlink muintptr
mcache *mcache
lockedg guintptr
createstack [32]uintptr // stack that created this thread.
freglo [16]uint32 // d[i] lsb and f[i]
freghi [16]uint32 // d[i] msb and f[i+16]
fflag uint32 // floating point compare flags
locked uint32 // tracking for lockosthread
nextwaitm uintptr // next m waiting for lock
needextram bool
traceback uint8
createstack [32]uintptr // stack that created this thread.
freglo [16]uint32 // d[i] lsb and f[i]
freghi [16]uint32 // d[i] msb and f[i+16]
fflag uint32 // floating point compare flags
locked uint32 // tracking for lockosthread
nextwaitm uintptr // next m waiting for lock
waitunlockf unsafe.Pointer // todo go func(*g, unsafe.pointer) bool
waitlock unsafe.Pointer
waittraceev byte