6

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

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

4

3 回答 3

7

/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...
}

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

于 2012-09-07T14:32:05.260 回答
6

如果源可用, C++11 提供std::random_device了非确定性随机数。你必须检查你的实现以确保它是好的。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);

}

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

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

八个 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
于 2012-09-07T17:50:26.170 回答
0

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

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

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

于 2012-09-07T14:39:03.433 回答