I have a rather large C++ library and need to deal with random number generations in different portions of the code (i.e. different methods or classes).
While the question How do I generate thread-safe uniform random numbers? is concerned to the case when the lifespan of the random engine is limited to a (parallel) function call, here instead, I'm looking for a way of having one (one per thread) generator that survives for the whole program.
The main structure of the code is based on an Algorithm class that at every iteration calls an update() method from several instances of class B (the number of instances may change at every iteration). In the update() method, several random numbers are generated.
To avoid dealing with random number engines, I encapsulated a 'global' RNG in a static class:
class Rng {
public:
static Rng &Instance() {
static Rng s;
return s;
}
std::mt19937_64 &get() { return mt; }
void seed(int seed_val) { mt.seed(seed_val); }
private:
Rng(int seed_val = 20201103) { mt.seed(seed_val); }
~Rng() {}
Rng(Rng const &) = delete;
Rng &operator=(Rng const &) = delete;
std::mt19937_64 mt;
};
Now I realize that the update of the instances of class B can be performed in parallel and independently, and would like to use openmp to do something like
std::vector<B> b_instances = .... ;
#pragma omp parallel for
for (auto& b: b_instances) b.update()
....
auto& rng = Rng::Instance().get();
... do more stuff with rng ...
A minimal example of the update method could be
B::update() {
auto& rng = Rng::Instance().get();
std::normal_distribution<double> distribution(5.0,2.0);
this->x = distribution(rng);
}
My question now is: how can I call the update methods in parallel without incurring in any race from the static rng? I read that the best solution would be to have a dedicated RNG for every thread, but I still would like to keep the static Rng class. What could be an elegant solution?
Aucun commentaire:
Enregistrer un commentaire