PCG, A Family of Better Random Number Generators
pcg-random.org
pcg-random.org
https://www.youtube.com/watch?v=45Oet5qjlms
Its a bit long but I highly recommend it. I learned a lot about RNGs from it.
For those who didn’t bother poking around and are interested in random number generation and C++, the blog also great: http://www.pcg-random.org/blog/
He invented the XorShift method (2003), the LCG with good hyperplane behavior (1968), and the modern method of combining multiple poorly behaving RNGs (via function combination and output mapping) to create modern RNGs, not to mention the "diehard" tests he developed which are used to evaluate the performance of RNGs (1995).
This "PCG" algorithm, which is just xorshift(LCG), is just a typical implementation of his methods, which he even explicitly states in his papers.
Sadly Marsaglia home page with all his papers is no longer online, but they can be found scattered around the net.
Has this something to do with address space randomization?
"This paper is currently submitted to ACM Transactions on Mathematical Software, where it is currently under review. "
The biggest downside I ran into is that it requires 64 bit numbers even for the 32 bit RNG, which means its very simple code becomes more complex on a platform with only 32 bit numbers, or in a scripting language. Also, it's not a CSPRNG, if this matters to you.
This is minor though, and I would use it again. It's flexibility for seeding and easy serialization outweigh this IMO (and it's still simple compared to e.g. mtrand)
sudo apt-get install dieharder
http://www.phy.duke.edu/~rgb/General/dieharder.php
If you make a GSL interface for the RNG it will make using dieharder much easier
I'll try to find a more complete/better tested port, or try to do it myself.
I had been limited in selection on the random number generator reproducibility (so that each planet is only stored as the seed for the generator)
I'll have a try later on, it'd be interesting how a sampling of planets turn out from both rngs, if they are visually different - the rng is used both for features and for the perlin noise that generates cloud&land textures, so any artifact should come up easy in the textures
In their table, they acknowledge that Arc4Random and ChaCha20 as secure. The only negatives against ChaCha20 is that it's not 'fast enough' and k-Dimensional Equidistribution. In my experience it's never showed up in my profiling, so I feel it's fast enough; and I'm not sure why I want k-Dimensional Equidistribution.
So... I'll keeping using ChaCha20 when I need to (it's part of nacl/libsodium if you don't know where to get it from).
I used mt19937 for this and it worked ok. I suspect that using pcg might have shaved a few percentage points off the total run time of the program (maybe I should do a benchmark sometime). If so, not a huge win, but noticeable. Especially if you're doing renders on a larger scale than I was. A couple percentage points could trim a few computers from a render farm.
Your dismissal strikes me as both ignorant and rude.
One of the good features of ChaCha is that it is fast. A modern CPU can churn out Gbps of data. And in HW you can do it at low clock frequencies. This is the reason we use ChaCha as the CSPRNG in the Cryptech HSM.
Why not? It's perfectly valid to use a secure RNG for non-secure purposes.
As I mentioned, I've used ChaCha20 for those sort of purposes too. And the random number generation barely shows up as a fraction of the runtime.
i.e. improving 1% of the runtime by 99% isn't worth the overhead of having more than one random number generator.
It's much slower. Yes, in your application it was a fraction, but they are still much slower than non-secure RNG's.
This gives you both good quality random numbers during the simulation run yet lets others reproduce your results and expand with more results if required.
This is also the implementation used for the benchmark at the pcg-random.org homepage.
Btw, libsodium prefers salsa20 instead of chacha20, I don't know why; but I trust they made a good decision.
My SIMD implementation can be made to run a bit faster, but this would mean computing more blocks in parallel, and thus increase the state size of the RNG even more. I chose to only compute one block at a time. An optimized stream cipher implementation will have all the implementations with different parellel block sizes embedded, to achieve optimal speed for long messages.
---
ChaCha20 is a stronger more modern variation on Salsa20. But the differences are minor.
But, to be precise, libsodium prefers XSalsa20 to ChaCha20. The core feature about XSalsa20 is that it supports a 192-bit nonce instead of the 64-bit nonce of ChaCha20. This means that it is safe to use a randomly generated nonce, while randomly generating a 64-bit nonce would result in collisions eventually. I believe this is the reason they chose XSalsa20.
XSalsa20 is a simple variation on Salsa20 that does a bit more initialization to turn the normal 64-bit nonce into 192-bit. I assume the same construction can be applied to ChaCha20, but since djb (the author of both Salsa, XSalsa and ChaCha) hasn't done it, I think that libsodium went with the safe approach and just used XSalsa20.
Unless you're hurting for space---and in a Haswell machine you probably aren't---the case for using a cryptographic generator everywhere is strong. If you're hurting for space, or are on a less desktop-oriented architecture, you probably are not going to like 64-bit integer multiplications and variable rotation counts either.
By the way, you're using the aligned _mm_load_si128 and _mm_store_si128 intrinsics to load and store the block: https://gist.github.com/orlp/32f5d1b631ab092608b1#file-chach.... But there's no guarantee that block is aligned to 16 bytes, so that code may crash in some compiler/platform combination.
The drawback however, is that these implementation only get that fast because ChaCha is embarrassingly parallel. The fastest implementations can be computing 16-24 blocks in parallel efficiently with AVX2. That's 1.5kB of random data generated at once. And it's only this fast in a closed loop, where all code and memory is hot.
For the above reasons and simplicity I've chosen to not do a parallel SIMD implementation in my gist.
But I agree that 'fairly slow' is not really fair to say, at least not in combination with 'Good' statistical quality (rather than Excellent, because the author found faults in ChaCha2). ChaCha8 is blazing fast, and so far no cryptographer has been able to do a successful attack against it. However, before, ChaCha was mentioned as being 'slow', and I attempted to fix that by emailing the author with my implementation.
-
Interestingly, I was (sadly I never got to finish it before the http://competitions.cr.yp.to/caesar.html deadline) working on an AEAD design similar to ChaCha, that was doing 1.5 cpb authenticated encryption on AVX2: http://www.liacs.nl/~opeters/orlein.pdf. SIMD plus embarrassingly parallel ciphers is a strong combination.
-
Thanks for the warning about the alignment. Because I tacked on the SIMD implementation later, I forgot to add the alignment requirement, I did that now.
That is my point exactly. Why would you design, in this day and age, a generator that doesn't vectorize well? It will not take full advantage of the CPU. Even with parallel streams, large integer multiplication and variable-length rotation are SIMD-killers. Regarding the 1.5KB of data, I suspect you can get away with less than that if you specialize to this application, but note that this is still around half the state size of mt19937.
If you prefer, you can see the seed + stream as a combined 128 bit seed.
For the party tricks, of course! http://www.pcg-random.org/party-tricks.html