Faster Rand?
BlitzMax Forums/BlitzMax Programming/Faster Rand?
| ||
Is there a faster Rand function, or a faster way to get a random number between 2 given values? |
| ||
Why do you need faster random numbers? |
| ||
Make an array of random numbers? |
| ||
Deleted |
| ||
How slow is it then? |
| ||
Well if you look at the code Rand uses RndDouble. RndFloat is tighter if you can put up with the reduced precision and range. so for a random number between 3.0 to 5.0 r#=3.0+RndFloat()*2.0 |
| ||
Filling an Array with 50000 random numbers takes about one minute. Sorting it takes about 24 milliseconds... I need to fill this array to make some performance tests on a engine I'm developing. |
| ||
Try a Mersenne twister. |
| ||
Ziggy, are you using RAND (integer return) or RND (float/double) return? Filling an array with 50000 random numbers on my crappy laptop takes 12ms when using rnd so why would it take you a minute? rndfloat is twice as fast. Have you got any code which shows your '50000 random number array in 1 min' issue? |
| ||
Not here, but I'll post it. It is not an array of floats, it is an array of types containing two folats, each one of them with a different dand, so at the end it is to fill an array with 100,000 rands. I'm using rand(MinValue, MaxValue). Is it any faster use MinValue + Rnd()*(MaxValue-MinValue) ? |
| ||
Maybe you're more bound to the limits of the memory manager than to random number generation which usually is quite fast even using typical standard implementations. Shouldn't take more than 1-2 minutes to create a test on your machine creating 100.000 rands into a simple float/int array. |
| ||
First thing, RAND returns integers doesn't it? MinValue + Rnd()*(MaxValue-MinValue) was twice as fast on my system but... try it. It took me 6 ms to fill a 50000 float array using that method so I can't believe doing 100000 will take 10 times longer <edit> sorry 10,000 times longer - I think. My guess is this is going to be code specific. For some reason I think it's going to be GC related. |
| ||
Well, this really isn't like filling an array at all, when it comes to speed. You've got an array of objects with separate pointers to the fields for floats, so the 100,000 floats aren't going to be in a nice big hunk of contiguous memory like they would if they were actually in an array. I still find it hard to believe that that would make it an order of magnitude slower, but I suppose it's possible. |
| ||
Something like this? ? This takes 22ms as-is and 36 if I use standard rnd. It really is going to need some code to show us what you're doing though. |
| ||
There was a bottleneck in the objects creation algorithm that were filling the array. Now it takes 74 millisecons to fill the array with rand, and 58 using rnd(). Debug enabled. So it is solved. Thanks to everybody! |
| ||
Eureka. OK I'll stop worrying about my occasional use of Rand then :-) |
| ||
See? This is why I asked you why you needed faster random numbers. I figured you must be doing something wrong! :-) |
| ||
i posted this a time ago to bug-forum... but all people like this slow function and nothing happen... so my tip is: DO NOT USE THIS SLOW BBMAX-RAND FUNCTION instead just use gcc-rand-function http://www.blitzbasic.com/Community/posts.php?topic=65474#731786 See? This is why I asked you why you needed faster random numbers. I figured you must be doing something wrong! :-) why you need slow functions? |
| ||
Hi MrCreado, your crnd function is way faster. Thanks |
| ||
comparison? |
| ||
here:Extern "C" Function crand:Int () = "rand" End Extern Function fastrand:Int (start:Int, ende:Int) Return crand() Mod (ende-start+1) + start EndFunction Local i:Int = 0 Local F:Int Local M:Int = MilliSecs() For i = 0 To 1000000 f = fastrand(1,1000) Next Print "time to do fast rand: " + (MilliSecs()-M) M= MilliSecs() For i = 0 To 1000000 f = Rand(1,1000) Next Print "time to do rand: " + (MilliSecs()-M) in my computer: time to do fast rand: 126 time to do rand: 410 This sample code was posted by MrCredo in another thread, and it seems to be about four times faster |
| ||
wow. OK but is there a difference in the "Quality" of the random numbers? Of course it could be speeded up more by inlining the actual rand function. I wish BMax had the option to write INLINE after a function declaration... |
| ||
The only difference is that this fastrand function return a value between two integers, it is not using doubles. that's why it is faster (I think). I think this is a better test: Extern "C" Function _crand:Int () = "rand" End Extern Function IntRand:Int (start:Int, ende:Int) Return _crand() Mod (ende-start+1) + start EndFunction Local i:Int = 0 Local F:Int Local M:Int Local Time1:Int Local Time2:Int Print "Doing test on 10 cicles of 100,000 iterations" For Local K=1 To 10 M= MilliSecs() For i = 0 To 1000000 IntRand(1,1000) Next Time1 = MilliSecs()-M M= MilliSecs() For i = 0 To 1000000 Rand(1,1000) Next Time2 = MilliSecs()-M Print "time to do rand: " + Time2 + " IntRand: " + Time1 + " Speed improvement: " + Int(((time2-time1)/Double(time2)) * 100) + "%" Next Print "Done" The results on my machine are: Doing test on 10 cicles of 100,000 iterations time to do rand: 429 IntRand: 143 Speed improvement: 66% time to do rand: 433 IntRand: 138 Speed improvement: 68% time to do rand: 429 IntRand: 139 Speed improvement: 67% time to do rand: 431 IntRand: 143 Speed improvement: 66% time to do rand: 431 IntRand: 139 Speed improvement: 67% time to do rand: 432 IntRand: 137 Speed improvement: 68% time to do rand: 435 IntRand: 138 Speed improvement: 68% time to do rand: 431 IntRand: 139 Speed improvement: 67% time to do rand: 470 IntRand: 137 Speed improvement: 70% time to do rand: 432 IntRand: 139 Speed improvement: 67% Done |
| ||
buuuut, you can't use SeedRnd to change the numbers sequence. So it's not random at all. :S |
| ||
unless you add this to the source:Extern "C" Function crndseed:Int(val:Int) = "srand" Function _crand:Int () = "rand" End Extern Function FastRand:Int (start:Int, ende:Int) Return _crand() Mod (ende-start+1) + start EndFunction Adding this code, you can use the function cRndSeed(Value) to set the rand seed. Example: Extern "C" Function crndseed:Int(val:Int) = "srand" Function _crand:Int () = "rand" End Extern crndseed(MilliSecs()) Function FastRand:Int (start:Int, ende:Int) Return _crand() Mod (ende-start+1) + start EndFunction For Local i = 0 To 10 Print FastRand(1,10) Next run it several times to get different random numbers each time. |
| ||
well I'm gonna bookmark this one. |
| ||
Ziggy: What CPU do you have? On my core 2 Duo the differences appear even larger: a pretty solid 77%. (I had to increase the number of iterations though, the original finished way too quickly to have reliable comparisons) Doing test on 10 cicles of 10,000,000 iterations time to do rand: 792 IntRand: 177 Speed improvement: 77% time to do rand: 792 IntRand: 177 Speed improvement: 77% time to do rand: 791 IntRand: 179 Speed improvement: 77% time to do rand: 790 IntRand: 177 Speed improvement: 77% time to do rand: 791 IntRand: 178 Speed improvement: 77% time to do rand: 793 IntRand: 185 Speed improvement: 76% time to do rand: 793 IntRand: 177 Speed improvement: 77% time to do rand: 791 IntRand: 176 Speed improvement: 77% time to do rand: 791 IntRand: 176 Speed improvement: 77% time to do rand: 791 IntRand: 177 Speed improvement: 77% |
| ||
Yep, I just put this into the ZG BMax Framework. Awesome guys. |
| ||
I wish BMax had the option to write INLINE after a function declaration... well I'm gonna bookmark this one Yep. And yep |
| ||
time to do rand: 792 IntRand: 177 Speed improvement: 77% Actually... shouldn't that be a speed improvement of 440%? |
| ||
337% cos you got to take off the first 100%. e.g. 200 is a 100% increase on 100, not 200%. |
| ||
If you look to the source code, the percent is the time saving comparison. (Randtime - FastRandTime) / Randtime * 100 |