Singleton handler of Pseudo-Random Number Generator(s) More...
#include <GlobalPRNG.h>
Public Member Functions | |
T_GlobalPRNG (T_GlobalPRNG const &)=delete | |
Copy constructor disabled as per singleton pattern. More... | |
void | operator= (T_GlobalPRNG const &)=delete |
Copy operator disabled as per singleton pattern. More... | |
Static Public Member Functions | |
static T_GlobalPRNG & | handle () |
Return a handle to the hash table, not to the single generator (see below). More... | |
static PRNG * | get_or_create (const sqlite3_context *db, uint64_t seed=no_seed) |
Return a pointer to an initialized generator. More... | |
static PRNG * | get_or_create (const sqlite3 *db, uint64_t seed=no_seed) |
Return a pointer to an initialized generator. More... | |
static bool | release (const sqlite3 *db) |
Releases a generator (delete). May require re-seeding. More... | |
Static Public Attributes | |
static constexpr uint64_t | no_seed = 0xBAD0000000000000L |
Higher part of the int64 is used to identify missing or invalid seed. More... | |
Singleton handler of Pseudo-Random Number Generator(s)
The generation of pseudo-random numbers for Monte Carlo applications is a critical aspect in the design of an application.
Pseudo-random numbers should be generated upon a known seed. Reproducibility of the complete simulation process must be guaranteed, provided the same seed.
A further complication arises from multithreaded applications with multiple threads sharing a single Pseudo-Random Number Generator (PRNG). Indeed, the order with which threads may advance the sequence of pseudo-random numbers is defined by the order of execution of threads which is, by nature, stocastic.
In SQLamarr, PRNs are generated with a generator connected to the database instance. Database instances are supposed to live in a thread as concurrent access to the same SQLite database introduces an easily avoidable overhead. If such a good practice is followed, then each thread gets associated to a different random number generator, seeded indepedently (for example based on the number of threads).
From a technical perspective, a Singleton GlobalPRNG class handles a hash table associating a random number generator to each known database instance.
On the attempt to access a generator for a database instance not previously mapped in the hash table, a new instance is allocated, using the seed provided as an argument. If the seed is not provided, an exception is thrown, unless explicitely ignored compiling with flag -DALLOW_RANDOM_DEVICE_FOR_SEEDING
.
Generators can be reseeded at any time, by accessing the generator associated to an existing database instance, while passing the seed.
Any pseudo random number generator defined according the STL generator interface can be used to specialize the template class T_GlobalPRNG
defining the behaviour described above.
The default GlobalPRNG
specialization uses a RANLUX with 48 bit generator as provided by the C++ STL.
Note on multithreading. A std::unordered_map is used to associate a random number generator to a given database. Since the operations of consulting and updating an unordered_map are not thread-safe and since, by design, such a mapping must be shared across multiple threads, the access to the map is protected by a std::mutex.
Definition at line 81 of file GlobalPRNG.h.
|
delete |
Copy constructor disabled as per singleton pattern.
|
inlinestatic |
Return a pointer to an initialized generator.
Definition at line 110 of file GlobalPRNG.h.
|
inlinestatic |
Return a pointer to an initialized generator.
Definition at line 99 of file GlobalPRNG.h.
|
inlinestatic |
Return a handle to the hash table, not to the single generator (see below).
Definition at line 91 of file GlobalPRNG.h.
|
delete |
Copy operator disabled as per singleton pattern.
|
inlinestatic |
Releases a generator (delete). May require re-seeding.
Definition at line 157 of file GlobalPRNG.h.
|
staticconstexpr |
Higher part of the int64 is used to identify missing or invalid seed.
Definition at line 86 of file GlobalPRNG.h.