1

I often see std::random_device used to seed random engines. In libstdc++, it defaults to using IA-32 RDRAND if a hardware RNG is available, otherwise /dev/urandom. libc++ has choices between arc4random(), /dev/urandom and nacl_secure_random. Windows might use RtlGenRandom or the Crypt API.

Of course there are many more options:

Intel-specific:

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

PID:

getpid()

Thread ID:

std::this_thread::get_id()

Using chrono:

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

For libstdc++ this will not always be a nano-second resolution:

#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++ has a similar problem:

#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

Other options include a hash of compile metadata(__DATE__ __FILE__ __TIME__, as one string), the heap, a hash of address of standard library functions, of a function, of the this pointer, etc. Or some combination of all of them?

  • What is wrong with `std::random_device`? Just be careful when using MinGW, I think it always returns 0 there or sth. Probably fixed by now. – Baum mit Augen Sep 07 '15 at 23:43
  • could you tell more why do you need to seed RNG? – Severin Pappadeux Sep 07 '15 at 23:47
  • @Severin Pappadeux: Maybe, for some strange reason, he doesn't want to get the same sequence every time he runs the program? :) – Paul Groke Sep 07 '15 at 23:53
  • @PaulGroke That is quite different from more usual case when he (or she) wants to split the run between multiple cores. Different problems have different solutions... – Severin Pappadeux Sep 08 '15 at 00:15
  • You should expand on your requirements. e.g., there's not much point in a 'secure' seed if you're not using a CSPRNG. There's no point using timestamps if you want reproducible results. There's no point using anything with nano-second variation unless you're instancing millions of random engines per second. – Brett Hale Sep 08 '15 at 08:06
  • @Brett Hale: The reason for using nanosecond precision is not only to enable thousands/millions of instances per second but also to lower the predictability of the seed. Which can be more or less important, depending on the application. – Paul Groke Sep 08 '15 at 09:55
  • 3
    Possible duplicate of [How to succinctly, portably, and thoroughly seed the mt19937 PRNG?](https://stackoverflow.com/questions/45069219/how-to-succinctly-portably-and-thoroughly-seed-the-mt19937-prng) – Peter O. Aug 11 '17 at 19:22

2 Answers2

0

If you have access to std::random_device I would suggest you use it. If not, I'd suggest concatenating everything you listed into one big string and then computing a hash-code over that string. (At least everything you listed that's not redundant, i.e. it wouldn't make much sense to use both gettimeofday and std::chrono::high_resolution_clock::now.)

Paul Groke
  • 6,259
  • 2
  • 31
  • 32
0

How you should seed your RNG depends on your purpose.

The options you mention are not high entropy seeds, and aren't appropriate for use in applications where the quality of the randomness is very important. For instance in numerical experiments for scientific, or financial, purposes. Or for cryptographic purposes.

The purpose of std::random_device is to provide a cross-platform source of seeds that is appropriate for those kinds of applications. If you are just making a game or something, unless it is a hard core strategy game and you really care, you are surely fine just using srand(time(NULL)) and rand like people have been doing for at least 20 years.

Chris Beck
  • 15,614
  • 4
  • 51
  • 87