目前,我在 Fortran 中有一个主要应用程序,需要一个种子来生成伪随机数。我想用完全不相关的种子(以及完全独立的伪随机数链)运行这个应用程序很多次。
我的问题是:如何使用 C++ 2011 生成种子?
/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
从数百个整数的序列中播种。
如果源可用, 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
您永远无法真正生成随机种子。你把它们从某个地方拉出来。操作系统可能有一种方法可以检索/dev/urandom
可用于播种的伪随机值(例如在 Linux 上)。
获取代表当前时间的时间戳也是一种常见的选择——然后为了确保您为每个线程获得不同的种子,只需确保它们在稍微不同的时间请求时间戳,并使用高分辨率计时器来确保它们实际得到不同的值作为种子。
C++11 中没有内置“获得好种子”功能,因为这样的功能本质上是没有意义的。计算机无法生成随机数据。您必须为您的目的选择看起来足够随机的东西,并使用它来为随机生成器提供种子