Skip to main content
GameDev.net gamedev.net
🔒 Locked

C++ rand on microtime?

Started by l0ki Aug 5, 2005 at 8:04 AM 15 replies 6k views
Original Post
l0ki
l0ki
Is there a way to srand() based on microtime? I have:

if(varMax > 0){
    srand(time(NULL));
    // calc a random variable set number between 0 and varMax.
    this->page[iCount]->m_varSet = ((rand() % varMax)+1);
}else{
}
However, this is in a program that can have new processes spawned with only a milliseconds difference in time, the problem is that m_varSet is always choosing the same number between multiple processes because of this time issue, so how does srand(time(NULL)) seed, seconds? TIA.
guyaton
guyaton
If you are using windows, you can use the high performance counter. First you have to see if you hardware supports it using this function then you can query it using this funtion.

hope this helps

~guyaton
~guyaton
l0ki
l0ki
Aye under Windows I know how to do it, unfortunately this is being dev'd on RHE4 linux, and the simple routes don't apply :D
FlowingOoze
FlowingOoze
What's your program doing? You probably won't get very good random numbers that way if you're concerned with each instance having different sequences.
If you're only using linux/unix why not read from /dev/random to seed srand()?
l0ki
l0ki
This process is a testing agent studying web site performance under stress, each of these is basically a user journey through a website. What I am choosing is a set of parameters to post to the server, but I want this to be different each time. However, because these processes are started within milliseconds of each other, the second count doesn't tick over and I'm seeing results based on the same sets chosen by rand() :(

I'm not sure what /dev/random is, I'll have to look into that, I'm new to linux programming. ta.
FlowingOoze
FlowingOoze
/dev/random is a device that produces an unlimited sequence of random values. You can read it like it was a file.
Inmate2993
Inmate2993
Don't re-seed Rand. Some randomizers have the significant flaw that when reseeded with sequential seeds, they report very similar sequences that take a lot of time to diverge. If this is beyond your control, store the last value rand reported and reseed with that, so you can continue the sequence.
william bubel
FlowingOoze
FlowingOoze
Quote:
Original post by Inmate2993
Don't re-seed Rand. ...

I though there might be something like that. Using /dev/random to seed srand seems like an elegant solution on linux/unix.
Fruny
Fruny
Alternatively, and since /dev/random blocks when it runs out of entropy, you can read all your random numbers from /dev/urandom.

You could even use the boost::random module of the Boost library - it has a bunch of different RNG algorithms, adaptors and can be seeded directly from a device file.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Agony
Agony
Quote:
Original post by l0ki
This process is a testing agent studying web site performance under stress, each of these is basically a user journey through a website. What I am choosing is a set of parameters to post to the server, but I want this to be different each time. However, because these processes are started within milliseconds of each other, the second count doesn't tick over and I'm seeing results based on the same sets chosen by rand() :(

So you have a process that creates new processes (fork, whatever, I'm a Windows guy), and each of these processes then seeds its own random sequence with the time? You could instead have the original process seed its random sequence, then pass a random number to each process that it creates that actually runs the journey through the website. Each process can take this number and use it (or a modified version of it) as the seed for their random sequence, rather than using the time. This would ensure that each one got a significantly different random number to use as a seed.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas nly, and not for things themselves." - John Locke o
Fruny
Fruny
One problem with that approach is that if that random number comes from rand(), all you have achieved is to seed the processes with slightly offset sequences.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
eyal
eyal
If you want to reseed the PRNG in each process, you can use the pid as part of the seed (xor'ed with the time, for example). This will ensure that different processes get different seeds.
Agony
Agony
Quote:
Original post by Fruny
One problem with that approach is that if that random number comes from rand(), all you have achieved is to seed the processes with slightly offset sequences.

Which is why I said "or a modified version of [what is returned from rand()]", such as inverting the bits, rotating them over 5 bits, and xoring them with a randomish constant. Or something weird. Wouldn't that effectively negate the offset-sequence phenomenon sufficiently for the non-rigorous use that is needed here?
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas nly, and not for things themselves." - John Locke o
ZQJ
ZQJ
As I understand it rand() is a pretty crappy random number generater anyway. So for something better try here and seed with anything that will be different in trial.
random_thinker
random_thinker
As a starting point for a fast random number generator, do a search for 'taus88' or 'tausme2'. Taus 88 (with period 2^88) is a very fast tausworth generator developed by L'ecuyer (Montreal) and is one of my favourites for general purpose variates. Get the paper 'tausme2.ps' as it contains the code and 'correct' initialization info. It is very fast; probably 40 to 50% faster than rand when optimized.

The mrg319 is another one from L'ecuyer but is slower than rand(); it appears to be the basis for L'ecuyer's own software. However, both of these have been through extensive testing for randomness. Also, Marsaglia and Tseng have produced some superb variate generators. An excellent reference with background can be found in 'Marsaglia, George, 'KISS random number generator', sci.math : The Math Forum, Jan 17, 2003.' This provides a very fast, extensively tested mwc with period 2^33242, as well as others. All of this stuff can be downloaded from the 'net. The Journal of Statistical Software is on the net and contains excellent information on derived variates.

For a serious random number system, you need to be able to save the seed state and reload it for a later run. It is sometimes necessary to repeat the stream exactly to check your results. Additionally, there is no such thing as a 'perfect' generator. Cryptology requires total randomness, so that the series of numbers can not be repeated regardless of the seed, whereas Monte Carlo requires 'repeatable randomness' if you know what I mean. I follow Knuth's advice; roughly that the best way to test a random number system is to repeat the run with different generators. Another source of good technology in this area is 'Numerical Recipes in C++", parts of which can be accessed on the net via Cambridge University. You may also want to look at the Mersenne Twister (Japan). It is a tgfsr with period 2^19000+ (I think) that it very popular in commercial apps, and is also very fast.

One of the more difficult tasks is to be able to repeat the number stream for all variates, base and derived, from a single seed. This includes normal, exponential, gamma, etc. You may find this a struggle, as some of the best algorithms do not 'process' base random numbers, but instead use other methods.

Be careful in the selection of generators from the net because there's a lot of rubbish out there that people still use. Be warned!

I really don't think that it matters what you use to seed your generator. I personally use rand() because it is easy to to set srand to time(0) as you have done. You can then save this value as the state and repeat the trial from there. I prefer to concentrate more on the best base integer generators instead for producing the stream.

Using /dev/random can be an option, but as was stated earlier this depends upon the entropy of the system and can have interrupts. I've never personally used it mainly because I do cross platform work and /dev/random is a Unix/Mac thing. I don't like to be tied down to platform-specific issues as I use three (WinXP/Linux/MacOSX) in my work, so my code has to be portable. However I do all my development on Gentoo.

Best of Luck!!

--random

--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
random_thinker
random_thinker
As a thought, if you need comnpletely distinct random processes, why not use 2 different generators, seed one and use it to seed instances of the other?

--random
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.