Uncorrelated parallel random seeds with C++ 2011?

Currently, I have a main application in Fortran that need a seed to generate pseudo-random numbers. I would like to run many (many) times this application with completely uncorrelated seeds (and furthermore completely independent pseudo-random numbers chains).

My question is : how to generate the seeds with C++ 2011 ?

Answers


In your main thread, extract a single seed (or seed sequence) from a good random source (e.g. from /dev/urandom on Linux). Use that data to seed a single root PRNG. Then use that PRNG to generate seed values for your thread-local PRNGs.

#include <random>
#include <vector>

typedef std::mt19937 rng_type;
std::uniform_int_distribution<rng_type::result_type> udist;

int main()
{
    rng_type rng;

    // seed rng first, and store the result in a log file:
    rng_type::result_type const root_seed = get_seed();
    rng.seed(root_seed);

    // make thread seeds:
    std::vector<rng_type::result_type> seeds(NUMBER_OF_THREADS);
    for (auto & n : seeds) { n = udist(rng); }

    // make threads...
}

The random number engine interface in <random> lets you seed both from a single integer and from a sequence of integers. If you want additional randomness, you can seed the mt19937 from a sequence of several hundred integers.


C++11 provides std::random_device to provide non-deterministic random numbers if a source is available. You'll have to check your implementation to be sure it's good though. libc++ uses /dev/urandom by default. libstdc++ does as well if the macro _GLIBCXX_USE_RANDOM_TR1 is defined. Visual Studio's implementation is unfortunately not non-deterministic. edit: as of VS2012 their implementation uses Windows' cryptography services.

If std::random_device provides access to a non-deterministic source of randomness (typically /dev/urandom uses a cryptographic PRNG) then this should be sufficient for generating independent seeds.

#include <random>

int main() {
    std::random_device r;
    std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
    std::mt19937 engine(seed);

}

Instead of using a single value as a seed, some engines may do better with more seed data. A seed sequence is the alternative provided by the standard. Engines can be seeded with seed sequences, which are objects you load up with any amount of data and which produces seed data based on that.

std::random_device r;
std::vector<std::mt19937> engines;

int engines = 50;
for (int i = 0; i < engines; ++i) {
    std::seed_seq s{r(), r(), r(), r(), r(), r(), r(), r()};
    engines.emplace_back(s);
}

Eight 32-bit values, 256 bits, is enough but if you really want you can use more. Each of the standard engines documents how much data it uses from a seed sequence.

For example, each mt19937 engine will retrieve mt19937::state_size (624) 32-bit values from the seed sequence. The seeds retrieved from the seed sequence aren't the same as the input data, but they're based on that data, so we can use that much random data in the sequence.

std::random_device r;
std::vector<std::uint_least32_t> data;
std::generate_n(back_inserter(data), 624, std::ref(r));

std::seed_seq seed(begin(data), end(data));

std::mt19937 engine(seed); // 'fully' seeded mt19937

Need Your Help

How to find LTFS Volume serial number instead of tape drive serial number

c# console-application wmi

I have an LTFS Tape mounted on my machine and I want to find its volume serial number programatically. I found that 'A00024' is that number by rightclick-->Properties-->LTFSDetails. I wrote a code to

Class cannot be cast to android.app.Fragment on FragmentActivity

android android-fragments

I'm getting the following error trying to start an activity with a Fragment

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.