Intel® oneAPI Math Kernel Library
Ask questions and share information with other developers who use Intel® Math Kernel Library.

Random Number Generator State Info

I'm porting some Fortran applications from CVF to Fortran 8.0
and also moving to MKL 6.1. I'm using Visual Studio 2003 .NET
for the IDE.

Some of my old software uses the ability to get / set the current
state of the current random number generator, and I'm looking
for a similar facility in MKL 6.1 from Fortran. I see the
following in C headers accessed by mkl_vsl.h:

vslGetBrngProperties(int , VSLBRngProperties* properties);


vslRegisterBrng(const VSLBRngProperties* properties);

But at the moment, all I can see is the SIZE of the stream state,
not it's location or structure.

Is there a capability for reading / writing the RNG state under
the current or a future version of MKL? This capability is
important IF I have to "back up" a simulation, say to re-run
the last 10,000 iterations while recording a new parameter....

This note may duplicate a previous attempt of 1/4/2004.

Well Howell
0 Kudos
8 Replies
The developer has a rather complete response to this question but is having some difficulty in getting access to the forum. While I could submit his response, I would prefer to wait until he is able to provide the response himself. This should be resolved soon. I will give away the plot, but not the details - what you want to do can be done.
0 Kudos
That Intel "can do" is not giving much away - I knew that ~;)
Thanks for the good news - I can concentrate on other areas
(like the really neat MV addition to gaussian RNG in 7.0 beta!!!).
0 Kudos
Yes,MKLVSL provides means tocontrola state of the generator.A number of VSL service routines control RNG (to save, copy its state as well as routines useful to use RNGs in parallel).
vslNewStream(stream,brng,seed) - creates and initializes new random stream stream. Routine allocates the memory to store the state of brng, initial value seed is used to set initial state (pick up a random sequence).Descriptorstream is used later for reference to this particular sequence. (You may create unlimited number of streams in your simulation).
vslCopyStream(newstream,srcstream) - createsa copy ofthe srcstream. Descriptornewstrem is used later for reference to the stream copy.This routine is similar to vslNewStream. The only difference is that brng and its state are copied from the srcstream.
vslCopyStreamState(deststream,srcstream) - copiesthe state of thesrcstream to thedeststream.The deststream should be created earlier, i.e. byvslNewStream or by vslCopyStream.
vslDeleteStream(stream) -deallocates the memory used for the stream stream.You should delete all the streams you created at the end of simulation.
Regarding to your particular question, I would recommend the following general scheme:
  1. Create an original stream stream by vslNewStream routine.
  2. Perform initial propagation (RNG generation) using the stream. After initial propagation you will start main simulation (10,000 iterations) with different parameters.
  3. Create a copy of the stream streamcopy, which will hold the state of the generator after initial propagation.
  4. Perform last 10,000 iterations with the stream.
  5. Restore the state of the stream from the streamcopy using vslCopyStreamState routine: vslCopyStreamState(stream,streamcopy).
  6. Perform last 10,000 iterations with the stream and different simulation parameter.
  7. Delete the stream and the streamcopy.

Steps 5 and 6 are used every time you change the simulation parameter.

For further information I would recommend you MKL Reference Manual (API and list of routines). Also I would recommend you VSL Notes document, which provides VSL-related general discussions, RNG testing results and performance figures.

0 Kudos

Thank you for your reply and help.

Your 7 steps are useful in changing the state of a generator
within a single computer run. However, I also need what might
be called a "persistant state save", which is what I intended
to ask for with the ability to read / write the state information.

This would seem to conflict with an other design objective of
"data hiding" where I should not want to know just how the state
is stored inside the RNG. However, if my uninterruptable power
supply sends a signal which requires that I shut down a long-running
task, I'd like to be able to query the RNG state, possibly with
streamcopy(), and then write the results of that query to my
hard-drive prior to shutdown. Then I could restore the RNG
when I restart.

Can I bypass "data hiding" and determine the size of the data
structure to be stored and the contents of that structure?

Sorry to be such an ah, er, NAG.

0 Kudos

Well, you are very advanced and powerful user! Thanks for asking interesting questions.

VSL do not provide direct access to the stream state data. This is because VSL has a number of basic generators, and each basic generator's state has different size, fields, etc.

Bad news is that MKLVSL currently do not provide routines to save/restore stream to a file. However, such a feature might be useful for Monte Carlo people since Monte Carlo simulation is basically takes a lot of time.

Good news is that you are able to get the size of the stream state, and try to store/restore data yourself. The vslGetBrngProperties routine is what you really need:

vslGetBrngProperties(brng,properties) - fills the fields of the structure properties with the data describing properties of the basic generator brng.

Among other fields the properties structure has the streamstatesize field (the first field in the structure, its size is 4 bytes). For further information I would recommend the Advanced Service Subroutines chapter of the MKL Reference Manual.

To implement the save/restore to a file I would suggest the following scheme:

  1. Perform the first run of a simulation.
  2. Determine the size in bytes of the stream state structure.
  3. Get access to the memory, where the stream state data is stored, and save this data to a file (you know number of bytes to store from Step 2).
  4. Delete all streams and finish application.

For the second run.

  1. Create new stream restored_stream by vslNewStream routine. The basic generator should be the same as in the first run. No matter which seed you will pass.
  2. Before the second run you should determine the size of the stream state structure again, and load the stream state data from the file to the memory restored_stream points to.

I would not recommend using restored stream state directly because there are some fields in the structure you saved to a f ile, which are pointers to allocated memory (used internally by VSL in some cases). To avoid non-allocated memory access you should do following:

  1. Create one more stream stream by vslNewStream function. No matter which seed you will pass, the only important is brng - should be the same as you saved/restored.
  2. Use vslCopyStreamState to copy the state of restored_stream to the stream. This routine will copy only the stream state related information and will not copy pointers.
  3. Perform second run.
  4. Delete all streams.

The main difficulty is in getting access to the stream state data you want to save/restore in FORTRAN. (It could be done very naturally in C). I have no nice idea how to do this. Let me explain in more details why.

Each instance of VSL_STREAM_STATE (i.e. the stream we want to save) has two 32-bit fields used internally to store address of the memory block allocated in vslNewStream, which is used to store stream state data.

INTEGER*4 descriptor1
- stores 32-bit address of the memory block used to store stream state information
INTEGER*4 descriptor2 - stores higher 32-bits of the address (for 64-bit systems)

I don't know how to use these fields in the FORTRAN. Perhaps, you have ideas. I would really appreciate you if you could share with me.

- Sergey

0 Kudos

Thanks for your detailed and helpful suggestions. You may have
just sold be an Intel C compiler to go with my Fortran ~;)

For now, I may just hope that any random starting point is as good
as any other, and not worry about restarting at the very point
where I left off - after all, the numbers are random! That feature
is needed, however, if I need to re-start at an earlier, rather
than a random point.

While I'm bi-lingual, I couldn't think of a way of doing
typedef void* VSLStreamStatePtr;
in Fortran 8 either.

Your trick of vslCopyStreamState to move the state info without
changing the stream pointers is very interesting. I may have
to wait until the weekend to try it (darn "day jobs" anyway ~;).
0 Kudos

Hello Well,

Please let me know any issues you encounter while testing save/restore to a file.

I have one more idea how to resolve the issue with stream state storing/restoring.

There is vslSkipAheadStream routine, which might be useful to restart simulation. Parameters are the stream and number of random numbers to skip. Thus, the solution might be following:

  1. Create the stream with vslNewStream function (you will pass basic generator and the seed). Perform the first run. At the end of the run you know how many numbers N were generated.
  2. Save this N to a file, delete the stream and finish the application.

In the second run you should do following:

  1. Create the stream with vslNewStream function (you will pass the same basic generator and the same seed as in the first run).
  2. Call vslSkipAheadStream subroutine to skip N numbers generated in the first run. This subroutine works much faster than if you would simply generate these N numbers. One restriction is that not all VSL basic generators support the skip-ahead method. Please see VSL Notes document for details.
  3. Perform the second run.
  4. Delete the stream and finish the application.

Regarding to choosing initial state at random fashion, yes, this isanotherpossible solution. Isee several things I need to keep in mind in this situation.

  • Is it acceptable tostudy the system under different parameters and different random sequences? Sometimes it might be important to use the same random numbers with different parameters (i.e. to study correlation properties).
  • Does basic generator have sufficient period to choose sequences at random?It is quite general recommendation not use random numbers more than square root of generator's period. In addition, choosing subsequences at random there is a chance that two subsequences will significantly overlap. (This chance is higher when total length of subsequences goes toward generator's period). Sometimes overlapping is not critical.On the other hand,situations are possible when overlapping in two sequences with result in inconsistent (biased) result.

Thanks for interesting discussion.

- Sergey

0 Kudos

And thank you for all your suggestions. As for "interesting",
I'd reserve that term for your wonderful article on
"Monte Carlo European Options Pricing....." in the Intel
download library. Random numbers are fun, and maybe the
ancient statisticians who helped their kings wager were
really on to something!

0 Kudos