Better, cheaper, more abundant random numbers
economist.com
economist.com
I have a hard time understanding how this is a problem. Using uniform random numbers to choose the x-axis value on a graph of an integrated probability distribution function and mapping it to the y-axis is pretty garsh darn simple and normal. This is the crux of monte carlo methods and is stupidly fast these days.
What are they talking about?
So choose one at random for each sample :)
As is the case with most implementations of things, even elementary things, that have to do with the real numbers on discrete hardware (see numerical integration, square roots and inverses, trig functions, various approximations of the real numbers themselves, etc.).
Real numbers are hard. It's a blessing only a minority of computer programs need to actually deal with them (or their approximations).
Just doing simple things like choosing a uniformly distributed random point in a disk or on the surface of a sphere are awkward enough to do efficiently; choosing a bunch of random points drawn from the London temperature/pressure/rainfall distribution for December is much worse. I wonder if that might be part of the complexity that is being elided to bring this article to a popular-science-reader level?
Sampling vectors from multidimensional random distributions is a well studied problem. For example the open source project https://mc-stan.org implemented several (at the time) state of the art methods like Hamiltonian Monte Carlo with the help of Automatic Differentiation.
Knowing temperature PDFs is similarly easy, and so is sampling them.
I will have to go read some literature on this cointoss business I think.
For the normal distribution, you can use a bisection on the math.h erf() function to invert it. This is expensive, but you're only going to do it to make your lookup table once. Build that table to reasonably fit in your cache, and then use your uniform pseudo random integers to peak into that table.
As I mentioned above, you can interpolate between values in the table if you need more resolution. There are other tricks for specific distributions, but the technique is very general.
Greying or mixing or whatever of pseudorandom or actual "trng" like static or radiation discharges is pretty well known. I.e. take some source of randomness for 10000 bits, xor with each other, and use that to seed a cryptographically secure generator, topping up the seed as more bits become available, is pretty much the gold standard for "I need 50gbit bitstream of 'random'"
The other part seems to be the binning/bucketing/curve fitting, or "massaging" the output of that to only gives numbers in the range under scrutiny, which sounds like an implementation detail to me, rather than something that you can configure at ... Runtime? Compile time?
I'm sure there are real HRNG (or sensors for TRNG) that can approach ludicrous bitrates, I've never had the luxury of one, and I'm not entirely sure I could be convinced the output was any "better" than a vetted arrangement from my second paragraph.
All of this is to say: okay but we already do that and massaging randomness to give us results we want is what all this modeling stuff ... is, so other than some off in the weeds magnetic film manipulation, I'm assuming that's modelled, too. It's just models all the way down?
Sometimes, you even discard numbers so different simulation runs with different parameters consume the same amount of numbers. A simplistic example:
if rand()<.5 :
doSomethingWithRand(rand())
else:
doSomethingWithoutRand()
rand()Do not try to cook your moderate entropy data source. You can end up cooking what little entropy it had out of it.
Many CSPRNGs allow seeds of arbitrary size. Just push all of your sketchy data into it, and let the hash function handle scavenging the entropy for you.
Completely off-topic: do you live alone in the forest, or with others?
With others.
If you do not mind me asking: is it a community? I swear I have been wanting to live in a community such as Twin Oaks Community but I am in Europe! :(
I'm pretty sure the project is looking at physical devices to add to the entropy pool, and they talked about two examples (which do seem pretty neat).
> One relies on the patterns magnetic films make when disturbed, the other on how electrons travel through the barrier of a quantum-tunnelling diode. Both of these things are truly random.
The use of the Von Neumann quote, "Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin” is pretty annoying, given that he said it in defense of his PRNG. Sort of a tongue-in-cheek "yes this is fundamentally wrong (sinful) but I'm going to do it" sort of thing.
What happened to the good old days of taking a picture of a lava lamp and using that as your random number until you take another picture?
[1] https://partofthething.com/thoughts/making-true-random-numbe...
Other than having to keep the secret app id actually secret.
Massaging the bits into proper form: using modulus operator, requires like 80-cycles (aka: a division) on 5-year old CPUs and maybe 20-cycles on a very modern core (with the past 3 years, as Intel seems to have put a lot of work optimizing division). So the bulk of the time is on this massaging process actually.
--------
Even if the bulk of the CPU time is spent converting the uniformly random bits into usable integers (division / modulus is really slow!!), or usable floats / normal distributions or whatever... I still expect the typical core to handle 100-million pseudo random numbers per second... __per core__.
Seeding your PRNG with a true random seed every now and then will ensure large-scale randomness.
I think cryptographers might need something higher quality, but key-generation is quite uncommon, so you wouldn't need to be doing millions-and-millions of keygens per second, would you?
Simultaions need lots of random numbers, but those random numbers don't need to have entropy guarantees, but instead have weirder requirements (not only speed of generation, but also the ability to rerun your simulation... you actually want deterministic random-number-generators for simulations to verify your results). So in these cases, PRNGs are not only needed, but superior to a true RNG.
There's also the weird case of quasi-random, a term I learned from the graphics community. You want your rays to be random-ish, but actually "more uniform" than actually random. Its a more pleasant randomish pattern to look at, leading to pleasant and artistic images (https://en.wikipedia.org/wiki/Halton_sequence). Quasi-random raytracing is a so called "Biased" generator, because the physical light models are probably closer to true random. However, quasi-random sequences lead to far less noise in far less time / samples, so they're more useful in practice.
--------
Ultimately, our x86 CPUs today have "true" RNGs built into the RDSEED instruction, pulling entropy from some kind of physical circuit that's highly sensitive to temperature conditions (thermal quantum noise generators inside of circuits. After all, heat is quantumly random as your electrons jump between states in the very small scale).
It's not uncommon to instead treat the RNG data as a floating point number between 0 and 1 and multiply it by the modulus (adding or subtracting 1 as appropriate depending on whether you want, say, 0-20 or 1-20 as the output). So that's a float multiplication, an addition, and a conversion to integer. Still probably cheaper than 80 cycles.
But we're also burning 32bits of data to get 4.4 bits of output. When randomness was more expensive than CPU cycles they would throw a Linear Congruence Generator on top, which is a function can transform an input and achieve similar levels of entropy in the output. It might take 5 bits or 8 bits of data instead of 32, at least quadrupling the utility of your source. But that's mostly for historical purposes. As you say, the ratio of CPU to random decisions has shifted many orders of magnitude in the last 20 years.
https://lemire.me/blog/2019/06/06/nearly-divisionless-random...
The 64x64 bit multiplier outputs a 128-bit output in ARM and x86. You see the 64-bit number as a fixed-point integer between 0 and 1 (that is to say: 0xFFFFFFFF as a 32-bit number is .9999999...). Multiply by the 64-bit version, bit-shift the result down and bam, you've got a high-speed, low-bias result.
-----
So you can see the 64-bit number is a number between 0 and .999999...., that number is multiplied with "6" or whatever you care about (assuming you want to make a dice roll from 0 to 5), and the results are in the top 64-bits of the 128-bit number the multiplier circuit created.
Getting you slightly less bias, and losing the unnecessary int->float and float->int conversion.
-----
A bit of the cutting edge, but I gave it a few experiments and it clearly worked. I was working on an SIMD-version of this technique a couple of years back and it definitely works.
You can also SIMD-ify the integer->float conversion with some smart AND / OR instructions. (See the "toFloats" routine here: https://github.com/dragontamer/AESRand/blob/master/AESRand_P...)
Oh right, and you can also use the AES circuits to make random numbers, but that actually was really difficult for me to figure out just right (!!!). AES round function is surprisingly bad at shuffling bits around, but with enough effort I got something working (passes 8TB+ of PractRand tests and other statistical tests)
I will say that random numbers as a service is a viable business opportunity. And I have heard that micro QRNG chips are being put into new phones.
I'm a bit of an rng nerd
How do you compete with the free CSPRNGs provided by the operating system?
Disclaimer: not a cryptographer. This is not cryptography advice.
Edit: cryptography