0
votes

I created a class that I can use as a random number generator that works better than the standard rand(). Below I've included the .cpp file for my class which contains the class variables std::mt19937 gen and std::uniform_real_distribution distr.

My question is whether it's necessary to create multiple instances of my number generator. For instance if I have classes A and B and each class needs to sample random numbers both within the range [0,1] would it be better if A and B each had its own instance of UniformNumberGenerator or should I take a singleton approach and use one instance for both classes?

UniformNumberGenerator::UniformNumberGenerator(double min, double max)
{
    gen = CreateGenerator();
    distr = std::uniform_real_distribution<double>(min, max);
}

std::mt19937 UniformNumberGenerator::CreateGenerator()
{
    std::random_device rd;
    std::mt19937 result(rd());
    return result;
}

//Take a sample
double UniformNumberGenerator::operator()()
{
    return distr(gen);
}
2
This seems perfectly pointless. The standard library already factors randomness and distributions into precisely those two components that should be kept functionally separate: An expensive engine to be generated once (per thread) and never touched again, and cheap distribution objects that produce actual numbers based on a given source of randomness. You're reinventing the wheel, only that yours has corners and is made of paper mache.Kerrek SB
How do you prime/seed your generator? Most random generators allow a seed value, which allows reproducible sequences as well as "random". If you do that a singleton would be better.Gone Coding
I seed the generator in my "CreateGenerator" method. the mt19937 instnace gets seeded with the std::random_device rd. @KerrekSB can you explain a bit more when you say these two components should be kept separate? You need to supply the distribution with a random generator in order to get it to produce a value.user1855952

2 Answers

2
votes

One legitimate reason to have multiple instances of a pseudo-random number generator (PRNG) would be to increase the precision of simulation estimates of the difference between two systems using correlation induction strategies. The simplest of these is "common random numbers" (CRN)*. Intuitively, if you have two different arrangements of your bank or your grocery store and you want to determine which configuration works best, it would make sense to compare them with exactly the same set of customers and transactions. CRN does this by generating exactly the same sequence of PRNs for both scenarios, but you have to be very careful to keep the PRNG streams in sync. This can be a real challenge if the two systems have different quantities of permanent entities such as servers. In that case, one PRNG per server would be appropriate, and one PRNG to generate characteristics for each arrival stream as well. All PRNGs would be independently seeded within a run (so the servers would appear to be independent of each other), and identically seeded between runs to yield the run-level synchronization.

Bottom line -- unless you plan to use correlation induction strategies for variance reduction and you're really sure you know what you're doing, you should use a single PRNG. MT19937 produces sequentially uncorrelated k-tuples for fairly large values of k, over 600 if I recall correctly. If your goal is to generate independent samples, that's exactly what MT19937 and other decent generators are designed to mimic via a single instance of the generator.

* - There's a Wikipedia article about this as well, but it's currently written very poorly so I don't recommend using it as a resource.

1
votes

I can't judge your random number generator based on the code you posted, but I can say a few things based on which approach (instantiating a few copied of the generator vs having a singe global one), is best:

  1. if memory is important, obviously the singleton approach is the one you would prefer because you only a allocate the memory once
  2. unless your generator supports any fancy features which you would like to use for your objects like being able to generate numbers in a certain, customizable distribution, I don't really see a reason for having more than one instance of this generator in the application.
  3. if I think of how you usually use a random number generator in an application - you rarely need to call it - I would go for the singleton approach.

hope this helps...