in reply to Re^10: PDL and srand puzzle
in thread PDL and srand puzzle

No. It may indicate PDL's random() is being seeded incorrectly.

PDL's RNG is at https://github.com/PDLPorters/pdl/blob/master/Basic/Primitive/xoshiro256plus.c, and generates 64(!) bits of randomness, of which only 53 are used in an IEEE 754 double-precision number. See the comments in that file for limitations, including that the lowest 3 bits can fail linearity testing, which is not likely to be a problem. Note it generates n (a parameter) seeds, not necessarily just one, so independent POSIX threads will have different seeds if PDL's built-in POSIX threading is used to generate large amounts of random numbers.

PDL's srandom function, if not given an input, uses PDL::Core::seed - see https://github.com/PDLPorters/pdl/pull/352.

There is no interaction with Perl's srand() or rand() functionality.

EDIT - I have just realised that Perl's "threads" functionality might clash with this, if it uses POSIX threads: PDL's RNG has a global vector of n seeds, in a global C variable. PDL's code will, if it is being used in what it thinks is single-threaded mode, use the 0th offset in that. If multiple POSIX threads are accessing that single seed (which gets updated on each RNG generation), there will be a race condition, hence less uniqueness. The workaround for that would be to generate the random numbers in the main thread first, possibly using PDL's multithreading if there are >1e6 elements in the ndarray, then use those suitably divided in the Perl threads.

Replies are listed 'Best First'.
Re^12: PDL and srand puzzle
by syphilis (Archbishop) on Jun 10, 2024 at 09:05 UTC
    PDL's RNG is at https://github.com/PDLPorters/pdl/blob/master/Basic/Primitive/xoshiro256plus.c, and generates 64(!) bits of randomness, of which only 53 are used in an IEEE 754 double-precision number.

    How does one retrieve (from the PDL object that random() returns) that actual double-precision random value as an NV ?
    BTW, I initially read "64(!) bits of randomness" as "64! bits of randomness" ... and was very impressed ;-)

    Cheers,
    Rob
      To get a single SV out of an ndarray, use $pdl->at($offset1, ...). That SV will have the appropriate numerical info available, be it NV, IV or UV.

      By the way, this is as you have marioroy has been doing with some of your test scripts, including looping over large ndarrays one element at a time. That made those scripts go impressively slower with PDL than the other versions. PDL has a function to output ndarrays in text column format: https://metacpan.org/pod/PDL::IO::Misc#wcols.

        To get a single SV out of an ndarray, use $pdl->at($offset1, ...)

        Thanks - that's what I was looking for.

        By the way, this is as marioroy has been doing with some of your test scripts


        The only thing I noticed was marioroy's use of $pdl->at.(0) which returned a 15-significant-decimal-digit representation of the value - not what I was looking for:
        C:\>perl -MPDL -MDevel::Peek -le "$pdl = random(); Dump $pdl->at.(0);" SV = PV(0x1c544eeb140) at 0x1c544eeaa10 REFCNT = 1 FLAGS = (PADTMP,POK,pPOK) PV = 0x1c5474d1ca0 "0.2684813620074430"\0 CUR = 18 LEN = 20
        That construct threw me a bit, and I'm way too dense to realize that all I needed to do was to remove the ".":
        C:\>perl -MPDL -MDevel::Peek -le "$pdl = random(); Dump $pdl->at(0);" SV = NV(0x1426b33a8f0) at 0x1426b33a908 REFCNT = 1 FLAGS = (TEMP,NOK,pNOK) NV = 0.32972986684150651
        Cheers,
        Rob