Search code examples
fortrangfortranfortran90intel-fortran

Correctly setting random seeds for repeatability


The method for setting random seeds using the Fortran 90 subroutine random_seed is quite straightforward.

call random_seed( put=seed )

But I can't find any information about guidelines for setting the seed (which is absolutely necessary when you want repeatability). Folklore I've heard in the past suggested that scalar seeds should be large. E.g. 123456789 is a better seed than 123. The only support for this I can find on the web is that it is suggested for the ifort extension function ran() that one use a "large, odd integer value"

I understand this might be implementation specific and am using gfortran 4.8.5 but am also interested in ifort and (if possible) general guidelines that are independent of implementation. Here's some example code:

# for compactness, assume seed size of 4, but it will depend on 
# the implementation (e.g. for my version of gfortran 4.8.5 it is 12)

seed1(1:4) = [ 123456789, 987654321, 456789123, 7891234567 ]
seed2(1:4) =   123456789
seed3(1:4) = [         1,         2,         3,          4 ]

I'd guess that seed1 is fine, but pretty verbose if you're setting it manually (as I am) as seed length can be 12 or 33 or whatever. And I'm not even sure that it's fine because I haven't been able to find any guidelines at all about setting these seeds. I.e. these seeds should be negative for all I know, or 3 digit even numbers, etc. although I guess you'd hope the implementation would warn you about that (?).

seed2 and seed3 are obviously more convenient to set and for all I know are just as good. @Ross suggests that seed2 is in fact fine in his answer here: Random number generator (RNG/PRNG) that returns updated value of seed

So my question in summary is just: How can I correctly set the seed? Are any or all of seed1 to seed3 acceptable?


Solution

  • Guidelines for setting the seed depend on the PRNG algorithm that RANDOM_NUMBER uses, but in general the more "entropy" you provide the better.

    If you have a single scalar value, you can use some simple PRNG to expand that to the full seed array required by RANDOM_SEED. See e.g. the function lcg in the example code at https://gcc.gnu.org/onlinedocs/gcc-4.9.1/gfortran/RANDOM_005fSEED.html

    Current versions of GFortran have some protections against bad seeds, and it should be relatively immune towards "dumb" seeding (e.g. all values of seed(:) identical, or all values small or even zero), but for portability to other compilers following something like I suggested above might still be a good idea.