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