skeeto/scratch

splitxix33 fails PractRand consistently

Opened this issue · 9 comments

Hi!

Doing some quick tests with splitxix33 and PractRand.
For 21 out of 21 different seeds I get failures, always with Gap-A or Gap-B, on average after 180 GB tested (failure at 128GB at the earliest and 256GB at the latest).
It consistently fails one of my own tests too, but PractRand fails splitxix33 more quickly.

Neat idea, having an implementation trivial to memorize but these constants don't quite work.

SplitMix64 does not have this behaviour.

With PractRand pre0.95 and a zero seed, I believe I had tested up to 8TiB — my usual stopping point — without anomalies. A quick run now to 128GiB just now definitely has no anomalies.

int main(void)
{
    uint64_t s = 0;
    uint64_t buf[1<<12];
    for (;;) {
        for (int i = 0; i < 1<<12; i++) {
            buf[i] = splitxix33(&s);
        }
        if (!fwrite(buf, sizeof(buf), 1, stdout)) {
            return 1;
        }
    }
}

How I ran this:

$ cc -O3 test.c
$ ./a.out | RNG_test stdin64

See how it fares with RNG_test stdin64 -tf 2 (my standard setting)?

I also ran a quick test with the shifts set to 32 instead of 33, pretty much the same result (min fail at 128G, max at 256G, mean 182GB with 21 seeds).

Running tests with other easy to remember multipliers now, not as easy as 1111111111111111111
but OTOH I think the prime-property is quite useless here. A few years ago I was looking for good (not necessarily easy to remember) constants. I did find some useful constants but couldn't spot any particular pattern.

As long as the multiplicative constant is odd, has reasonable Hamming weight in nybbles, bytes, 16-bit, 32-bit and 64-bit words, that should suffice.

With the constant 17317317317317317317 (prime), 10 out of 10 tests with PractRand -tf 2 have failed but all of them at 1TB. I'll look at some more constants that are easy to remember but not necessarily prime.

Running tests overnight now; for M = 1111111111111111111, shifts 28 and 29 have passed 1TB without any anomalies found (30 failed at 1TB).
I just might be on to a sensible metric for multiplicative/shift constant pairs but too early to say.

By tomorrow I should have some more results.

So far, shifting with 28 or 29 looks much better than 33:

==> split-1111111111111111111-28-practrand.txt <==
rng=RNG_stdin64, seed=unknown
length= 8 terabytes (2^43 bytes), time= 33580 seconds
  no anomalies in 1081 test result(s)


==> split-1111111111111111111-29-practrand.txt <==
rng=RNG_stdin64, seed=unknown
length= 8 terabytes (2^43 bytes), time= 33611 seconds
  no anomalies in 1081 test result(s)

I will continue to run these (with different seeds) through PractRand and report any progress here.

Running more tests now. From the merit scores I get from running RRC-64 (improved version), 33 seems to be one of the least desirable shifts:

Mean number of tests before failure, higher is better.
24 15.01425390625
25 14.91104296875
26 14.99709375
27 14.68859375
28 13.9673359375
29 13.41816796875
30 13.11098046875
31 12.40925390625
32 12.22753515625
33 12.1771171875

Alas, I'm out of cores but my machine is currently happily munching data with S = 27, 28, 29.

S = {27, 28, 29} just passed 32TB of PractRand -tf 2. I'll let it keep running though a screening test (RRC-64) indicates that S = 26 would be a better shift.

A full screening test with RRC-64 give the following scores (= average exponent when failing, higher is better). Note that these failures are not from PractRand but from a much faster [and in some cases stronger] test, yet to be published):

  • moremur 16.8766494140624
  • splitxix-26 15.6561492187499
  • splitxix-27 15.1493624999999
  • splitxix-25 15.0837752545026
  • splitxix-24 14.6506789062499
  • splitxix-28 14.3580085937499
  • splitxix-29 13.05266484375
  • variant13 12.70163671875
  • splitxix-30 11.0644289062499
  • splitxix-31 10.4414421875
  • splitxix-34 10.4246455078125
  • splitxix-33 10.2477294921875
  • splitxix-32 10.087998046875
  • murmur3 9.064263671875
  • lea64 9.57194238281248
  • degski64 9.38765820312499

S = {27, 28, 29} just passed 128TB of PractRand -tf 2.

S = {27, 28, 29} just passed 256TB of PractRand -tf 2.

I won't be testing any further. S = 26 might be even better but my machines are busy with other tests.