Modernize the PRNG used for rand() by using a Configure option#24105
Modernize the PRNG used for rand() by using a Configure option#24105scottchiefbaker wants to merge 2 commits intoPerl:bleadfrom
rand() by using a Configure option#24105Conversation
|
|
||
| typedef struct { uint64_t state; uint64_t inc; } pcg64_random_t; | ||
| // Global PRNG object | ||
| pcg64_random_t prng; |
There was a problem hiding this comment.
Yeah, this should probably live in the interpreter instead. And do something sensible on thread cloning so different threads don't get the same results.
9c6eb8c to
8b56090
Compare
8b56090 to
bb9d9b5
Compare
40d4a6d to
1b78937
Compare
9002fb7 to
b0c2c62
Compare
rand() by add a Configure optionrand() by adding a Configure option
rand() by adding a Configure optionrand() by using a Configure option
b0c2c62 to
de7f507
Compare
| const uint64_t word = ((prng.state >> ((prng.state >> 59) + 5)) ^ prng.state) * 12605985483714917081ull; | ||
| prng.state = prng.state * 6364136223846793005ull + prng.inc; |
There was a problem hiding this comment.
Are these fairly arbitrary numbers, or did they get created by some specific process? Either way, I'd like to see some sort of comment explaining why these numbers in particular.
There was a problem hiding this comment.
That algorithm was designed by people WAY smarter than me. Per a previous iteration of this PR I added notes in prng.h with links to various documents talking about PCG64 and how to choose a good PRNG:
// Notes:
// https://zephyrtronium.github.io/articles/randomness.html
// https://docs.oracle.com/en/java/javase/21/core/choosing-prng-algorithm.html
// https://github.com/alvoskov/SmokeRand
TLDR; PCG64 has been tested and vetted by people smarter than me.
| // Splitmix64 is defined in util.c | ||
| static U64 splitmix64(U64 *state); | ||
|
|
||
| typedef struct { uint64_t state; uint64_t inc; } pcg64_random_t; |
There was a problem hiding this comment.
I suspect this should be U64 instead of uint64_t
Per past discussion on p5p we know the
drand48we use as a PRNG has limitations. This PR attempts to cleanly upgrade the PRNG used forrand()calls, while leaving the existing drand48 code in place for internal Perl stuff (hash seed, etc). I foundrandfuncandseedfuncoptions in Configure that allow us to point at a new PRNG without affecting the existing code.I created a new
prng.hfile which is largely self-contained except for a couple of additions toembed.fncandConfigure. I have included two new PRNG implementations: PCG64 (my preference)and xoroshiro128** as options.Completed items
srand()functionality works as expectedrand()outputs the full 53 bit state capable from a double (drand48 could only do 48 bits)./perl -I lib -E 'for (1..5) { printf("%064b\n", rand() * 2**64-1); }'TODO
prng.hdoes not seem to be rebuilt consistently after changes. Do I need to add this new file to build system?make regenputs the functions prototypes in a weird location "Used in locale.c and perl.c"rand64()?Alternate options
rand()is "good enough"Random::Simpleis a drop-in replacement forrand()andsrand()already