1
0
mirror of https://github.com/golang/go synced 2024-11-23 19:50:06 -07:00

math/rand: minor optimization to Perm

Instead of writing out 0..n and then reading it
back, just use i when it is needed.

Wikipedia calls this the "inside-out" implementation:
http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

This yields identical values to the previous
implementation, given the same seed. (Note that the
output from Example_rand is unchanged.)

2.8 GHz Intel Core i7, results very stable:

benchmark          old ns/op    new ns/op    delta
BenchmarkPerm3           138          136   -1.45%
BenchmarkPerm30          825          803   -2.67%

Stock Raspberry Pi, minimum improvement out of three runs:

benchmark          old ns/op    new ns/op    delta
BenchmarkPerm3          5774         5664   -1.91%
BenchmarkPerm30        32582        29381   -9.82%

R=golang-dev, dave, mtj, adg
CC=golang-dev
https://golang.org/cl/21030043
This commit is contained in:
Josh Bleecher Snyder 2013-12-17 13:49:34 +11:00 committed by Andrew Gerrand
parent 1561230ca0
commit 4a18e0edd9
2 changed files with 16 additions and 4 deletions

View File

@ -103,12 +103,10 @@ func (r *Rand) Float32() float32 { return float32(r.Float64()) }
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func (r *Rand) Perm(n int) []int { func (r *Rand) Perm(n int) []int {
m := make([]int, n) m := make([]int, n)
for i := 0; i < n; i++ {
m[i] = i
}
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
j := r.Intn(i + 1) j := r.Intn(i + 1)
m[i], m[j] = m[j], m[i] m[i] = m[j]
m[j] = i
} }
return m return m
} }

View File

@ -357,3 +357,17 @@ func BenchmarkInt31n1000(b *testing.B) {
r.Int31n(1000) r.Int31n(1000)
} }
} }
func BenchmarkPerm3(b *testing.B) {
r := New(NewSource(1))
for n := b.N; n > 0; n-- {
r.Perm(3)
}
}
func BenchmarkPerm30(b *testing.B) {
r := New(NewSource(1))
for n := b.N; n > 0; n-- {
r.Perm(30)
}
}