如何正确初始化C++ 11 std :: seed_seq

Wyz*_*a-- 14 c++ random c++11

我有一个C++ 11程序需要创建几个独立的随机生成器,供并行计算中的不同线程使用.应使用不同的种子值初始化这些生成器,以便它们都产生不同的伪随机序列.

我看到有一个std::seed_seq类似乎是为了这个目的,但目前尚不清楚构建它的正确方法是什么.我见过的例子,比如cppreference.com上的例子,用一些在程序中硬编码的整数常量初始化它:

std::seed_seq seq{1,2,3,4,5};
Run Code Online (Sandbox Code Playgroud)

我怀疑这实际上是一个建议的最佳实践,所以我不知道什么推荐的做法.特别是:

  • 由于a seed_seq可以使用任意数量的整数进行初始化,因此初始化列表长度的重要性是什么?如果我想为100个随机生成器生成种子,我是否需要seed_seq使用100个整数初始化?
  • 如果初始化列表的长度不必与我想要生成的种子数相匹配,那么seed_seq只用一个整数初始化a 然后用它来生成大量种子就可以吗?
  • 如何初始化没有整数,即使用默认构造函数?(这意味着我每次都会得到相同的种子.)
  • 如果seed_seq从单个整数构造一个然后从中生成大量种子是可以的,那么使用seed_seq而不是普通的随机生成器有什么好处?为什么不直接std::mt19937从该单个整数构造一个并使用来为其他生成器生成种子值?

pax*_*blo 9

使用像这样的固定序列的麻烦在于,你从中得到了相同的种子序列,就像你srand(42)在程序开始时调用一样:它生成相同的序列.

C++ 11标准声明(部分26.5.7.1 Class seed_seq):

种子序列是消耗一系列整数值数据并基于所消耗的数据产生所请求数量的无符号整数值i,0 i <2 32的对象.

[注意:这样的对象提供了一种避免随机变量流复制的机制.例如,这在需要大量随机数引擎的应用中是有用的. - 尾注]

它还说明了如何将这些整数转换8为该部分段落中的种子,即使整数输入项非常相似,这些种子的分布也是可接受的.因此,您可以将其视为种子值的伪随机数生成器.

如果它们本身具有一些随机性,则更多数量的项将在种子值中提供更多"随机性".出于这个原因,使用常量作为输入是一个坏主意.

我倾向于做的非常类似于你通常随机选择台发电机的方式srand (time (0)).换一种说法:

#include <random>
#include <cstdint>
#include <ctime>
#include <iostream>

int main()
{
    std::seed_seq seq{time(0)};
    std::vector<std::uint32_t> seeds(10);
    seq.generate(seeds.begin(), seeds.end());
    for (std::uint32_t n : seeds) {
        std::cout << n << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您有多个随机源,例如从/dev/randomLinux下读取的值,或某些描述的白噪声发生器,或者上次用户运行此程序时按键之间的平均毫秒数,您可以将它们用作额外输入:

std::seed_seq seq{time(0), valFromDevRandom(), getWhiteNoise(), avgMillis()};
Run Code Online (Sandbox Code Playgroud)

但我怀疑常数是要走的路,因为它们不会增加等式.

  • 原因 (2) 使用“time(0)”被广泛认为是一种非常糟糕的 PRNG 种子方式。(3) 答案提到了 `\dev\random` 但没有提到 `std::random_device`。(4) 为什么只有四个随机值?为什么不是 624,即 `std::mt19937` 内部状态的大小? (2认同)