Random numbers inside OpenACC loop (nvfortran compiler)

Is there a straightforward way to generate random numbers inside an OpenACC parallel loop? I want the seed within each loop/thread to be different. The reference code that demonstrates the required task to be done is as follows:

PROGRAM genRandNums

    implicit none

    integer :: i
    double precision :: a(100)
    
   !$acc parallel loop
    DO i = 1,100
        call random_seed()
        call random_number(a(i))
    ENDDO

END PROGRAM

This code works on the gnu’s 'gfortran ’ but throws an error with the 'nvfortran ’ compiler as the intersic functions random_seed() and random_number() are not supported. How can I modify this code to work with the nvfortran compiler?

Hi hemanthgrylls,

In general, running a RNG in parallel is problematic. RNGs contain state which is often shared, making the RNG unsafe to parallelize. Instead, each iteration of the parallel loop would need to maintain it’s own state in order to avoid race conditions.

You can do this with the device side cuRAND (examples include with the compilers under the “examples/CUDA-Libraries/cuRAND” directory), the cost of maintaining state for each iteration is high. Plus, you need to pass in a set of randomly generated seeds so each instance of the RNG is unique. Since your only using one random number per iteration, you’re better off calling cuRAND from the host to generate an array of random values and then using this array in the parallel loop.

I had the opportunity to work with Johan Carlsson on a pure OpenACC device side RNG implementation. Like cuRAND, you’d want to use it if your generating many random number per loop iteration. For cases where you’re using one random number per iteration, its still better to precompute the random values. Though unlike cuRAND Johan’s DES PRNG implementation is much lighter weight so has less overhead. For full details on DES PRNG see: Pseudo Random Number Generation by Lightweight Threads | OpenACC

I’ve only used DES PRNG with C/C++ programs, but presume if you add a Fortran interface module, should be able to be used within Fortran as well.

Hope this helps,
Mat

1 Like