【问题标题】:How should I seed a random engine?我应该如何播种随机引擎?
【发布时间】:2015-09-07 23:42:09
【问题描述】:

我经常看到std::random_device 用于播种随机引擎。在 libstdc++ 中,如果硬件 RNG 可用,则默认使用 IA-32 RDRAND,否则 /dev/urandom。 libc++ 可以在arc4random()/dev/urandomnacl_secure_random 之间进行选择。 Windows 可能使用 RtlGenRandom 或 Crypt API。

当然还有更多选择:

英特尔专用:

__asm__ __volatile__ ("rdtsc" : "=a"(lo));

PID:

getpid()

线程 ID:

std::this_thread::get_id()

使用计时:

std::chrono::high_resolution_clock::now()
                        .time_since_epoch().count();

对于 libstdc++,这并不总是纳秒级分辨率:

#ifdef _GLIBCXX_USE_CLOCK_REALTIME
      timespec tp;
      // -EINVAL, -EFAULT
#ifdef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL
      syscall(SYS_clock_gettime, CLOCK_REALTIME, &tp);
#else
      clock_gettime(CLOCK_REALTIME, &tp);
#endif
      return time_point(duration(chrono::seconds(tp.tv_sec)
                 + chrono::nanoseconds(tp.tv_nsec)));
#elif defined(_GLIBCXX_USE_GETTIMEOFDAY)
      timeval tv;
      // EINVAL, EFAULT
      gettimeofday(&tv, 0);
      return time_point(duration(chrono::seconds(tv.tv_sec)
                 + chrono::microseconds(tv.tv_usec)));
#else
      std::time_t __sec = std::time(0);
      return system_clock::from_time_t(__sec);
#endif

libc++也有类似的问题:

#ifdef CLOCK_REALTIME
    struct timespec tp;
    if (0 != clock_gettime(CLOCK_REALTIME, &tp))
        __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
    return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
#else  // !CLOCK_REALTIME
    timeval tv;
    gettimeofday(&tv, 0); // :(
    return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
#endif  // CLOCK_REALTIME

其他选项包括编译元数据的散列(__DATE__ __FILE__ __TIME__,作为一个字符串)、堆、标准库函数地址的散列、函数的地址、this 指针的散列等。或者一些组合全部?

【问题讨论】:

  • std::random_device 有什么问题?使用 MinGW 时要小心,我认为它总是在那里返回 0 或某事。现在可能已经修复了。
  • 你能告诉更多为什么你需要为 RNG 做种吗?
  • @Severin Pappadeux:也许,出于某种奇怪的原因,他不想每次运行程序时都得到相同的序列? :)
  • @PaulGroke 这与他(或她)想要在多个核心之间拆分运行的更常见情况完全不同。不同的问题有不同的解决方案……

标签: c++ c++11 random


【解决方案1】:

如果您可以访问std::random_device,我建议您使用它。如果不是,我建议将您列出的所有内容连接成一个大字符串,然后在该字符串上计算哈希码。 (至少您列出的所有内容都不是多余的,即同时使用gettimeofday std::chrono::high_resolution_clock::now 没有多大意义。)

【讨论】:

    【解决方案2】:

    您应该如何播种 RNG 取决于您的目的。

    您提到的选项不是高熵种子,不适合在随机性质量非常重要的应用中使用。例如,用于科学或金融目的的数值实验。或用于加密目的。

    std::random_device 的目的是提供适合这些应用程序的跨平台种子源。如果您只是制作游戏或其他东西,除非它是一款硬核策略游戏并且您真的在意,否则您肯定可以像人们一直在做的那样使用 srand(time(NULL))rand至少 20 年。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-02
      • 1970-01-01
      • 2018-05-31
      • 2020-04-09
      • 2012-06-15
      • 1970-01-01
      • 1970-01-01
      • 2011-11-28
      相关资源
      最近更新 更多