Skip to content

math/rand: rand.Float64() twice slower since Dec 18 #7267

@siritinga

Description

@siritinga
Hello everyone, 

I have noticed that the float random number generator in Go tip is slower than 1.2. I
have done some testing and most of the float functions of math/rand are slightly slower,
but Float64 is much slower, it takes twice the time. Benchmark here:
http://play.golang.org/p/_bjHfAtRv3

Checking the code, it seems than the problem appears in revision 3ed9d5c72102 in file
math/rand/rand.go, in particular:

changeset:   18661:3ed9d5c72102
user:        Jeff R. Allen <jra@nella.org>
date:        Wed Dec 18 15:38:53 2013 -0500
summary:     math/rand: Float32/64 must only return values in [0,1)

Diff for Float64:
 // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
-func (r *Rand) Float64() float64 { return float64(r.Int63()) / (1 << 63) }
+func (r *Rand) Float64() float64 { return float64(r.Int63n(1<<53)) / (1 <<
53) }

Discussed here:
https://groups.google.com/forum/#!searchin/golang-dev/rand.Float64/golang-dev/3b_OW2DYpbI/wuePqYv-JvsJ

After this change, Float64() uses Int63n() that is much slower than Int63. There is a
similar change for Float32(), using Int31n(), but Int31n is fast enough.

If it is possible to change it back somehow to Int63, speed should return to previous
values.

Maybe in a 64 bit system the difference is not noticeable. I have only tested in arm and
linux/386.

There is also a side effect: a random sequence of Floats will be different than in
previous Go versions, even if the same seed is used. That may affect the repeatability
of some tests (I don't think that would break the compatibility promise, but...)

(GO 1.2) $ go test -bench=.
BenchmarkFloat64         1000000              1211 ns/op
BenchmarkFloat32         1000000              1280 ns/op
BenchmarkExpFloat64      1000000              1184 ns/op
BenchmarkNormFloat64     1000000              1182 ns/op
BenchmarkInt     2000000               880 ns/op
BenchmarkIntn    1000000              1291 ns/op
BenchmarkInt31n  1000000              1248 ns/op
BenchmarkInt63n  1000000              2194 ns/op
BenchmarkInt31   2000000               873 ns/op
BenchmarkInt63   2000000               834 ns/op

(GO TIP) $ ~/gotip/go/bin/go version
go version devel +d067c6de4ec3 Wed Feb 05 01:24:51 2014 -0500 linux/arm
$ ~/gotip/go/bin/go test -bench=.
BenchmarkFloat64          500000              2646 ns/op
BenchmarkFloat32         1000000              1391 ns/op
BenchmarkExpFloat64      1000000              1196 ns/op
BenchmarkNormFloat64     1000000              1211 ns/op
BenchmarkInt     2000000               876 ns/op
BenchmarkIntn    1000000              1339 ns/op
BenchmarkInt31n  1000000              1271 ns/op
BenchmarkInt63n  1000000              2419 ns/op
BenchmarkInt31   2000000               874 ns/op
BenchmarkInt63   2000000               818 ns/op

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions