我应该如何播种随机引擎?

时间:2015-09-07 23:42:10

标签: c++ c++11 random

我经常看到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()

使用chrono:

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指针的等等。或者所有这些的组合?

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

如何种植RNG取决于您的目的。

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

std::random_device的目的是提供适用于这些类型应用程序的 的跨平台种子源。如果你只是制作游戏或其他东西,除非它是一个硬核策略游戏并且你非常关心,你肯定可以使用srand(time(NULL))rand就像人一样已经做了至少20年。