【问题标题】:How often should I reseed in C++?我应该多久在 C++ 中重新播种一次?
【发布时间】:2013-02-17 10:42:39
【问题描述】:

我只是想知道在程序开始时只播种一次随机数生成器是否足够。我编写使用随机数的函数。我从不在函数中播种 rand() 生成器,而是在主条目上保留调用 srand() 。例如。我的程序可能如下所示:

void func1()
{
    std::cout << "This is func1 " << std::rand() << std::endl;
}

void func2()
{
    std::cout << "This is func2 " << std::rand() << std::endl;
}

int main()
{
    std::srand(std::time(NULL));
    func1();
    func2();
    return 0;
}

通过这样做,我可以轻松地从主条目中关闭播种。它在调试程序时很有用 - 每次我运行程序而不播种时结果都保持不变。有时,如果由于某个随机数而出现问题,如果要生成一组不同的随机数,它可能就会消失,所以我更喜欢这种简单的机制来关闭种子。

但是,我注意到在 C++11 的新随机实用程序集中,随机数生成器必须在使用前进行实例化。 (例如 default_random_engine)。并且每次生成器都必须单独播种。我想知道是否真的鼓励在需要新生成器时重新植入生成器。我知道我可以创建一个全局随机生成器并像以前一样只播种一次,但我根本不喜欢使用全局变量的想法。否则,如果我创建一个本地随机数生成器,我将失去全局关闭种子以进行调试或任何目的的能力。

我很高兴学习 C++11 中的新功能,但有时它只是非常令人困惑。如果我对新的随机生成器有任何问题,谁能告诉我?或者 C++11 中的最佳实践是什么?

【问题讨论】:

  • 有一个全局种子函数,它返回当前时间或(在调试模式下)一个常量。

标签: c++ c++11


【解决方案1】:

这肯定取决于您正在开发的系统的总体目标,但一般来说,您只需在系统初始化时为需要随机数生成器 (RNG) 的任何系统播种一次。

在游戏开发中,每个系统(AI、程序内容生成器、粒子等)都有一个单独的 RNG 来隔离该系统以进行调试和维护是很常见的。

如果您存储种子,您还可以用很少的数据重放逻辑(只需要每帧的增量输入)。这不仅可以让您更轻松地调试应用程序,还可以让您支持用户的录制和回放功能。显然,如果您要创建重播模式,则需要在每次重播会话之前为系统提供每个系统的记录种子。

还有其他系统,例如密码学,您可能希望定期建立新种子。您可能希望随着时间的推移使种子过期,或者需要在每次与客户端应用程序握手时生成一个新种子。但是,您可能希望使用 Cryptography 库,因为它们可能比您自己开发的库更强大。

【讨论】:

  • 很棒的答案,非常全面。 +1
【解决方案2】:

随机数生成器 (RNG) 需要实例化的原因之一是它可以将其状态保持在内部,这样在多线程应用程序中,当多个线程使用相同的线程时就不会引入不确定性具有进程全局状态的 RNG。假设您有两个线程,每个线程都在处理问题的独立部分 - 如果状态(种子)对于 RNG 实例是私有的,那么当您使用已知值为每个线程的 RNG 播种时,您就可以获得确定性。另一方面,如果 RNG 将状态保存在全局变量中,那么每个线程观察到的随机数序列取决于它们对 RNG 的调用的交错 - 您现在已经引入了非确定性。

一种用于在多线程应用程序中分配工作的编程模式是thread pool。如果在池中排队等待工作线程执行的工作项需要一个 RNG,并且您希望每次运行都具有确定性,那么您希望每个线程在从排队

  • 这可以作为工作项初始化的一部分来完成
  • 种子可能涉及作业的 hash function 参数
  • 如果你对它的编码方式很小心,你可能会有伪随机性 和确定性,无论工作线程的数量或 他们从队列中拉出作业的顺序。

这是一个处理此问题的 SO 问题:Deterministic random number generator tied to instance (thread independent)

在单线程应用程序中,没有必要重新播种 RNG,实际上这是不可取的,因为这样做会缩短它开始重复之前的周期。 @MatthewSanders 指出的例外是密码学 - 在这种情况下,您需要最大熵(最小确定性),因为随机数被用作私钥。

【讨论】:

  • 非常感谢!看来我已经使用单线程应用程序太久了。现在我确信我希望为多线程应用程序单独保留随机数生成器。
猜你喜欢
  • 1970-01-01
  • 2014-07-07
  • 2019-09-27
  • 2012-11-16
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
相关资源
最近更新 更多