Repository navigation
Move PRNG algorithms out of Rand #431
Description
Edit by dhardy: adding a tracker for the planned tasks:
- Replace
SmallRngalgorithm (see Requirements for a small fast RNG dhardy/rand#60 and Shootout: small, fast PRNGs dhardy/rand#52) - Deprecate
XorshiftRng(required: that the RNG is available in another crate) - Move ISAAC* to new crate
- Publish PCG RNGs somewhere (
rand_rngs,rand_pcgor something) - Publish SFC generators somewhere
- Review xoshiro crate by @vks
- Review state of other published RNGs (see linked comment) and fix up if useful
- Document available RNGs (internal and external crates)
Also: we should consider whether we want to rename PRNGs when moving or adding them.
As decided in dhardy#58.
The idea is to only keep the StdRng and SmallRng wrappers in Rand, and to not expose PRNG algorithms directly.
The field of PRNG algorithms is not static, it seems like a good idea to cut Rand partly loose from the developements to improve our backward-compatability and usability story. Advantages (from the original issue)
randprovide easy to reason generator(s) to satisfy the bulk of the usersrandprovides low-friction upgrades and keeps the optimal-ish algorithms readily availablerandwill not accumulate and/or deprecate specific algorithms throughout time- Specific
randRng names won't bleed out to the world, like in forum posts, stackoverflow, etc..
Instead we want to provide an official companion crate, rand_rngs, with a couple of blessed implementations.
Whether Rand should depend on rand_rngs or copy the two algorithms used by StdRng and SmallRng is not fully decided. It might reduce code size if a crate depends on both StdRng and its algorithm (currently Hc128Rng) directly, but that seems rare and not worth much. It has the disadvantage that both implementations should remain in sync. Maybe the CI can check this?
If Rand depends on rand_rngs, it would restrict rand_rngs to only depend on rand_core. But that is what rand_core is for. I am for having Rand depend on rand_rngs.
rand_rngs
rand_rngs should provide a good selection of PRNGs.
Including multiple PRNGs in one crate has the advantage of having a single place to provide guidance, as it helps comparing different algorithms with each other. Also it gives one place to offer consistent benchmarks, to run PRNG test suites, to keep up a common quality level, and possibly to develop functionality that is useful for more than one PRNG (e.g. jumping).
Which PRNGs to include has been the topic of endless discussions. A few are basically decided. I fully expect the number of PRNGs to grow over time. But we also should be careful not to expose too many, as there are hundreds. Every PRNG should have one thing that gives it a clear advantage over others, otherwise it is not worth the inclusion.
Normal PRNGs
dhardy#60 explored normal PRNGs. The following 5 I feel comfortable about for an initial version of rand_rngs:
- PCG-XSH-RR 64/32 (LCG)
- PCG-XSL-RR 128/64 (MCG)
- SFC (32-bit variant)
- SFC (64-bit variant)
- Xoroshiro128+
The two PCG variants offer good quality and reasonable performance. SFC provides high performance and a chaotic PRNG (not a fixed period). Xoroshiro128+ has acceptable quality but high performance.
An PRNG put together by me, XoroshiroMT, is also good quality and sits between PCG and Xoroshiro128+ qua performance. But now that there is just a new Xoshiro PRNG, it may be worth evaluating that one first, as it is said to also be good quality.
CSPRNGs
For CSPRNGs we currently have two good implementations in Rand
- ChaCha20
- HC-128
ChaCha20 offers reasonably good performance and uses little memory, while HC-128 brings high performance at the cost of using much memory.
I would also like to see some implementation of AES-CTR DRBG eventually, as it is commonly used, and has hardware support on modern desktop processors.
Other / deprecated PRNGs
We currently have the ISAAC, ISAAC-64 and Xorshift128/32 PRNGs in rand. They have no real advantages over the PRNGs metioned before. It is better to use HC-128 instead of ISAAC, and Xoroshiro128+ or PCG instead of Xorshift. We can include them in something like a deprecated module, but I propose to move them to stand-alone crates outside the Rand repository.
Steps to take
- move the
prngsmodule to a seperaterand_rngscrate in the Rand repository, similar torand_core. - move
generatorsbenchmarks over. - lift PRNG implementations from https://github.com/pitdicker/small-rngs (I have updated it to master a while ago, but still have to push the changes)
- lift Xoroshiro128+ from https://github.com/vks/xoroshiro/
Does this sound about right?
Activity
vks commentedon May 6, 2018
pitdicker commentedon May 6, 2018
See the first post and the linked issue.
dhardy commentedon May 6, 2018
I actually see no reason that we shouldn't have one crate per RNG (or perhaps family of RNGs), but I think it's worth having these in the Rand repo and the crates owned by the Rand team (currently me and the libs team). Or we could try organising more and have a
rust-randproject and set of repositories on GH maybe.TheIronBorn commentedon May 6, 2018
Both the new xoshiro and xoroshiro** variants I think are worth consideration.
Vigna claims xoroshiro256** has a higher degree polynomial than PCG 128 variants https://www.reddit.com/r/programming/comments/8gx2d3/new_line_of_fast_prngs_released_by_the_author_of/dygkkng/, so xoshiro variants are probably even stronger.
Edit: poor wording
burdges commentedon May 6, 2018
Is the separate repository is merely a transitional detail? It improves code size if any code that gets used actually gets exposed somewhere, even if only in another crate. It would improve tests if all this lives in the rand repository, right?
dhardy commentedon May 7, 2018
@TheIronBorn this issue isn't about what algorithms we include, it's just about organisation and presentation.
dhardy commentedon May 7, 2018
@burdges I'm not sure what you mean about transitional; no. The easiest option is I think just to have sub-projects in this repo (like
rand_core).I'm not even sure if it does help with testing having everything in the same repo; in one way it makes it worse since CI must run all unit-tests on any change (although with API-breaking changes this may be necessary).
Once we have stable core APIs it may make more sense to use separate repos since most changes (docs, new features, tweaks to other features) will not affect other crates. I.e. once
rand_coreis stable then changes to things like the distribution code will have no effect on the RNG implementations, so separate repos do make some sense.pitdicker commentedon May 7, 2018
In this issue and the previous one I have given arguments that it would really benefit users to have one crate, as it helps comparing and contrasting them. And real but smaller benefits for us. Are those reasons wrong?
Maybe it is good to also collect the reasons multiple crates can be a good idea.
Two related thoughts:
rand_*crate.The unit tests we have now for PRNGs run in a fraction of a second, easily a 100 times less than the set-up time for Travis.
vks commentedon May 7, 2018
dhardy commentedon May 16, 2018
So sounds like
rand_coreis)prngmodule should moveranddepend on whichever crates are necessary for theStdRngandSmallRngalgorithmsHow many crates do we want? Only 1-3 (e.g. crypto, non-crypto and deprecated)? One crate per family of RNGs? One crate per RNG?
@newpavlov do you have anything to say about the many-small-crates design of RustCrypto's hashes (and other projects)?
newpavlov commentedon May 16, 2018
In my opinion small crates work pretty well (but not too small, i.e. crates for family of algorithms, not for each variation), yes there is some headache with coordinated upgrades to the new trait version, but if
rand_corewill be relatively stable, I don't think it will be a big problem.cargo test --allandcargo bench --allmore or less solve this problem. There is an issue with features when you work with virtual manifest, but I don't think that RNG crates will suffer from it.RustCrpyto partially solves this problem by having feature gated
devmodule in trait crates, which define functions and macros to make it easier to write tests and benchmarks. Though I am not sure if RNG crates should follow this approach.I would like suggest to move
CryptoRngcrates to the RustCrypto/CSRNGs repo. (of course with full access granted to @dhardy and lang team) Pros:randcrate, e.g.rdrand(@nagisa gave his consent) andaesrngdeveloped by @vksCon is of course is the split of RNG crates between two organizations.
dhardy commentedon May 16, 2018
Actually we already stopped using
--allfor most tests because of this issue. It's a shame it's not been solved.burdges commentedon May 16, 2018
It'd be nice to save code size by using stream cipher code for CSPRNGs of course, but not that pressing. At first blush, I kinda think moving CSPRNG crates into another project, especially one less blessed by Mozilla, sounds premature and distracting. At minimum, all the BlockRng business will make reading the code annoying.
22 remaining items
TheIronBorn commentedon Jul 13, 2018
Note:
xorshift4096*also exists. Probably impractical but it's curious. (not sure why it's no longer listed)dhardy commentedon Jul 14, 2018
Well, I'll try again: @astocko are you interested in maintaining your Xorshift crate?
But given the lack of commits in the last year it seems unlikely. The code is CC0 so it may be sensible at this point to pull out what we want and make a new
rand_xorshiftcrate.@vks what do you think should be the divide between Xorshift, Xoroshiro and Xoshiro generators, since you already have the latter two in your crate?
iddm commentedon Jul 14, 2018
I see you mentioned me here as an author of randomorg crate. I am the one and I just wanted to remind you that this crate unfortunately is not going to have
Rngtraits implementations due to its nature of remote data source.vks commentedon Jul 14, 2018
dhardy commentedon Jul 14, 2018
We could just throw it all under
rand_vigna, but a separate crate for Xorshift is also fine. His recommendations have changed over time, so putting this years' recommendations undervigna2018doesn't seem sensible for what we hope will become a stable crate.vks commentedon Jul 14, 2018
Well, stability is why I decided to create a new crate, so the old one can still be used for reproducibility. One of the advantages of moving the algorithms out of Rand it that we can just add and drop crates from the recommendations without breaking anyone's code.
afnanenayet commentedon Jul 14, 2018
Hey, author of the Pcg32 crate here. The other PcgRand crate seems much more full-fledged than mine, but I'd be happy to continue maintaining Pcg32.
I personally would advocate for some sort of vetting/benchmarking with the rand crates. Even something like dieharder scores would be nice to see.
TheIronBorn commentedon Jul 14, 2018
We currently have quality comparisons here: https://docs.rs/rand/0.5.4/rand/prng/index.html#basic-pseudo-random-number-generators-prngs
I don't know if we've thought about listing actual test data though (probably TestU01 or PractRand if anything)
dhardy commentedon Jul 31, 2018
@droundy if you're still interested, we'd accept Xorshift1024 in the new
rand_xorshiftsub-crate (see #557).dhardy commentedon Jul 31, 2018
@pitdicker I think it's time to turn your
small-rngsrepo into a real crate 😄As you say, it is more useful having a small crate with a few high-quality PRNGs than to have a huge collection, so how about we create
rand_small_rngswith the following guide-lines:Potentially we can add a separate
rand_rngssub-project for comparison purposes (benchmarks, quality testing). These should be separate: the former is a small collection of high-quality RNGs not hosted elsewhere (and should remain small); the latter is a comparison across many RNGs (and could host thegenerators.rsbenchmarks later).droundy commentedon Jul 31, 2018
I've just gone ahead and implements a xoroshiro256+ in my own code, which ended up seeming simplest, after I decided that compatibility with my old C code didn't matter. Maybe I'll use a "standard" xoroshiro implementation at some later point, but for now it seemed easiest to just translate the C code myself. That way I didn't have to mess with serde feature flags, and I could easily get proper seeding with a u64 as recommended by Vigna.
peteroupc commentedon Aug 22, 2018
If it helps you decide which PRNGs to include where, I have written an article on random number generators and categorized "good" RNGs into two categories. Essentially:
Any RNG other than a cryptographic or statistical RNG, as defined in my article, should be considered low-quality, I think.
afnanenayet commentedon Aug 22, 2018
I updated my pcg crate to implement the
RngCore/Rngtraits