Random numbers in NEST

From NEST

Jump to: navigation, search

Random numbers are used for a variety of purposes in neuronal network simulations, e.g.

  • to create randomized connections
  • to choose parameter values randomly
  • to inject noise into network simulations, e.g., in the form of Poissonian spike trains.

This document discusses how NEST provides random numbers for these purposes, how you can choose which random number generator (RNG) to choose, and how to set the seed of RNGs in NEST. We use the term "random number" here for ease of writing, even though we are always talking about pseudorandom numbers generated by some algorithm.

NEST is designed to support parallel simulation and this puts some constraints on the use and generation of random numbers. We discuss these in the next section, before going into the details of how to control RNGs in NEST.

Contents

Random numbers in parallel simulations

Ideally, all random numbers in a simulation should come from a single RNG. This would require shipping truckloads of random numbers from a central RNG process to all simulations processes and is thus impractical, if not outright prohibitively costly. Therefore, parallel simulation requires an RNG on each parallel process. Advances in RNG technology give us today a range of RNGs that can be used in parallel, with a quite high level of certainty that the resulting parallel streams of random numbers are non-overlapping and uncorrelated. The latter, although, cannot be proven for any RNG we know of.

Per-process RNGs in NEST

Based on this idea, each virtual process (VP) in NEST has its own random number generator. Numbers from these RNGs are used to

  • choose random convergent connections
  • create random spike trains (poisson_generator, ht_generator, pulsepacket_generator) or currents (noise_generator).

Global RNG in NEST

In some situations, randomized decisions on different virtual processes are not independent of each other. The most important case are randomized divergent connections. The problem here is as follows. For the sake of efficiency, NEST stores all connection information in the virtual process (VP) to which the target of a connection resides (target process). Thus, all connections are generated by this target process. Now consider the task of generating 100 randomized divergent connections emanating from a given source neuron while using 4 VPs. Then there should be 25 targets on each VP on average, but actual numbers will fluctuate. If independent processes on all VPs tried to choose target neurons, we could never be sure that exactly 100 targets would be chosen in total.

NEST thus creates divergent connections using a global RNG. This random number generator provides the exact same sequence of random numbers on each virtual process. Using this global RNG, each VP chooses 100 targets from the entire network, but actually creates connections only for those targets that reside on the VP. In practice, the global RNG is implemented using one "clone" on each VP; NEST checks occasionally that all these clones are synchronized, i.e., indeed generate identical sequences.

Seeding, choosing and using RNGs in NEST

Per-process RNGs

Seeding

NOTE: This section applies to serial simulations, too. In this case, one has a single per-process RNG which is used for random convergent connections and all generators creating random signals. We first give an example for a simulation on a single VP, then one for four VPs. In SLI, you seed as follows:

0 << /rng_seeds [ 10 ] >> SetStatus

The equivalent PyNEST code is

nest.SetKernelStatus({'rng_seeds': [10]})

In both cases, 10 is used as seed. Note that the single seed value must be passed as an array/list.

The corresponding code for four VPs is

0 << /rng_seeds [ 10 11 12 13 ] >> SetStatus

The equivalent PyNEST code is

nest.SetKernelStatus({'rng_seeds': [10, 11, 12, 13]})

NEST requires that all seeds differ from each other. Otherwise, identical sequences would result.

Changing the generators

By default, NEST uses the Mersenne Twister mt19937ar random number generator. If you want to use other generators, you can exchange them as described below. If you have built NEST without the GNU Science Library (GSL), you will only have the Mersenne Twister and Knuth's lagged Fibonacci generator available. Otherwise, you will also have some 60 generators from the GSL at your disposal. To see the full list of RNGs, look at the rngdict:

rngdict info
nest.sli_run('rngdict info')

To replace the existing with new generators, you have to pass an array of NEST rng objects to the NEST kernel. This is illustrated here first for one, then for four virtual processes. There is no convenient PyNEST command to do this - you need to run the code through sli_run for now.

0 << /rngs [rngdict/knuthlfg :: 10 CreateRNG] >> SetStatus

The following happens here:

  • rngdict/knuthlfg :: fetches a "factory" for Knuth LFG generators from the rngdict
  • 10 CreateRNG uses the factory to create a single Knuth LFG generator with seed 10
  • This is then passed to the /rngs status variable of the kernel. This is a "write only" variable that is invisible in ShowStatus.

For four VPs, we iterate over the seeds inside the dictionary

0 << /rngs [10 11 12 13] { rngdict/knuthlfg :: exch CreateRNG } Map >> SetStatus

The Map command applies the function in curly braces to each seed value and returns the result as an array, i.e., it creates an array of four Knuth LFG generator objects seeded with 10, 11, 12, and 13, respectively.

To do this in PyNEST, simply wrap it all into

nest.sli_run('0 << /rngs [10 11 12 13] { rngdict/knuthlfg :: exch CreateRNG } Map >> SetStatus')

Global RNG

Seeding and exchanging the global RNG works in the same way as for the per-process RNGs. The seed of the global RNG must differ from the seeds of all per-process RNGs.

Seeding

SLI 0 << /grng_seed 10 >> SetStatus

PyNEST

nest.SetKernelStatus({'grng_seed': 10})

In both cases, 10 is used as seed.

Changing

SLI

0 << /grng rngdict/knuthlfg :: 10 CreateRNG >> SetStatus

PyNEST

nest.sli_run('0 << /grng rngdict/knuthlfg :: 10 CreateRNG >> SetStatus')
Views