prepare_codeobj_code_for_rng function

(Shortest import: from brian2cuda.device import prepare_codeobj_code_for_rng)


Prepare a CodeObject for random number generation (RNG).

There are two different ways that random numbers are generated in CUDA:
  1. Using a buffer system which is refilled from host code in regular intervals using the cuRAND host API. This is used for rand(), randn() and poisson(lambda) when lambda is a scalar. The buffer system is implemented in the template.

  2. Using on-the-fly RNG from device code using the cuRAND device API. This is used for binomial and poisson(lambda) when lambda is a vectorized variable (different across neurons/synapses). This needs initilization of cuRAND random states, which is also happening in the template.

This function counts the number of rand(), randn() and poisson(<lambda>) appearances in codeobj.code.cu_file and stores this number in the codeobj.rng_calls dictionary (with keys "rand", "randn" and "poisson_<idx>" ,one <idx> per poisson() call). If the codeobject uses the curand device API for RNG (for binomial of poisson with variable lambda), this function sets codeobj.needs_curand_states = True.

For RNG functions that use the buffer system, this function replaces the function arguments in the generated code such that a pointer to the random number buffer and the correct index are passed as function arguments.

For RNG functions that use on-the-fly RNG, the functions are not replaced since no pointer or index has to be passed.

For the poisson RNG, the RNG type depends on the lambda value. For scalar lambda, we use the buffer system which is most efficient and most robust in the RNG. For vectorized lambda values, the host API is inefficient and instead the simple device API is used, which is the most efficient but least robust. For the two RNG systems to work, we overload the CUDA implementation of _poisson with _poisson(double _lambda, ...) and _poisson(unsigned int* _poisson_buffer, ...). When the buffer system is used, we replace the _poisson(<lambda>, ...) calls with _poisson(<int_pointer>, ...) calls.

For poisson with lambda <= 0, the returned random numbers are always 0. This function makes sure that the lambda is replaced with a double literal for our overloaded _poisson function to work correctly.


codeobj: CodeObjects :

Codeobject with generated CUDA code in codeobj.code.cu_file.