Developer Guide and Reference

Contents

Usage Model

A typical usage model for using the intrinsics in the Short Vector Random Number Generator (SVRNG) library is the same as for standard C++ or Intel® Math Kernel Library (Intel® MKL) vector statistics random number generator and looks something like the following:
  • Include
    svrng.h
    header file
  • Create and initialize basic SVRNG generator engine, create and initialize distribution (if necessary).
  • Call one or more SVRNG generation function.
  • Process the output.
  • Delete the SVRNG engines and distributions.
On Windows*, users will need to explicitly link the static or dynamic libraries: static:
libirng.lib
, dynamic:
libirngmd.lib
. On Linux*
and
macOS*
the compiler driver will link automatically.
The following example demonstrates generation of a random stream that is output of basic generator engine MT19937 with seed equal to 777. The engine is used to generate two arrays: 1024 uniformly distributed random numbers between <a = 0.0, b = 4.0> via scalar generator call which should be vectorized by the compiler and 1024 normally distributed with parameters <mean = 2.0, standard deviation = 1.0> random numbers in blocks by 16 elements via direct call of SIMD-vector implementation. Delete engines and distributions after completing the generation. Check status for possible errors happened. The purpose of the example is to calculate the sample mean for both distributions with the given parameters.
#include <stdio.h> #include <svrng.h> int main( void ) { int i, st = SVRNG_STATUS_OK; double res1[1024], res2[1024]; double sum1 = 0, sum2 = 0; double mean1, mean2; svrng_engine_t engine; svrng_distribution_t distr1, distr2; /* Create mt19937 engine */ engine = svrng_new_mt19937_engine( 777 ); /* Create uniform distribution */ distr1 = svrng_new_uniform_distribution_double( 0.0, 4.0 ); /* Create normal distribution */ distr2 = svrng_new_normal_distribution_double( 2.0, 1.0 ); /* Scalar generator call, can be vectorized by compiler */ #pragma ivdep #pragma vector always for( i = 0; i < 1024; i ++ ) { res1[i] = svrng_generate_double( engine, distr1 ); } /* Direct call to SIMD-vector implementation */ /* generating 16 packed elements */ for( i = 0; i < 1024; i += 16 ) { *((svrng_double16_t*)(&res2[i])) = svrng_generate16_double( engine, distr2 ); } /* Compute mean values */ for( i = 0; i < 1024; i++ ) { sum1 += res1[i]; sum2 += res2[i]; } mean1 = sum1 / 1024.0; mean2 = sum2 / 1024.0; /* Printing results */ printf( "Sample mean of uniform distribution = %f\n", mean1 ); printf( "Sample mean of normal distribution = %f\n", mean2 ); /* Check for resulted status */ st = svrng_get_status(); if(st != SVRNG_STATUS_OK) { printf("FAILED: status error %d returned\n", st); } /* Delete distributions */ svrng_delete_distribution( distr1 ); svrng_delete_distribution( distr2 ); /* Delete engine */ svrng_delete_engine( engine ); return st; }
Another example demonstrates the "skip-ahead" technique which ensures identical random number sequences in cases of parallel and sequential generation for certain engines. The rand0 engine is being created and copied to T "threads" with the "skip-ahead" adjustments applied. Each "thread" generates N uniformly distributed unsigned integer random values and then all LEN=T*N numbers are compared to the sequential call:
#include <stdio.h> #include <stdint.h> #include <svrng.h> #define LEN 1024 #define T 8 #define N (LEN/T) int main( void ) { uint32_t seq_res[LEN+32], parallel_res[LEN+32]; svrng_engine_t seq_engine; svrng_engine_t parallel_engine[T]; int l, n, t, errs = 0, st = SVRNG_STATUS_OK; /* Create sequential engine and distr */ seq_engine = svrng_new_rand0_engine( 777 ); /* Copy existing sequential engine to new T parallel ones */ /* with t*N offsets using skipahead method */ for( t = 0; t < T; t++ ) { int thr_offset = t*N; parallel_engine[t] = svrng_copy_engine( seq_engine ); parallel_engine[t] = \ svrng_skipahead_engine( parallel_engine[t], thr_offset ); } /* Sequential loop using scalar function (can be vectorized) */ #pragma ivdep #pragma vector always for( l = 0; l < LEN;