From: Stephen Hemminger <hidden> Date: 2004-08-12 17:49:00
While doing the network emulator, I discovered that the default net_random()
is too stupid, and get_random_bytes() is more than needed. Rather than put
another function in just for sch_netem, how about making net_random() smarter?
The tin-hat crowd already replace net_random() with get_random_bytes anyway.
Here is a proposed alternative to use a longer period PRNG for net_random().
The choice of TT800 was because it was freely available, had a long period,
was fast and relatively small footprint. The existing net_random() was not
really thread safe, but was immune to thread corruption.
Signed-off-by: Stephen Hemminger <redacted>
diff -Nru a/net/core/utils.c b/net/core/utils.c
@@ -34,8 +36,79 @@voidnet_srandom(unsignedlongentropy){net_rand_seed^=entropy;+net_random();+}+#else+/*+*ThisistheTT800twistedGlobalFiniteShiftRegisterrandomnumber+*generatororiginallybyM.Matsumoto,email:matumoto@math.keio.ac.jp.+*July8th1996Version+*+*See:ACMTransactionsonModellingandComputerSimulation,+*Vol.4,No.3,1994,pages254-266.+*+*Ithasalargeperiod2^800andgooddistributionproperties+*uptodimension25,andpassesstatisticaltests.+*+*Don'tuseforcryptographicpurposes,seeget_random_bytesinstead.+*/+#define N 25+#define M 7++staticunsignedlongnet_rand_seed[N]={+0x95f24dab,0x0b685215,0xe76ccae7,0xaf3ec239,0x715fad23,+0x24a590ad,0x69e4b5ef,0xbf456141,0x96bc1b7b,0xa7bdf825,+0xc1de75b7,0x8858a9c9,0x2da87693,0xb657f9dd,0xffdc8a9f,+0x8121da71,0x8b823ecb,0x885d05f5,0x4e20cd47,0x5a9ad5d9,+0x512c0c03,0xea857ccd,0x4cc1d30f,0x8891a8a1,0xa6b7aadb+};++staticspinlock_tnet_random_lock=SPIN_LOCK_UNLOCKED;++unsignedlongnet_random(void)+{+unsignedlongy;+unsignedlongflags;+staticintk;+staticconstunsignedlongmag01[2]={0x0,0x8ebfd028};+#define X net_rand_seed++/* generate N words at one time */+spin_lock_irqsave(&net_random_lock,flags);+if(k==N){+intkk;+for(kk=0;kk<N-M;kk++){+X[kk]=X[kk+M]^(X[kk]>>1)^mag01[X[kk]%2];+}++for(;kk<N;kk++){+X[kk]=X[kk+(M-N)]^(X[kk]>>1)^mag01[X[kk]%2];+}+k=0;+}++y=X[k];+y^=(y<<7)&0x2b5b2500;/* s and b, magic vectors */+y^=(y<<15)&0xdb8b0000;/* t and c, magic vectors */++/* +*thefollowinglinewasaddedbyMakotoMatsumotointhe1996version+*toimprovelowerbit'scorellation.+*Deletethislinetoousethecodepublishedin1994.+*/+y^=(y>>16);/* added to the 1994 version */+k++;+spin_unlock_irqrestore(&net_random_lock,flags);+#undef X+returny;+}++voidnet_srandom(unsignedlongentropy)+{+net_rand_seed[0]^=entropy;net_random();}+#endifintnet_msg_cost=5*HZ;intnet_msg_burst=10;
From: David S. Miller <hidden> Date: 2004-08-12 19:50:06
On Thu, 12 Aug 2004 10:48:35 -0700
Stephen Hemminger [off-list ref] wrote:
Here is a proposed alternative to use a longer period PRNG for net_random().
The choice of TT800 was because it was freely available, had a long period,
was fast and relatively small footprint. The existing net_random() was not
really thread safe, but was immune to thread corruption.
Any chance of a version that doesn't grab a global lock and
disable interrupts every call? :(
From: Ben Greear <hidden> Date: 2004-08-12 20:02:35
Stephen Hemminger wrote:
While doing the network emulator, I discovered that the default net_random()
is too stupid, and get_random_bytes() is more than needed. Rather than put
another function in just for sch_netem, how about making net_random() smarter?
The tin-hat crowd already replace net_random() with get_random_bytes anyway.
Here is a proposed alternative to use a longer period PRNG for net_random().
The choice of TT800 was because it was freely available, had a long period,
was fast and relatively small footprint. The existing net_random() was not
really thread safe, but was immune to thread corruption.
Is it really worth the extra spin lock & math? Maybe we could have a
net_more_random() method instead that encompasses this improved random logic?
Ben
--
Ben Greear [off-list ref]
Candela Technologies Inc http://www.candelatech.com
From: Stephen Hemminger <hidden> Date: 2004-08-13 18:52:16
Here is another alternative, using tansworthe generator. It uses percpu
state. The one small semantic change is the net_srandom() only affects
the current cpu's seed. The problem was that having it change all cpu's
seed would mean adding locking and the only user's today are a couple of
places that feed in mac address to try make sure address resolution to
collide.
diff -Nru a/include/linux/net.h b/include/linux/net.h
On Fri, 13 Aug 2004 11:51:40 -0700
Stephen Hemminger [off-list ref] wrote:
Here is another alternative, using tansworthe generator. It uses percpu
state. The one small semantic change is the net_srandom() only affects
the current cpu's seed. The problem was that having it change all cpu's
seed would mean adding locking
I would just update the other CPUs without locking. Taking
a random number from a partially updated state shouldn't be a big
issue.
-Andi
From: David S. Miller <hidden> Date: 2004-08-16 06:30:21
On Fri, 13 Aug 2004 21:28:57 +0200
Andi Kleen [off-list ref] wrote:
On Fri, 13 Aug 2004 11:51:40 -0700
Stephen Hemminger [off-list ref] wrote:
quoted
Here is another alternative, using tansworthe generator. It uses percpu
state. The one small semantic change is the net_srandom() only affects
the current cpu's seed. The problem was that having it change all cpu's
seed would mean adding locking
I would just update the other CPUs without locking. Taking
a random number from a partially updated state shouldn't be a big
issue.
I personally don't think we need to touch the other cpus
at all, and that having a different current seed on each
cpu might actually be a good thing.
Stephen, I like this one a lot, especially compared to
what we had before. I'm going to add this to my tree for
the time being.
Is there a reason why get_random_bytes() is unsuitable?
Keeping the number of PRNGs in the kernel to a minimum should a goal we can
all share.
JLC
On Thu, Aug 12, 2004 at 10:48:35AM -0700, Stephen Hemminger wrote:
quoted hunk
While doing the network emulator, I discovered that the default net_random()
is too stupid, and get_random_bytes() is more than needed. Rather than put
another function in just for sch_netem, how about making net_random() smarter?
The tin-hat crowd already replace net_random() with get_random_bytes anyway.
Here is a proposed alternative to use a longer period PRNG for net_random().
The choice of TT800 was because it was freely available, had a long period,
was fast and relatively small footprint. The existing net_random() was not
really thread safe, but was immune to thread corruption.
Signed-off-by: Stephen Hemminger <redacted>
diff -Nru a/net/core/utils.c b/net/core/utils.c
@@ -34,8 +36,79 @@voidnet_srandom(unsignedlongentropy){net_rand_seed^=entropy;+net_random();+}+#else+/*+*ThisistheTT800twistedGlobalFiniteShiftRegisterrandomnumber+*generatororiginallybyM.Matsumoto,email:matumoto@math.keio.ac.jp.+*July8th1996Version+*+*See:ACMTransactionsonModellingandComputerSimulation,+*Vol.4,No.3,1994,pages254-266.+*+*Ithasalargeperiod2^800andgooddistributionproperties+*uptodimension25,andpassesstatisticaltests.+*+*Don'tuseforcryptographicpurposes,seeget_random_bytesinstead.+*/+#define N 25+#define M 7++staticunsignedlongnet_rand_seed[N]={+0x95f24dab,0x0b685215,0xe76ccae7,0xaf3ec239,0x715fad23,+0x24a590ad,0x69e4b5ef,0xbf456141,0x96bc1b7b,0xa7bdf825,+0xc1de75b7,0x8858a9c9,0x2da87693,0xb657f9dd,0xffdc8a9f,+0x8121da71,0x8b823ecb,0x885d05f5,0x4e20cd47,0x5a9ad5d9,+0x512c0c03,0xea857ccd,0x4cc1d30f,0x8891a8a1,0xa6b7aadb+};++staticspinlock_tnet_random_lock=SPIN_LOCK_UNLOCKED;++unsignedlongnet_random(void)+{+unsignedlongy;+unsignedlongflags;+staticintk;+staticconstunsignedlongmag01[2]={0x0,0x8ebfd028};+#define X net_rand_seed++/* generate N words at one time */+spin_lock_irqsave(&net_random_lock,flags);+if(k==N){+intkk;+for(kk=0;kk<N-M;kk++){+X[kk]=X[kk+M]^(X[kk]>>1)^mag01[X[kk]%2];+}++for(;kk<N;kk++){+X[kk]=X[kk+(M-N)]^(X[kk]>>1)^mag01[X[kk]%2];+}+k=0;+}++y=X[k];+y^=(y<<7)&0x2b5b2500;/* s and b, magic vectors */+y^=(y<<15)&0xdb8b0000;/* t and c, magic vectors */++/* +*thefollowinglinewasaddedbyMakotoMatsumotointhe1996version+*toimprovelowerbit'scorellation.+*Deletethislinetoousethecodepublishedin1994.+*/+y^=(y>>16);/* added to the 1994 version */+k++;+spin_unlock_irqrestore(&net_random_lock,flags);+#undef X+returny;+}++voidnet_srandom(unsignedlongentropy)+{+net_rand_seed[0]^=entropy;net_random();}+#endifintnet_msg_cost=5*HZ;intnet_msg_burst=10;-
From: Andreas Dilger <hidden> Date: 2004-08-20 19:07:00
On Aug 20, 2004 13:59 -0400, Jean-Luc Cooke wrote:
Is there a reason why get_random_bytes() is unsuitable?
Keeping the number of PRNGs in the kernel to a minimum should a goal we can
all share.
For some uses a decent PRNG is enough, and the overhead of get_random_bytes()
is much too high. We've needed something like this for a long time (something
that gives decenly uniform numbers) and hacks to use useconds/cycles/etc do
not cut it. I for one welcome a simple in-kernel interface to
e.g. get_urandom_bytes() (or net_random() as this is maybe inappropriately
called) that is only pseudo-random but fast and efficient.
Cheers, Andreas
--
Andreas Dilger
http://sourceforge.net/projects/ext2resize/http://members.shaw.ca/adilger/http://members.shaw.ca/golinux/
From: Richard B. Johnson <hidden> Date: 2004-08-20 19:22:57
On Fri, 20 Aug 2004, Andreas Dilger wrote:
On Aug 20, 2004 13:59 -0400, Jean-Luc Cooke wrote:
quoted
Is there a reason why get_random_bytes() is unsuitable?
Keeping the number of PRNGs in the kernel to a minimum should a goal we can
all share.
For some uses a decent PRNG is enough, and the overhead of get_random_bytes()
is much too high. We've needed something like this for a long time (something
that gives decenly uniform numbers) and hacks to use useconds/cycles/etc do
not cut it. I for one welcome a simple in-kernel interface to
e.g. get_urandom_bytes() (or net_random() as this is maybe inappropriately
called) that is only pseudo-random but fast and efficient.
Cheers, Andreas
--
Andreas Dilger
The attached code will certainly work on Intel machines. It is
in the public domain, having been modified by myself to produce
a very long sequence...
I wouldn't suggest converting it to 'C' because the rotation
takes many CPU instructions when one tries to do the test, shift,
and OR in 'C',
Cheers,
Dick Johnson
Penguin : Linux version 2.4.26 on an i686 machine (5570.56 BogoMips).
Note 96.31% of all statistics are fiction.
If speed is what you want, and you want a period > 2^N.
Then a single get_rand_bytes() to fill a seed of a simple LFSR might do.
Seed value will be N+1 bits long.
Rochard's PRNG does not have a period > 2^32, that's for sure.
JLC
On Fri, Aug 20, 2004 at 12:48:23PM -0700, David S. Miller wrote:
On Fri, 20 Aug 2004 15:22:09 -0400 (EDT)
"Richard B. Johnson" [off-list ref] wrote:
quoted
The attached code will certainly work on Intel machines. It is
in the public domain, having been modified by myself to produce
a very long sequence...
How long a period does it have? The one we're adding to the
networking has one which is 2^88.
quoted
I wouldn't suggest converting it to 'C' because the rotation
takes many CPU instructions when one tries to do the test, shift,
and OR in 'C',
You only need 2 'shifts' and an 'or' to do a rotate in C.
No tests are needed.
From: Lee Revell <hidden> Date: 2004-08-20 21:24:19
On Fri, 2004-08-20 at 14:59, Andreas Dilger wrote:
On Aug 20, 2004 13:59 -0400, Jean-Luc Cooke wrote:
quoted
Is there a reason why get_random_bytes() is unsuitable?
Keeping the number of PRNGs in the kernel to a minimum should a goal we can
all share.
For some uses a decent PRNG is enough, and the overhead of get_random_bytes()
is much too high.
Agreed. I have numbers to support the above.
We've needed something like this for a long time (something
that gives decenly uniform numbers) and hacks to use useconds/cycles/etc do
not cut it. I for one welcome a simple in-kernel interface to
e.g. get_urandom_bytes() (or net_random() as this is maybe inappropriately
called) that is only pseudo-random but fast and efficient.
One problem is that AIUI, we incur this overhead even if a hardware RNG
is present. This does not seem right. Hardware RNGs are increasingly
common, Linux supports hardware RNGs from AMD, Intel, and VIA.
Lee
One problem is that AIUI, we incur this overhead even if a hardware RNG
is present. This does not seem right. Hardware RNGs are increasingly
common, Linux supports hardware RNGs from AMD, Intel, and VIA.
Hardware RNG's are actually fairly slow and thus are better as sources
to perturb a PRNG.
From: Stephen Hemminger <hidden> Date: 2004-08-23 17:07:08
The attached code will certainly work on Intel machines. It is
in the public domain, having been modified by myself to produce
a very long sequence...
I wouldn't suggest converting it to 'C' because the rotation
takes many CPU instructions when one tries to do the test, shift,
and OR in 'C',
Cheers,
Dick Johnson
Penguin : Linux version 2.4.26 on an i686 machine (5570.56 BogoMips).
Note 96.31% of all statistics are fiction.
My choice of PRNG was not random. I am not a mathematician (IANAM),
but what I was looking for was:
+ well researched
+ fast
+ good distribution
+ small seed (since per cpu)
+ Free and open
The second version uses tausworthe because it was the fastest in the GNU scientific
library and had good properties.
See:
http://www1.physik.tu-muenchen.de/~gammel/matpack/html/LibDoc/Numbers/Random.html
----------
Returns integer pseudorandom numbers uniformly distributed within [0,4294967295].
The period length is approximately 288 (which is 3*1026).
This is Pierre L'Ecuyer's 1996 three-component Tausworthe generator "taus88"
This generator is very fast and passes all standard statistical tests.
P. L'Ecuyer, Maximally equidistributed combined Tausworthe generators, Mathematics of Computation 65, 203-213 (1996), see Figure 4.
P. L'Ecuyer, Random number generation, chapter 4 of the Handbook on Simulation, Ed. Jerry Banks, Wiley, 1997.
--------
http://www.gnu.org/software/gsl/manual/gsl-ref_17.html
Performance
The following table shows the relative performance of a selection the available random number generators. The fastest simulation quality generators are taus, gfsr4 and mt19937. The generators which offer the best mathematically-proven quality are those based on the RANLUX algorithm.
1754 k ints/sec, 870 k doubles/sec, taus
1613 k ints/sec, 855 k doubles/sec, gfsr4
1370 k ints/sec, 769 k doubles/sec, mt19937
565 k ints/sec, 571 k doubles/sec, ranlxs0
400 k ints/sec, 405 k doubles/sec, ranlxs1
490 k ints/sec, 389 k doubles/sec, mrg
407 k ints/sec, 297 k doubles/sec, ranlux
243 k ints/sec, 254 k doubles/sec, ranlxd1
251 k ints/sec, 253 k doubles/sec, ranlxs2
238 k ints/sec, 215 k doubles/sec, cmrg
247 k ints/sec, 198 k doubles/sec, ranlux389
141 k ints/sec, 140 k doubles/sec, ranlxd2
1852 k ints/sec, 935 k doubles/sec, ran3
813 k ints/sec, 575 k doubles/sec, ran0
787 k ints/sec, 476 k doubles/sec, ran1
379 k ints/sec, 292 k doubles/sec, ran2
From: Richard B. Johnson <hidden> Date: 2004-08-23 18:10:36
On Mon, 23 Aug 2004, Stephen Hemminger wrote:
quoted
The attached code will certainly work on Intel machines. It is
in the public domain, having been modified by myself to produce
a very long sequence...
I wouldn't suggest converting it to 'C' because the rotation
takes many CPU instructions when one tries to do the test, shift,
and OR in 'C',
My choice of PRNG was not random. I am not a mathematician (IANAM),
but what I was looking for was:
+ well researched
+ fast
+ good distribution
+ small seed (since per cpu)
+ Free and open
The second version uses tausworthe because it was the fastest in the GNU scientific
library and had good properties.
See:
http://www1.physik.tu-muenchen.de/~gammel/matpack/html/LibDoc/Numbers/Random.html
----------
Returns integer pseudorandom numbers uniformly distributed within [0,4294967295].
The period length is approximately 288 (which is 3*1026).
This is Pierre L'Ecuyer's 1996 three-component Tausworthe generator "taus88"
This generator is very fast and passes all standard statistical tests.
P. L'Ecuyer, Maximally equidistributed combined Tausworthe generators, Mathematics of Computation 65, 203-213 (1996), see Figure 4.
P. L'Ecuyer, Random number generation, chapter 4 of the Handbook on Simulation, Ed. Jerry Banks, Wiley, 1997.
--------
http://www.gnu.org/software/gsl/manual/gsl-ref_17.html
Performance
The following table shows the relative performance of a selection the available random number generators. The fastest simulation quality generators are taus, gfsr4 and mt19937. The generators which offer the best mathematically-proven quality are those based on the RANLUX algorithm.
1754 k ints/sec, 870 k doubles/sec, taus
1613 k ints/sec, 855 k doubles/sec, gfsr4
1370 k ints/sec, 769 k doubles/sec, mt19937
565 k ints/sec, 571 k doubles/sec, ranlxs0
400 k ints/sec, 405 k doubles/sec, ranlxs1
490 k ints/sec, 389 k doubles/sec, mrg
407 k ints/sec, 297 k doubles/sec, ranlux
243 k ints/sec, 254 k doubles/sec, ranlxd1
251 k ints/sec, 253 k doubles/sec, ranlxs2
238 k ints/sec, 215 k doubles/sec, cmrg
247 k ints/sec, 198 k doubles/sec, ranlux389
141 k ints/sec, 140 k doubles/sec, ranlxd2
1852 k ints/sec, 935 k doubles/sec, ran3
813 k ints/sec, 575 k doubles/sec, ran0
787 k ints/sec, 476 k doubles/sec, ran1
379 k ints/sec, 292 k doubles/sec, ran2
The rnd that I submitted is fast. That's all. For communications
it has been found to be good enough. Remember the saying; "Better
is the enemy of good enough". It obviously can't have a period
of better than 2^32 and, in fact, it has a period of:
4294896635 [0xfffeebfb].
This generates 199,962,632 integers per second on this 2.8 GHz machine.
This is a callable procedure that uses a pointer to private
data. The speed could be improved if this overhead is not required.
The distribution has also been found to be good enough for spread-
spectrum use. There are no missing codes although a sorted-
list of return values will show that there are some values (codes)
that are generated close together, in other words some people
expect that if you get a return code of '1', the next one won't
be '2', but something "very far away". This generator seems
to work more like "real world" noise sources except that such
noise sources may give you duplicate values, which this won't.
Depending upon how much time you wish to waste for making it
better than "good enough", this can be cascaded to give a
period of any length (you use one generator to produce the
"magic number" for another, etc.)
Cheers,
Dick Johnson
Penguin : Linux version 2.4.26 on an i686 machine (5570.56 BogoMips).
Note 96.31% of all statistics are fiction.