Faster Rand?

BlitzMax Forums/BlitzMax Programming/Faster Rand?

ziggy(Posted 2007) [#1]
Is there a faster Rand function, or a faster way to get a random number between 2 given values?


sswift(Posted 2007) [#2]
Why do you need faster random numbers?


Azathoth(Posted 2007) [#3]
Make an array of random numbers?


H&K(Posted 2007) [#4]
Deleted


Grey Alien(Posted 2007) [#5]
How slow is it then?


DJWoodgate(Posted 2007) [#6]
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


ziggy(Posted 2007) [#7]
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.


FlameDuck(Posted 2007) [#8]
Try a Mersenne twister.


tonyg(Posted 2007) [#9]
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?


ziggy(Posted 2007) [#10]
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) ?


Nelvin(Posted 2007) [#11]
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.


tonyg(Posted 2007) [#12]
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.


SculptureOfSoul(Posted 2007) [#13]
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.


tonyg(Posted 2007) [#14]
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.


ziggy(Posted 2007) [#15]
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!


Grey Alien(Posted 2007) [#16]
Eureka. OK I'll stop worrying about my occasional use of Rand then :-)


sswift(Posted 2007) [#17]
See? This is why I asked you why you needed faster random numbers. I figured you must be doing something wrong! :-)


MrCredo(Posted 2007) [#18]
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?


ziggy(Posted 2007) [#19]
Hi MrCreado, your crnd function is way faster. Thanks


Grey Alien(Posted 2007) [#20]
comparison?


ziggy(Posted 2007) [#21]
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


Grey Alien(Posted 2007) [#22]
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...


ziggy(Posted 2007) [#23]
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




BlackSp1der(Posted 2007) [#24]
buuuut, you can't use SeedRnd to change the numbers sequence. So it's not random at all. :S


ziggy(Posted 2007) [#25]
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.


Grey Alien(Posted 2007) [#26]
well I'm gonna bookmark this one.


xlsior(Posted 2007) [#27]
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%




Chroma(Posted 2007) [#28]
Yep, I just put this into the ZG BMax Framework. Awesome guys.


H&K(Posted 2007) [#29]
I wish BMax had the option to write INLINE after a function declaration...


well I'm gonna bookmark this one

Yep. And yep


xlsior(Posted 2007) [#30]
time to do rand: 792 IntRand: 177 Speed improvement: 77%


Actually... shouldn't that be a speed improvement of 440%?


Grey Alien(Posted 2007) [#31]
337% cos you got to take off the first 100%. e.g. 200 is a 100% increase on 100, not 200%.


ziggy(Posted 2007) [#32]
If you look to the source code, the percent is the time saving comparison. (Randtime - FastRandTime) / Randtime * 100