Closed define-private-public closed 9 months ago
Hi, thanks for your interest in OpenRAND.
Can you please tell me what particular compatibility you're looking for? I'll be happy to add anything that's reasonably possible. Regarding you particular examples:
OpenRAND generators does support standard cpp random number distributors. Here's a code snippet:
// Initialize RNG with seed and counter
RNG rng(1, 0);
// use std distribution functions with RNG
std::lognormal_distribution<double> dist(0.0, 1.0);
double x = dist(rng);
My understanding is that seed_seq
serves two purposes: inititiazling a single generator that has huge state- not relevant for OpenRAND since it uses only 96 bits, a 64-bit seed and 32-bit counter. The other, perhaps more common use is it provides a set of good initial seeds for multiple generators so they don't produce dependent/correlated streams (e.g. for multithreaded applications). A key feature of OpenRAND is that it doesn't need to have a set of seeds with special properties to produce independent streams, any set of seeds will produce good quality data so long the seeds are unique. You can just use RNG rng(omp_get_thread_num(), 0)
to initialize local rng in a thread for example.
By the way your project looks nice. I forked the GPU accelerated version of that same code with a previous iteration of OpenRAND: it's here
In my code, I was trying to see if I could plug in openrand::Phillox
there. And well, it didn't compile (which was kinda expected). I was hoping to make minimal changes to my RandomGenerator
object to try out OpenRand. std::mt19937
and pcg32
can work interchangeably.
My project is meant to operate a bit differently from the original "Ray Tracing in One Weekend" code. It has a similar architecture and outputs (and being CPU bound only). But it's goal was to see how far one could push standard vanilla C++ (or not requiring hefty 3rd party libraries); mostly by rewriting code. If OpenRAND is more performant than PCG32 I'd love to swap it out at the RNG for the project.
I was looking at PCG32 code, here is a minimal implementation from the author:
typedef struct { uint64_t state; uint64_t inc; } pcg32_random_t;
uint32_t pcg32_random_r(pcg32_random_t* rng)
{
uint64_t oldstate = rng->state;
// Advance internal state
rng->state = oldstate * 6364136223846793005ULL + (rng->inc|1);
// Calculate output function (XSH RR), uses old state for max ILP
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
uint32_t rot = oldstate >> 59u;
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
No loops (or rounds); there is a 64 bit multiply, but other than that it's mostly extremely efficient bit operations. In terms of speed, I do not believe it's possible for any OpenRAND generator to beat this.
I had considered including the PCG to OpenRAND. But at the author herself notes, it can not consistently produce statistically independent streams for any set of unique seeds. That's a very valuable property to have, it allows users to seamlessly use application variables to instantiate generators without going through a seperate seed generation step.
So in a nutshell, you don't think that OpenRAND could beat PCG32 in performance? That's mainly what I'm looking for.
Thank you for your investigation on this. I really appreciate it in try to squeeze more throughput of out my project.
Hi. This is a very nice project here. I have an open source RayTracing project. It can act as a way of benchmarking certain C++ features and libraries.
For example, I swapped out the standard Mersenne Twister engine (
std::mt19937
) with PCG32 and saw both better performance and nicer random.I wanted to try out OpenRAND to see if it might be more performant than PCG32. But when I tried to plug it in I noticed that its API differs from C++'s built in interface . Including things like
std::seed_seq
or the random number distrubtors.Having OpenRAND work with C++'s existing framework would be very beneficial IMO.