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

How to properly initialize a C++11 std::seed_seq

本文关键字:seed seq std 何正确 初始化 c++      更新时间:2023-10-16

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

我看到有一个std::seed_seq类似乎是为了这个目的,但不清楚什么是正确的方式来构建一个。我所看到的示例,例如cppreference.com上的示例,使用程序中硬编码的一些整型常量对其进行初始化:

std::seed_seq seq{1,2,3,4,5};

我怀疑这实际上是推荐的最佳实践,所以我想知道是什么推荐的实践。特别是:

  • 既然seed_seq可以用任意数量的整数初始化,那么它的初始化列表的长度有什么意义?如果我想为100个随机生成器生成种子,我需要用100个整数初始化我的seed_seq吗?
  • 如果初始化列表的长度不必与我打算生成的种子数量相匹配,是否可以初始化仅一个整数的seed_seq,然后使用它来产生大量的种子?
  • 如何初始化整数,即使用默认构造函数?(当然,这意味着我每次都会得到相同的种子。)
  • 如果可以从单个整数构建seed_seq,然后从中生成大量种子,使用seed_seq而不是普通随机生成器的好处是什么?为什么不直接从单个整数构造一个std::mt19937,并使用为其他生成器生成种子值呢?

使用这样的固定序列的问题是,您从中得到相同的种子序列,就像您在程序开始时调用srand(42)一样:它生成相同的序列。

c++ 11标准声明(26.5.7.1 Class seed_seq节):

种子序列是一个对象,它使用整数值数据序列并产生请求的无符号整数值i, 0 i <232,基于消耗的数据。

[注:这样的对象提供了一种机制来避免随机变量流的复制。例如,在需要大量随机数引擎的应用程序中,这可能很有用。端注)

还在该节的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';
    }
}

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

std::seed_seq seq{time(0), valFromDevRandom(), getWhiteNoise(), avgMillis()};

但我怀疑常数是可行的方法,因为它们不会给方程增加随机性。

根据c++ 11标准(第26.5.7.1.8节),seed_seq可以生成一个可能由哈希函数生成的序列,在范围内均匀随机。

我试着回答以下问题:

Q1 "由于seed_seq可以用任意数量的整数初始化,那么它的初始化列表的长度有什么意义呢?如果我想为100个随机生成器生成种子,我是否需要用100个整数初始化我的seed_seq ?

A1。您不需要用大量整数初始化seed_seq。即使seed_seq由一个随机整数初始化,生成的序列仍然保持随机性。但是你用更多的整数初始化seed_seq,并且在更大的范围内,生成的序列更难以"碰撞"。袭击者。

Q2。如果初始化列表的长度不必与我打算生成的种子数量相匹配,那么是否可以用一个整数初始化seed_seq,然后使用它来生成大量的种子?

A2。是的,如果你不需要加密安全级别,用一个整数初始化seed_seq是可以的。

第三季。如何初始化不使用整数,即使用默认构造函数?(当然,这意味着我每次都会得到相同的种子。)"

A3。通过默认构造的seed_seq运行更多次,您将获得相同的序列。这将成为一个安全漏洞。

第四季度。如果可以从单个整数构造一个seed_seq,然后从中生成许多种子,那么使用seed_seq而不是普通的随机生成器有什么好处?为什么不直接从这个整数构造一个std::mt19937,并用它为其他生成器生成种子值呢?

A4。Seed_seq是一个轻量级算法,只迭代填充序列3次。我猜你可以使用其他随机生成器而不是seed_seq。