Better random numbers ?

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Better random numbers ?

A.J. Venter-2
Hi, I am using standard run of the mill randomize/random() calls in a program
to generate random numbers, used in turn to select random data which is fed
into another program.
(All this just to create a multi-language enabled module structure eh)

Well there is just one little problem, on the commandline it works fine, just
about every single call gives a different result, or different enough.

But when run from inside my other app (where it is threaded) and where I
cannot proceed until I have at least the first 5 non-repeating values, it
doesn't work so great, I have to call the program an average of 40 times
before the value changes - I presume because randomize gets it's seed from
the clock and that is how long it takes for the whichever value it uses to
update.

So is there a better way I can do this ? Some way of getting a more frequently
updated random seed ? I am talking literally every few milliseconds here.
--
A.J. Venter
Chief Software Architect
OpenLab International
www.getopenlab.com
www.silentcoder.co.za
+27 82 726 5103
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Michalis Kamburelis
A.J. Venter wrote:

> Hi, I am using standard run of the mill randomize/random() calls in a program
> to generate random numbers, used in turn to select random data which is fed
> into another program.
> (All this just to create a multi-language enabled module structure eh)
>
> Well there is just one little problem, on the commandline it works fine, just
> about every single call gives a different result, or different enough.
>
> But when run from inside my other app (where it is threaded) and where I
> cannot proceed until I have at least the first 5 non-repeating values, it
> doesn't work so great, I have to call the program an average of 40 times
> before the value changes - I presume because randomize gets it's seed from
> the clock and that is how long it takes for the whichever value it uses to
> update.
>
> So is there a better way I can do this ? Some way of getting a more frequently
> updated random seed ? I am talking literally every few milliseconds here.

I think that this problem is more-or-less unavoidable when you want to
really call Randomize/Random inside the program that is called very often.

The proper solution is to use some system-wide generator, that doesn't
have to be initialized every time you initialize your program. On Unix,
just read /dev/urandom, this should return pseudo-random numbers. On
Windows I guess that you will have to do something like that on your own
(e.g. write a program in FPC that runs as a service and can be queried
for random numbers). (Or you can use Cygwin routines to read Cygwin's
/dev/urandom --- never done it, but it should be possible).

Some other workaround that comes to my mind is to do something like
   Randomize;
   RandSeed := RandSeed * getpid;
This way you increase chances that your RandSeed is different for
different processes, since they will most probably get different
(usually successive) pids. Probably there is some equivalent to "getpid"
on Windows.

Hope this helps.

Michalis
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Jeff Miller
In reply to this post by A.J. Venter-2
> Hi, I am using standard run of the mill randomize/random() calls in a program
> to generate random numbers, used in turn to select random data which is fed
> into another program.

You are just supposed to call randomize once, to initialize the random
number generator.  You then call random over and over, and a different
random number gets generated from each successive call.  The random
call modifies the stored seed so that repeated calls give different answers.
I can see how this might not work so well when you are calling the
program over and over again (i.e., restarting it).

One option is to have the random # generator program generate a large
batch of numbers that are saved to a file, and you only call it again when
the calling program has used up that batch.  (If you are working in windows,
you might look at the randgen program, freely available at
http://www.winsite.com/bin/Info?17000000036826
which can be used like this.)

Another option is to have the random # generator program return its
new seed value as well as its random number.  When you call it again,
you pass it the seed value that it last returned, and the random #
generator program sets the seed to that value without calling randomize
again.

I hope something here useful to you...
Jeff

[hidden email]


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

A.J. Venter-2
In reply to this post by Michalis Kamburelis

> Some other workaround that comes to my mind is to do something like
>    Randomize;
>    RandSeed := RandSeed * getpid;
This worked, cut the initial generation time from about 30 seconds down to
under 1, of course right now it's NOT platform independent at all so I will
need to enhance it but I like the direction of your thinking, combining
randseed with some virtually guaranteed unique value solves the problem.

Ciao
A.J.

--
A.J. Venter
Chief Software Architect
OpenLab International
www.getopenlab.com
www.silentcoder.co.za
+27 82 726 5103
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Tomas Hajny
On 27 Feb 06, at 1:15, A.J. Venter wrote:

> > Some other workaround that comes to my mind is to do something like
> >    Randomize;
> >    RandSeed := RandSeed * getpid;
> This worked, cut the initial generation time from about 30 seconds down to
> under 1, of course right now it's NOT platform independent at all so I will
> need to enhance it but I like the direction of your thinking, combining
> randseed with some virtually guaranteed unique value solves the problem.

System.GetProcessID should be perfectly platform
independent.

HTH

Tomas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Vincent Snijders
In reply to this post by A.J. Venter-2
A.J. Venter wrote:
>>Some other workaround that comes to my mind is to do something like
>>   Randomize;
>>   RandSeed := RandSeed * getpid;
>
> This worked, cut the initial generation time from about 30 seconds down to
> under 1, of course right now it's NOT platform independent at all so I will
> need to enhance it but I like the direction of your thinking, combining
> randseed with some virtually guaranteed unique value solves the problem.

Maybe you use a global variable and just add one for each randseed call. After all
the only thing that matters for the randseed, is that it is different.

BTW, I never would have guessed that the random number generator would have used
threadvars. I would have thought, that on app start you would set one randseed and
then call random from all threads.

Vincent.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Jonas Maebe-2
In reply to this post by A.J. Venter-2

On 27 feb 2006, at 00:15, A.J. Venter wrote:

>>    Randomize;
>>    RandSeed := RandSeed * getpid;
> This worked, cut the initial generation time from about 30 seconds  
> down to
> under 1, of course right now it's NOT platform independent at all  
> so I will
> need to enhance it but I like the direction of your thinking,  
> combining
> randseed with some virtually guaranteed unique value solves the  
> problem.

It's not just that, but randseed is not a threadvar. This means that  
all your threads use the same randseed variable, so if two threads  
call "random" at the same time they will still get the same "random"  
number.


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Jonas Maebe-2
In reply to this post by Vincent Snijders

On 27 feb 2006, at 09:41, Vincent Snijders wrote:

>>> Some other workaround that comes to my mind is to do something like
>>>   Randomize;
>>>   RandSeed := RandSeed * getpid;
>> This worked, cut the initial generation time from about 30 seconds  
>> down to under 1, of course right now it's NOT platform independent  
>> at all so I will need to enhance it but I like the direction of  
>> your thinking, combining randseed with some virtually guaranteed  
>> unique value solves the problem.
>
> Maybe you use a global variable and just add one for each randseed  
> call. After all the only thing that matters for the randseed, is  
> that it is different.
>
> BTW, I never would have guessed that the random number generator  
> would have used threadvars.

It doesn't currently.

> I would have thought, that on app start you would set one randseed  
> and then call random from all threads.

Every time you call random, the current randseed is read, some  
calculations are performed and a new value is stored in the randseed  
variable. So if two threads call random "at the same time", then both  
will use the same randseed value and thus return the same random  
value (in the -current- case that randseed is not a threadvar).


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Vinzent Höfler
In reply to this post by Vincent Snijders
On Monday 27 February 2006 08:41, Vincent Snijders wrote:

> BTW, I never would have guessed that the random number generator
> would have used threadvars. I would have thought, that on app start
> you would set one randseed and then call random from all threads.

Considering that the state array for the Mersenne Twister is an
unprotected global variable, calling random from different threads
looks like a bad idea to me.

I mean, it surely gives you sort of random values, but ...


Vinzent.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Jonas Maebe-2

On 3 mrt 2006, at 13:42, Vinzent Hoefler wrote:

>> BTW, I never would have guessed that the random number generator
>> would have used threadvars. I would have thought, that on app start
>> you would set one randseed and then call random from all threads.
>
> Considering that the state array for the Mersenne Twister is an
> unprotected global variable, calling random from different threads
> looks like a bad idea to me.
>
> I mean, it surely gives you sort of random values, but ...

That's why its state (and indeed not just randseed) should be  
threadvars.


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Vincent Snijders
Jonas Maebe wrote:

>
> On 3 mrt 2006, at 13:42, Vinzent Hoefler wrote:
>
>>> BTW, I never would have guessed that the random number generator
>>> would have used threadvars. I would have thought, that on app start
>>> you would set one randseed and then call random from all threads.
>>
>>
>> Considering that the state array for the Mersenne Twister is an
>> unprotected global variable, calling random from different threads
>> looks like a bad idea to me.
>>
>> I mean, it surely gives you sort of random values, but ...
>
>
> That's why its state (and indeed not just randseed) should be  threadvars.

Or use some locking mechanism. That would be slower, but would safe some
memory.

Vincent
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Better random numbers ?

Vinzent Höfler
On Friday 03 March 2006 12:55, Vincent Snijders wrote:

> Jonas Maebe wrote:
> > On 3 mrt 2006, at 13:42, Vinzent Hoefler wrote:
> >>> BTW, I never would have guessed that the random number generator
> >>> would have used threadvars. I would have thought, that on app
> >>> start you would set one randseed and then call random from all
> >>> threads.
> >>
> >> Considering that the state array for the Mersenne Twister is an
> >> unprotected global variable, calling random from different threads
> >> looks like a bad idea to me.
> >>
> >> I mean, it surely gives you sort of random values, but ...
> >
> > That's why its state (and indeed not just randseed) should be
> > threadvars.
>
> Or use some locking mechanism. That would be slower, but would safe
> some memory.

I'd suggest both. :)

Objectify the whole Mersenne Twister into a single "class", so that each
thread can have it's own PRNG if necessary and provide a single global,
but locked instance of it for the System.Random subroutines.


Vinzent.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal