Open bakkot opened 1 year ago
I haven't walked thru your references yet, but this seems like incredibly useful research. Thank you so much!
Go math/rand/v2 (https://pkg.go.dev/math/rand/v2) ended up settling with ChaCha8 as the default; it still has PCG as an option. https://github.com/golang/go/issues/61716 is the discussion, I believe. The argument is that it makes misuse-as-cryptographic-randomness less of a big arrow in the knee; I doubt that applies here given we are outputting a number
.
(Although getting not just [0,1) numbers out of the bag seems useful too: maybe someone wants a well-implemented dice roll. Tangentials, tangentials...)
There's a variety of modern PRNG algorithms we could choose from, with various tradeoffs around speed, memory, predictability, complexity, miscellaneous statistical properties, and also amenability to other things you might want to do like jumping ahead.
I think the main reasonable candidates are ChaCha, PCG or a variant, and Xoshiro/Xoroshiro. Honorable mention to sfc64 and SplitMix64. Wyrand looks interesting but I think it's too new to be the default choice. Dishonorable mention to Mersenne twisters, which require an excessive amount of state with basically no compensating advantages.
Note that Xoshiro/Xoroshiro is an entire family of PRNGs, so we'd have to choose among them; some of the older ones have (what I regard as) notable weaknesses.
Of these I'd lean towards ChaCha, specifically ChaCha12 (or 8, as Go has done), which is fast enough for almost all practical purposes, has good statistical properties, is extremely difficult to predict (just as much as ChaCha20, but faster), and as a bonus supports jump-ahead (which is only relevant if we expose that capability, which we probably won't). Detailed thoughts below.
I regard being able to generate ~hundreds of megabytes per second on old hardware is probably sufficient, so among algorithms which can achieve that I'm inclined to choose based on other attributes rather than continuing to worry about performance. All mentioned algorithms are capable of that. ChaCha is the slowest, being at least an order of magnitude slower than the others.
Then the most important attribute I'd look for is being statistically well-distributed.
Beyond that I'd optimize for being at least somewhat difficult to predict. People probably shouldn't be using seeded RNGs for cryptography, but it's still a useful property in non-cryptographic applications (e.g. games).
Other bits of context you may find helpful:
is considering adopting PCG as the default in Go 2Edit: ultimately went with ChaCha8 (instead of their ancient plan-9 derived thing); see discussion here and to a lesser extent here