在主线程中,从一个好的随机源(例如从/dev/urandom
Linux上)中提取单个种子(或种子序列).使用该数据为单个根PRNG播种.然后使用该 PRNG为线程本地PRNG生成种子值.
#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...
}
Run Code Online (Sandbox Code Playgroud)
随机数引擎接口<random>
允许您从单个整数和整数序列中播种.如果你想要额外的随机性,你可以mt19937
从几百个整数的序列中播种.
std::random_device
如果源可用,C++ 11 提供非确定性随机数.你必须检查你的实现,以确保它是好的.libc ++默认使用/ dev/urandom.libstdc ++也_GLIBCXX_USE_RANDOM_TR1
可以定义宏.遗憾的是,Visual Studio的实现并不是非确定性的.编辑:从VS2012开始,他们的实现使用Windows的加密服务.
如果std::random_device
提供对非确定性随机源的访问(通常/ dev/urandom使用加密PRNG),那么这应该足以生成独立种子.
#include <random>
int main() {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 engine(seed);
}
Run Code Online (Sandbox Code Playgroud)
一些引擎可以使用更多种子数据做得更好,而不是使用单个值作为种子.种子序列是标准提供的替代方案.可以使用种子序列播种引擎,种子序列是您使用任意数量的数据加载的对象,并基于此生成种子数据.
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);
}
Run Code Online (Sandbox Code Playgroud)
八个32位值,256位,就足够了,但如果你真的想要,你可以使用更多.每个标准引擎都记录了它从种子序列中使用了多少数据.
例如,每个mt19937引擎将从mt19937::state_size
种子序列中检索(624)32位值.从种子序列中检索的种子与输入数据不同,但它们基于该数据,因此我们可以在序列中使用那么多随机数据.
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
Run Code Online (Sandbox Code Playgroud)