From: Josh Bleecher Snyder Date: Tue, 17 Dec 2013 02:49:34 +0000 (+1100) Subject: math/rand: minor optimization to Perm X-Git-Tag: go1.3beta1~1213 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4a18e0edd94d156ebbccead44b553e2a436df5f5;p=gostls13.git 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 --- diff --git a/src/pkg/math/rand/rand.go b/src/pkg/math/rand/rand.go index 2157cdb465..04fb67d19d 100644 --- a/src/pkg/math/rand/rand.go +++ b/src/pkg/math/rand/rand.go @@ -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). func (r *Rand) Perm(n int) []int { m := make([]int, n) - for i := 0; i < n; i++ { - m[i] = i - } for i := 0; i < n; i++ { j := r.Intn(i + 1) - m[i], m[j] = m[j], m[i] + m[i] = m[j] + m[j] = i } return m } diff --git a/src/pkg/math/rand/rand_test.go b/src/pkg/math/rand/rand_test.go index 4d3abdb606..4f0a8d0ee9 100644 --- a/src/pkg/math/rand/rand_test.go +++ b/src/pkg/math/rand/rand_test.go @@ -357,3 +357,17 @@ func BenchmarkInt31n1000(b *testing.B) { 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) + } +}