Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28385 Discussions

Initializing the random_seed with /dev/urandom

Vishnu
Novice
792 Views

The example given on the GCC page for the same, uses /dev/urandom is as follows:

          subroutine init_random_seed()

            use iso_fortran_env, only: int64

            implicit none
            integer, allocatable :: seed(:)
            integer :: i, n, un, istat, dt(8), pid
            integer(int64) :: t
          
            call random_seed(size = n)
            allocate(seed(n))
            ! First try if the OS provides a random number generator

            open(newunit=un, file="/dev/urandom", access="stream", &
                 form="unformatted", action="read", status="old", iostat=istat)

            if (istat == 0) then
               read(un) seed
               close(un)
            else
            .
            .
            end if
            call random_seed(put=seed)

          end subroutine init_random_seed

 

I have a couple of questions:

  • Shouldn't the 'FORM' of the file opened be "BINARY"?
  • I don't understand how much data the READ pulls from /dev/urandom.
  • Here /dev/urandom is just used to initialize the seed for RANDOM_NUMBER(). But is there a way I can directly use /dev/urandom?
0 Kudos
1 Solution
mecej4
Honored Contributor III
792 Views

FORM='binary' is non-standard and was provided by some compilers before ACCESS='stream' became available in the Fortran standard. Intel Fortran supports lots of "legacy" features, and FORM='binary' is one of them. In new code, you should not use such features.

The purpose of the call to RANDOM_SEED with the SIZE=n argument is to query the RNG provided by the Fortran RTL. The query returns the size n, which is then used to allocate a sufficiently large array and to obtain values from /dev/urandom to fill that array. If the two lines that you marked with "." are left blank, you get yet another (but definitely insecure) seeding technique -- using a just-recently allocated variable without initialization.

There are many reasons for choosing one RNG over another. The "shopper"'s needs may range from "as secure as possible", for example in crypto-applications, to "reasonably random but really fast" for Monte-Carlo simulations.

In the debugging stage of program development, experienced programmers may use their own pet seeds in order to ensure reproducibility and, after debugging is completed, switch to a different method of setting the seed.

View solution in original post

0 Kudos
7 Replies
mecej4
Honored Contributor III
793 Views

FORM='binary' is non-standard and was provided by some compilers before ACCESS='stream' became available in the Fortran standard. Intel Fortran supports lots of "legacy" features, and FORM='binary' is one of them. In new code, you should not use such features.

The purpose of the call to RANDOM_SEED with the SIZE=n argument is to query the RNG provided by the Fortran RTL. The query returns the size n, which is then used to allocate a sufficiently large array and to obtain values from /dev/urandom to fill that array. If the two lines that you marked with "." are left blank, you get yet another (but definitely insecure) seeding technique -- using a just-recently allocated variable without initialization.

There are many reasons for choosing one RNG over another. The "shopper"'s needs may range from "as secure as possible", for example in crypto-applications, to "reasonably random but really fast" for Monte-Carlo simulations.

In the debugging stage of program development, experienced programmers may use their own pet seeds in order to ensure reproducibility and, after debugging is completed, switch to a different method of setting the seed.

0 Kudos
Vishnu
Novice
792 Views

mecej4 wrote:

The purpose of the call to RANDOM_SEED with the SIZE=n argument is to query the RNG provided by the Fortran RTL. The query returns the size n, which is then used to allocate a sufficiently large array and to obtain values from /dev/urandom to fill that array.

Okay, but where is 'n' defined?

I need a "reasonably random but really fast" generation of random numbers, but I suppose the seed won't affect the speed, as it is a one time thing. I use the RANDOM_NUMBER function, which I assume is the fastest possible option for serial generation.

0 Kudos
Steve_Lionel
Honored Contributor III
792 Views

If you call RANDOM_SEED with no arguments, the seed is set to a value based on the clock (in Intel Fortran - this is unspecified by the standard). ifort's RANDOM_NUMBER is reasonably fast, but one could come up with faster algorithms.

0 Kudos
mecej4
Honored Contributor III
792 Views

Vishnu wrote:

Okay, but where is 'n' defined?

The question suggests that you think that your chosen value of n is to be passed to the RNG. On the contrary, this is an "inquiry" call, asking the RNG to divulge the size of the seed that it uses. The IFort documentation says:

size

(Output; optional) Must be scalar and of type integer. Set to the number of integers (N) that the processor uses to hold the value of the seed.

For many simple RNG-s, n = 1 (i.e., the seed is a single integer).

0 Kudos
Steve_Lionel
Honored Contributor III
792 Views

ifort uses two 32-bit values for the seed. The algorithm is based on L'Ecuyer '90.

0 Kudos
Vishnu
Novice
792 Views

Steve Lionel (Ret.) wrote:

but one could come up with faster algorithms

Could you point me in their direction, if you know any? I would've thought that the fastest way would be to use '/dev/random' and use a function onto what ever space I want, say, real: [0,1), but then would it guarantee a distribution? I suppose that would depend on the specific function I used. Is there such an implementation already available?

mecej4 , Thanks for all the fish!

0 Kudos
Steve_Lionel
Honored Contributor III
792 Views

Do you want good or fast? See https://en.wikipedia.org/wiki/Linear_congruential_generator for simple ones. More uniform generators are more complex. I have no idea what /dev/random uses, and really, neither do you.

0 Kudos
Reply