【发布时间】:2015-09-07 23:42:09
【问题描述】:
我经常看到std::random_device 用于播种随机引擎。在 libstdc++ 中,如果硬件 RNG 可用,则默认使用 IA-32 RDRAND,否则 /dev/urandom。 libc++ 可以在arc4random()、/dev/urandom 和nacl_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 这与他(或她)想要在多个核心之间拆分运行的更常见情况完全不同。不同的问题有不同的解决方案……