JuliaLang/julia — pull request #8808 by rfourquet (2014-10-24 21:50:49+00:00)
Title: dSFMT: use fill_array_* API instead of genrand_* API

Mixing both APIs led to bug #6573. As a result `fill_array_*` functions were no more used. This PR proposes instead to use them exclusively with `MersenneTwister` objects (I could do the same for the global RNG if there is interest), for faster random generation (up to 2x or 3x on my machine).

Looking at the dSFMT code, my understanding is that both take advantage of simd instructions, but use different algorithms:
* `fill_array_*` generates random values (considering only `Float64` values for now) into an array of size (at least) `dsfmt_min_array_size`, using a state array of size `dsfmt_min_array_size`,

* whereas `genrand_*` cyclically overwrites a state array of size `dsfmt_min_array_size` filled with random values with new random values.

All it takes to use `fill_array_*` functions is to add a `Float64` array of size `dsfmt_min_array_size` to `MersenneTwister` instances (which then allocate roughly twice as much), to be cyclically filled with random values (via `fill_array_*`), which allows `rand(r::MersenneTwister)` to pick those values one by one.

I guess the same speed differences could be observed for integer generation, but currently `MersenneTwister` RNGs generate only floats (I would be happy to enable this if #8380 or equivalent got merged, which the use of `dsfmt_fill_array_close1_open2` anticipates here).