3

So normally I use something like:

srand(time(0));

To get pseudo-randomness that changes with every program invocation. However, I'm now in a situation where I have a batch of programs that will all be starting at the same time and since time only changes every second, most of the time all of my programs start with the same seed.

What is a better strategy for seeding my RNG when I want a bunch of programs to start at once and all get different seeds?

pjreddie
  • 390
  • 2
  • 10
  • Use a finer grain timer (ie system nanosecond counter) and mix it with the process id. Still not going to be good enough for security applications or Monte Carlo simulations. – Mark Lakata Apr 18 '14 at 03:39
  • 1
    use rdtsc http://stackoverflow.com/a/7617612/995714, it's the number of pseudo-cycles since the processor was powered on. If you need more assurance, xor it with PID – phuclv Apr 18 '14 at 04:14

3 Answers3

7

Use srand(time(0) ^ getpid()) to permute your seed by a process-specific value. This will ensure different seeds for processes started within the same second. Take care to not use this for anything "important", e.g., cryptography or real money is involved.

The permutation is accomplished using the "exclusive-or" or XOR operator '^'. Because we know that two process running at the same time must necessarily have different process-ids, by xoring the response from time(0) with the current PID, we can get some assurance that two different processes won't have exactly the same seed.

Note that this is a very weak assurance as we are only twiddling a few bits. If the time were to increment by exactly one second and the process id were to increment by exactly one, in certain circumstances you would end up with identical seeds.

If you need truly distinct random number seeds, then you want to read 4 bytes from /dev/random and then use that as an integer to seed your RNG.

And again, PLEASE do not use this random number sequence for anything "important". And by important I mean anything more than a simple monte-carlo simulation or a game of rock-paper-scissors.

caskey
  • 12,305
  • 2
  • 26
  • 27
  • Love it. Maybe go into more depth on how the XOR works to create a new distinct value. +1 – Brian Tracy Apr 18 '14 at 03:47
  • If you have a suitable library handy, you might want to use a secure hash function like SHA-1 to make your RNG seed out of the current time and the process ID number. If the RNG is really good this shouldn't matter I guess, but I'm a bit worried that the various PID values will only be a few bits apart. The secure hash functions really do a job of hashing things up, and even a single bit difference on input will result in a big difference on the output. This might be too time-consuming to use for every value of the RNG series, but just for the seed it likely should be okay. – steveha Apr 18 '14 at 04:34
  • 1
    Even if you use SHA-1 to generate your seed, you have no more entropy than the base calls to time() and getpid() and so it's a waste of effort to do anything more complicated. If OP is going to use srand/random then the best they can do is to pull their seed from /dev/random. – caskey Apr 18 '14 at 04:42
  • +1 for a reasonable and uncomplicated solution of `time(0) ^ getpid())`. It does has _some_ issues though as `gid` has some predictability to it and of course so does `time(0)`. Maybe if each program had its own random value conceived and fixed in the code: `time(0) ^ getpid() ^ my_program_mask`. I guess, at the end of the day, each program needs a call to a truly random source. – chux - Reinstate Monica Apr 18 '14 at 04:50
  • This is great. For my usage I actually just needed getpid() and could do away w/ the random number completely (I just needed a bit that flipped back and forth), but this is much more complete of an answer if anyone finds this in the future. – pjreddie Apr 18 '14 at 06:12
1

You can combine time(0) with some other program-specific value. For example, XOR it with a decent hash of the program name (argv[0] would normally suffice), or even just (preferably a hash of) the process id (if they're launched on the same host, otherwise XOR further with a hash of the hostname or IP). You could even go so far as to use a hash of an UUID.

Note: just xoring with the process id is pretty weak - if the second ticks over while the processes are starting, it could easily be that the bits flipped in the time value match the bits that differ between two of your process ids, leaving the generated seed identical. That said, put in an amount of effort commensurate with how much you have reason to care....

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
0

Maybe you need to use getpid() as well as some sub-second time (and perhaps whole second time too). Maybe make an MD5 hash of the values, and use that? Using getpid() guarantees that part of the data you're using will be unique to each process, but doesn't of itself give you very much randomness in your seed. Of course, using rand() is hardly guaranteed to be a good random number generator. You certainly can't use it for cryptography.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278