使用C ++ 2011的不相关的并行随机种子?

时间:2012-09-07 14:27:41

标签: c++ random c++11 seed

目前,我在Fortran中有一个主应用程序需要一个种子来生成伪随机数。 我想用完全不相关的种子(以及完全独立的伪随机数链)运行这个应用程序很多次(很多次)。

我的问题是:如何使用C ++ 2011生成种子?

3 个答案:

答案 0 :(得分:6)

在主线程中,从一个好的随机源(例如Linux上的/dev/urandom)中提取单个种子(或种子序列)。使用该数据为单个根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...
}

<random>中的随机数引擎接口允许您从单个整数和整数的序列中播种。如果您想要额外的随机性,可以从几百个整数的序列中播种mt19937

答案 1 :(得分:6)

如果源可用,则C ++ 11提供std::random_device以提供非确定性随机数。你必须检查你的实现,以确保它是好的。 libc ++默认使用/ dev / urandom。如果定义宏_GLIBCXX_USE_RANDOM_TR1,libstdc ++也会这样做。遗憾的是,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);

}

不使用单个值作为种子,一些引擎可能会使用更多的种子数据做得更好。种子序列是标准提供的替代方案。可以使用种子序列播种引擎,种子序列是您加载任意数据量的对象,并根据该数据生成种子数据。

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);
}

8个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

答案 2 :(得分:0)

你无法真正生成随机种子。你从某个地方拉它们。操作系统可能有办法检索伪随机值(例如Linux上的/dev/urandom),可以用来播种。

获取表示当前时间的时间戳也是一种常见的选择 - 然后为了确保为每个线程获得不同的种子,只需确保它们在稍微不同的时间要求时间戳,并使用高分辨率计时器来确保他们实际上得到了不同的价值作为种子。

C ++ 11中没有“获得良好的种子”功能,因为这样的功能基本上没有意义。计算机无法生成随机数据。您必须为您的目的选择看起来随机的东西,并使用它来播种随机生成器