srand64(3S)
srand64, drand64, drand64_advance, drand64_get, drand64_getv, drand64_maxthreads, drand64_set, drand64_setv, drand64_thread - Thread- safe parallel 64-bit random number generator
As shipped in IRIX 6.5.19. Added in IRIX 6.5.15.
NAME srand64, drand64, drand64_advance, drand64_get, drand64_getv, drand64_maxthreads, drand64_set, drand64_setv, drand64_thread - Thread- safe parallel 64-bit random number generator SYNOPSIS Fortran synopsis: REAL FUNCTION SRAND64 (harvest) REAL harvest DOUBLE PRECISION FUNCTION DRAND64 (harvest) DOUBLE PRECISION harvest SUBROUTINE DRAND64_ADVANCE (count) INTEGER*8 count SUBROUTINE DRAND64_GET (seed, count, thread) INTEGER*8 seed, count INTEGER thread SUBROUTINE DRAND64_GETV (state, count) INTEGER*8 state(*), count(*) INTEGER FUNCTION DRAND64_MAXTHREADS () SUBROUTINE DRAND64_SET (seed) INTEGER*8 seed SUBROUTINE DRAND64_SETV (state, count) INTEGER*8 state(*), count(*) INTEGER FUNCTION DRAND64_THREAD (thread) INTEGER thread C/C++ synopsis: #include <scsl.h> float srand64 (float *harvest); double drand64 (double *harvest); void drand64_advance (long long count); void drand64_get (long long *seed, long long *count, int thread); void drand64_getv (long long state[], long long count[]); int drand64_maxthreads (void); void drand64_set (long long seed); void drand64_setv (long long state[], long long count[]); int drand64_thread (int thread); IMPLEMENTATION These routines are part of the SCSL Scientific Library and can be loaded using either the -lscs or the -lscs_mp option. The -lscs_mp option directs the linker to use the multi-processor version of the library. When linking to SCSL with -lscs or -lscs_mp, the default integer size is 4 bytes (32 bits). Another version of SCSL is available in which integers are 8 bytes (64 bits). This version allows the user access to larger memory sizes and helps when porting legacy Cray codes. It can be loaded by using the -lscs_i8 option or the -lscs_i8_mp option. A program may use only one of the two versions; 4-byte integer and 8-byte integer library calls cannot be mixed. The C and C++ prototypes shown above are appropriate for the 4-byte integer version of SCSL. When using the 8-byte integer version, the variables of type int become long long and the <scsl_i8.h> header file should be included. DESCRIPTION These routines comprise a 64-bit thread-safe parallel random number generator that is based on the linear congruent sequence Y(n+1) = (a X(n) + c) mod 2^64. The parameters a and c are chosen from Knuth, The Art of Computer Programming , Vol. 2, 3rd edition, pp. 106-108: a = 6364136223846793005 c = 1 Y(n+1) is then converted to a floating point value in the range [0,1). The thread safety is ensured by separating the RNG state for each thread. Thus, each thread generates an independent random sequence starting from predefined values. Up to drand64_maxthreads() parallel streams of random numbers can be supported simultaneously. srand64 This function returns a single precision random number in the range [0,1); the same value is returned in the argument, if provided. drand64 This function returns a double precision random number in the range [0,1); the same value is returned in the argument, if provided. drand64_advance This routine advances the internal state table entries for the calling thread as if srand64() or drand64() had been called count times. drand64_get This routine obtains the starting point of srand64() and drand64(), as well as the invocation count for the thread specified in the third argument. drand64_getv This routine provides the internal state of srand64() and drand64(). The arguments are arrays of seeds and invocation counts that can be given as arguments to drand64_setv(). The array arguments must have at least drand64_maxthreads() elements. drand64_maxthreads This function returns the maximum number of random number streams that can be generated in parallel. The internal state tables used in drand64_getv() and drand64_setv() have drand64_maxthreads() entries. drand64_set This routine sets the starting point of srand64() and drand64(). By default the generator is initialized to -1. drand64_setv This routine sets the internal state of srand64() and drand64(). The arguments are arrays of seeds and invocation counts, as returned by drand64_getv, for example. The array arguments must have drand64_maxthreads() elements. drand64_thread After a call this routine, the next invocations of srand64() and drand64() will have the same effect as if called from the base thread number specified in the argument to drand64_thread(). This function returns the base thread number that had previously been generating the random sequence. EXAMPLES Below are several usage examples for RAND64 routines. Example 1: Initialize the internal RNG state table with a single seed value and generate a random number for each thread. Fortran 77: EXTERNAL SRAND64 REAL SRAND64 INTEGER*8 SEED REAL S1, DUMMY SEED = 1 CALL DRAND64_SET(SEED) C Each thread gets a different random number C$OMP PARALLEL PRIVATE(S1, DUMMY) S1 = SRAND64(DUMMY) C$OMP END PARALLEL C/C++: #include <scsl.h> float s1, dummy; long long seed = 1LL; drand64_set(seed); /* Each thread gets a different random number */ #pragma omp parallel private(s1, dummy) { s1 = srand64(&dummy); } Example 2: After saving the RNG state table, generate 11 random numbers for each thread. Then restore the state table and use drand64_advance() to "skip" 10 random numbers. The next random number generated for each thread should be identical to the 11th value from the original stream. Fortran 90: INTEGER(KIND=8), DIMENSION(:), ALLOCATABLE :: STATE, COUNT EXTERNAL DRAND64_MAXTHREADS, OMP_GET_THREAD_NUM, DRAND64 INTEGER :: I, TABLE_SIZE, DRAND64_MAXTHREADS, OMP_GET_THREAD_NUM REAL(KIND=8) :: D1, DUMMY, DRAND64 TABLE_SIZE = DRAND64_MAXTHREADS() ALLOCATE(STATE(TABLE_SIZE)) ALLOCATE(COUNT(TABLE_SIZE)) CALL DRAND64_GETV(STATE, COUNT) !$OMP PARALLEL PRIVATE(I, D1, DUMMY) DO I = 1, 11 D1 = DRAND64(DUMMY) END DO PRINT *, OMP_GET_THREAD_NUM(), D1 !$OMP END PARALLEL CALL DRAND64_SETV(STATE, COUNT) !$OMP PARALLEL PRIVATE(D1, DUMMY) DRAND64_ADVANCE(10_8) D1 = DRAND64(DUMMY) PRINT *, OMP_GET_THREAD_NUM(), D1 !$OMP END PARALLEL C/C++: #include <scsl.h> #include <omp.h> #include <stdlib.h> #include <stdio.h> long long *state, *count; int i, table_size; double d1, dummy; table_size = drand64_maxthreads(); state = (long long *) malloc(table_size * sizeof(long long)); count = (long long *) malloc(table_size * sizeof(long long)); drand64_getv(state, count); #pragma omp parallel private(i, d1, dummy) { for (i = 0; i < 11; i++) d1 = drand64(&dummy); printf("%d, %g0, omp_get_thread_num(), d1); } drand64_setv(state, count); #pragma omp parallel private(d1, dummy) { drand64_advance(10LL); d1 = drand64(&dummy); printf("%d, %g0, omp_get_thread_num(), d1); } Example 3: Using only a single thread, generate 10 independent streams of random numbers. Fortran 77: EXTERNAL DRAND64_THREAD, SRAND64 INTEGER DRAND64_THREAD REAL SRAND64 INTEGER I, J, OLDID REAL STREAM(1000,10), DUMMY DO J = 1, 10 OLDID = DRAND64_THREAD(J-1) DO I = 1, 1000 STREAM(I, J) = SRAND64(DUMMY) END DO END DO C RESTORE ORIGINAL BASE THREAD OLDID = DRAND64_THREAD(0) C/C++: #include <scsl.h> int i, j, oldid; float stream[10][1000], dummy; for (i = 0; i < 10; i++) { oldid = drand64_thread(i); for (j = 0; j < 1000; j++) stream[i][j] = srand64(&dummy); } /* restore original base thread */ oldid = drand64_thread(0); CAUTIONS Care is required when using drand64_thread() in parallel regions. If multiple parallel threads possess the same RAND64 base thread number as assigned with a call to drand64_thread(), then thread safety will be compromised, with different threads no longer producing independent random sequences. The statistical randomness of the resulting individual sequences will also likely be degraded. SEE ALSO INTRO_SCSL(3S), DRAND48(3C)