-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
faster rand(::MersenneTwister, UnitRange{<:BitInteger}) (fix #22600) #22612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Sorry, I'm really not qualified to comment on the RNG code. |
Would this function also benefit from using the new method for
Or perhaps a new RangeGenerator appropriate for new method? |
According to my preliminary testings, mostly, but with less speed-up and even a slow-down in some cases, e.g. for the range |
Perhaps @simonbyrne can also take a look. |
Probably we get only one shot at changing this so I think it is worthwhile to think a bit about the problem space. Basically we have to keep track of three sources of cost:
in your approach all costs are source 2, previously dominant costs are 1. and 3 and this might well be the right solution. On this machine, costs for There is not much what can be done about 3, but (on this machine) it is also only 1/4 of the sampling costs, so worthwhile to do if it decreases the number of rejections by a factor.
I have a "proof of concept" implemenation here https://gist.github.com/mschauer/d6a7a091bada2a828e1ac74e7baa106b It defines an iterator which counts downwards from So in praxis one might divide |
If this is PR/master, doesn't this show that master is faster than your PR?
|
What do you mean?
Very interesting! I will take time to read your proof of concept, and compare efficiency. That said, I guess the simplicity of this PR may be preferable for the general case.
My mistake, thanks for reporting (editing OP). |
There are some reasons not to change the random number generator too liberally, because old versions (at least say from julia 1.0 onwards) should be available for reproducibility of numerical experiments. R still has a normal variate generator called "Buggy Kinderman-Ramage" (kept for reproducibility...) |
I was vaguely thinking of this reason, but didn't remember having seen this stated clearly in the forums. Do you think the generators could be changed (i.e. the reproducibility broken) between 1.0 and 2.0 ? |
I would really like for RNG to be explicitly set when |
@StefanKarpinski I'm afraid I don't understand your concern here: in which case code will be broken? |
What I was trying to explain (poorly) is that if everything one needs to know about how random values are generated is specified when seeding the RNG, then we're free to change anything we want. In this case, we could have one RNG type for using resampling and one RNG type for using a pre-computed generator. This not only allows the user to decide what they want based on their use case, but also means that if we change the default in the future, user code won't break since it will keep using whatever they chose when they seed their RNG. |
I think I understand a bit better (this also relates to point 3. of #17918 (comment)), but not fully yet. But by "breaking code", do you mean that the stream of random numbers is modified when we change the implementation (i.e. non-reproducibility) ? Would you like to prevent the use of |
I feel incline to merge this soon, as that's the best we have for now, while still exploring @mschauer idea. |
are there benchmarks that would track this? @nanosoldier |
under review, see JuliaCI/BaseBenchmarks.jl#82. |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan |
@nanosoldier |
Your benchmark job has completed - no performance regressions were detected. A full report can be found here. cc @ararslan |
14a6e6e
to
07b4eac
Compare
This is a solution simirar to #14772: generation with
MersenneTwister
is fast, so it's cheaper to waste entropy bits rather than using divisions to save those bits as much as we can (it may have been different whenMersenneTwister
couldn't use the fast SIMD-optimized array functions).I intend to extend this work (when applicable) before the next release, but this first step will probably be the most visible.
Few timings I get (using in fact
@btime
from BenchmarkTools, andm
being aMersenneTwister
object), showing master/PR, or master/randi
/PR when applicable (usingrandi
from StatsBase):Basically, with the rejection sampling in this PR, when the lenght of the interval is a bit above a power of 2, then about 1 sample over two is rejected, which explains the change of performances around a power of 2. Also, this takes advantage of the fact that
MersenneTwister
nativily generates 52 bits of entropy, hence a change in performances after lengths of 2^52 and 2^104.