FreeBASIC's PRNG #2
-
- Posts: 4315
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: FreeBASIC's PRNG #2
I have not looked at this before but the '-multithreaded' switch will give your machine a good 'workout'. For the hell of it, I ran two instances of PractRand with that switch and saw my CPU usage averaging 80% on my 8 thread Intel i7. I think that I will just pop down to the shops and get an Intel® Core™ i9-7980XE; that has 36 threads. It may be wise to have a word with my bank manager first though. <smile>
Re: FreeBASIC's PRNG #2
Thanks, David. The '-multithreaded' option does speed things up, but certainly, I can't expect any miracles here =Ddeltarho[1859] wrote:Hi Paul. I use a very simple command line for PractRand.
<whatever.exe> | rng_test stdin32 -multithreaded
where <whatever.exe> is the name of the piping program.
On a side note if a test fails at PractRand's first hurdle then try
<whatever.exe> | rng_test stdin32 -tlmin 1KB -multithreaded
This will start PractRand at 1KB. I had to do this for the LCG tests which were failing at 4KB or 8KB.
On my machine the '-multithreaded' switch sees PractRand run about 25% faster.
This a simple stub of the code I'm using:
Code: Select all
dim shared as ulongint x = 12, w = 0, s = &h8b5ad4cef9c2703b
function msws() as ulong
x *= x
w += s
x += w
x = ( x shr 32 ) or ( x shl 32 )
return( x )
end function
/'
Main code
'/
dim as string cmd = "RNG_test stdin -multithreaded"
dim as long fileHandle = freeFile()
open pipe cmd for binary access write as fileHandle
do
put #fileHandle, , msws()
loop until( inkey() <> "" )
close( fileHandle )
It's a pity that FreeBasic doesn't support bi-directional piping directly. You can implement it using the OS features, or another, higher level program that pipes the testing code in one direction, and the PractRand instance in another.
Re: FreeBASIC's PRNG #2
Just to let you know. He uses this C code:deltarho[1859] wrote:I don't know exactly how Bernard Widynski created his seed.h ...
Code: Select all
/**************************************************************************\
* *
* create seed.h include file *
* *
* seed.h contains random and distinct seed values. These seeds can be *
* used for stream initialization. The streams will be different and *
* random at the very beginning. *
* *
* The seeds are chosen so that every nibble is different. This prevents *
* regularities that occur at the very beginning when the nibbles repeat. *
* For example, with a seed of all fs, i.e. 0xffffffffffffffff, even *
* though this passes BigCrush, the data appears non-random for the first *
* 10 iterations. A seed of mostly 0s, e.g. 0x0000000100000001, also *
* passes BigCrush, but the data also appears non-random for the first *
* 10 iterations. Good data at the very beginning can be obtained if the *
* nibbles are all different. Seeds of this type are generated by this *
* program. *
* *
* Two arrays are malloced: x and y. The x array is used to set the upper*
* 32 bits of the seed. The y array is used to to set the lower 32 bits *
* of the seed. The msws rng is called to generate random data to fill *
* these arrays. Each nibble is checked to be different. Prior to adding*
* an element a 2^32 bit map is used to verify that it has not been added *
* previously. This assures distinct data in the x and y arrays. These *
* arrays are printed into seed.h. The seed.h file may be used as follows:*
* *
* uint64_t seed[] = { *
* #include "seed.h" *
* }; *
* *
* x = 0; w = 0; s = seed[i]; *
* *
* See streams_example for example usage. *
* *
\**************************************************************************/
#include "msws.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define N 25000
#define two32 4294967296
#define nbytes two32/8
#define nwords two32/32
int main () {
FILE *fp;
uint32_t a, *b, c, i, j, k, m, n, *x, *y;
/* malloc x and y arrays */
x = (uint32_t *) malloc(N*4);
if (x == NULL) {
printf("malloc error\n");
return 1;
}
y = (uint32_t *) malloc(N*4);
if (y == NULL) {
printf("malloc error\n");
return 1;
}
/* malloc bit map array */
b = (uint32_t *) malloc(nbytes);
if (b == NULL) {
printf("malloc error \n");
return 1;
}
/* zero bit map */
for (i=0;i<nwords;i++) {
b[i] = 0;
}
/* create random x[N] */
for (n=0;n<N;n++) {
for (;;) {
for (m=0,a=0,c=0;m<32;) {
j = msws(); /* get 32-bit random word */
for (i=0;i<32;i+=4) {
k = (j>>i) & 0xf; /* get a nibble */
if ((c & (1<<k)) == 0) { /* verify not used previously */
c |= (1<<k);
a |= (k<<m); /* add nibble to output */
m += 4;
if (m>=32) break;
}
}
}
i = a / 32; j = a % 32; /* verify distinct data */
if ((b[i] & (1<<j)) == 0) {
b[i] |= (1<<j);
x[n] = a;
break;
}
}
}
/* zero bit map */
for (i=0;i<nwords;i++) {
b[i] = 0;
}
/* create random y[N] */
for (n=0;n<N;n++) {
for (;;) {
for (m=0,a=0,c=0;m<32;) {
j = msws(); /* get 32-bit random word */
for (i=0;i<32;i+=4) {
k = (j>>i) & 0xf; /* get a nibble */
if ((c & (1<<k)) == 0) { /* verify not used previously */
c |= (1<<k);
a |= (k<<m); /* add nibble to output */
m += 4;
if (m>=32) break;
}
}
}
a |= 1; /* set least significant bit to 1 */
i = a / 32; j = a % 32; /* verify distinct data */
if ((b[i] & (1<<j)) == 0) {
b[i] |= (1<<j);
y[n] = a;
break;
}
}
}
/* create seed.h include file */
fp = fopen("seed.h","w");
if (fp == NULL) {
printf("unable to open seed.h\n");
return 1;
}
for (i=0;i<N;i++) {
fprintf(fp,"0x%8.8x%8.8x,\n",x[i],y[i]);
}
fclose(fp);
return 0;
}
-
- Posts: 4315
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: FreeBASIC's PRNG #2
No thanks, Paul, I'll stick with the 64_bit prime.paul doe wrote:I can port it if you're interested in studying it =D
BTW, use stdin32 and not stdin which will do a 32-bit analysis as opposed an 8-bit analysis.
-
- Posts: 4315
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: FreeBASIC's PRNG #2
I have no idea if this would make any difference but I use the following. It pipes a 1MB string.
Code: Select all
Dim Shared S As String * 1048576
Dim As Ulong Ptr SPtr, BasePtr
Dim As Long j
SPtr = Cptr(Ulong Ptr, StrPtr( S ))
BasePtr = SPtr
Do
For j = 1 to 262144
*SPtr = randomNumber.one()
SPtr += 1
Next
Print S;
SPtr = BasePtr
Loop
Re: FreeBASIC's PRNG #2
Oooh good to know, thanks =Ddeltarho[1859] wrote:BTW, use stdin32 and not stdin which will do a 32-bit analysis as opposed an 8-bit analysis.
From a functionality standpoint, no. However, opening a pipe with 'open pipe' offers you the advantage of simply invoking PractRand from inside your code, so you can quickly test several algorithms in a row ie. you don't need to compile your code and go to the command line to invoke PractRand.deltarho[1859] wrote:I have no idea if this would make any difference...
You could create code that, say, pipes PCG32, MSWS and any/all other algorithm of your choice, pass them to the ChiSquared test, ENT, BigCrush and PractRand in succession, and gather all the results in a single report when finished. All this simply by hitting 'QuickRun' in the IDE of your choice =D
-
- Posts: 4315
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: FreeBASIC's PRNG #2
I like your 'open pipe cmd ...' approach.
This is your piping program start:
This is my 1MB string start:
Try this:
Actually it makes a world of difference.paul doe wrote:From a functionality standpoint, no.
This is your piping program start:
Code: Select all
rng=RNG_stdin, seed=unknown
length= 1 megabyte (2^20 bytes), time= 3.4 seconds
no anomalies in 94 test result(s)
rng=RNG_stdin, seed=unknown
length= 2 megabytes (2^21 bytes), time= 7.2 seconds
no anomalies in 109 test result(s)
rng=RNG_stdin, seed=unknown
length= 4 megabytes (2^22 bytes), time= 14.7 seconds
no anomalies in 124 test result(s)
Code: Select all
rng=RNG_stdin32, seed=unknown
length= 256 megabytes (2^28 bytes), time= 2.5 seconds
no anomalies in 165 test result(s)
rng=RNG_stdin32, seed=unknown
length= 512 megabytes (2^29 bytes), time= 5.0 seconds
no anomalies in 178 test result(s)
rng=RNG_stdin32, seed=unknown
length= 1 gigabyte (2^30 bytes), time= 9.5 seconds
no anomalies in 192 test result(s)
Code: Select all
Dim Shared As Ulongint x = 12, w = 0
Dim As String cmd = "RNG_test stdin32 -multithreaded"
Dim As Long fileHandle = Freefile()
Dim Shared S As String * 1048576
Dim As Ulong Ptr SPtr, BasePtr
Dim As Long j
Function msws() As Ulong
x *= x
w += &h8b5ad4cef9c2703b
x += w
x = ( x Shr 32 ) Or ( x Shl 32 )
Return( x )
End Function
SPtr = Cptr(Ulong Ptr, Strptr( S ))
BasePtr = SPtr
Open pipe cmd For Binary Access Write As fileHandle
Do
For j = 1 To 262144
*SPtr = msws
SPtr += 1
Next
Print #fileHandle, S;
SPtr = BasePtr
Loop
Close( fileHandle )
Re: FreeBASIC's PRNG #2
Ah, I see. I was piping 1 32-bit number at a time hahaha! Sorry, told you I'm quite noob in these matters =Ddeltarho[1859] wrote:I like your 'open pipe cmd ...' approach
...
Try this:
Thanks for the suggestion! Things should work much more smoothly now =D
Re: FreeBASIC's PRNG #2
My second attempt (bar the string one)
The string one run to 2gb shows no anomalies, but it is too slow and I got fed up waiting.
Here is my second attempt.
This is pipe.bas
And the results up to 64 Gb
The first hiccup at 64 Gb.
My computer is not very fast.(Ebay bargain.)
The string one run to 2gb shows no anomalies, but it is too slow and I got fed up waiting.
Here is my second attempt.
This is pipe.bas
Code: Select all
'pipe.exe
Type Random
Private:
As Ulongint a,b,c,d
Public:
Declare Function Valu() As Ulongint
Declare Function Valf() As double
Declare Sub seed(As Ulongint)
End Type
Function Random.Valu() As Ulongint
Dim As Ulongint e = a - ((b Shl 7) Or (b Shr (57)))
a = b xor ((c Shl 13) Or (c Shr (51)))
b = c + ((d Shl 37) Or (d Shr (27)))
c = d + e
d = e + a
Return d
End Function
function Random.valf() as double
return Valu/18446744073709551615
end function
Sub Random.seed(Byval z As Ulongint)
This=Type(4058668781,z,z,z)
For i As Ulongint=1 To 20
Valu
Next
End Sub
dim as random p
p.seed(100)
Dim Shared S As String * 1048576
Dim As Ulong Ptr SPtr, BasePtr
Dim As Long j
SPtr = Cptr(Ulong Ptr, StrPtr( S ))
BasePtr = SPtr
Do
For j = 1 to 262144
*SPtr = p.valu
SPtr += 1
Next
print S;
SPtr = BasePtr
Loop
Code: Select all
Microsoft Windows [Version 10.0.17134.285]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Users\User\Desktop\bin\random\PractRand_0.94\PractRand_094\bin\msvc12_64bit>pipe3.exe | rng_test stdin32 -multithread
ed
RNG_test using PractRand version 0.94
RNG = RNG_stdin32, seed = unknown
test set = core, folding = standard (32 bit)
rng=RNG_stdin32, seed=unknown
length= 256 megabytes (2^28 bytes), time= 3.3 seconds
no anomalies in 165 test result(s)
rng=RNG_stdin32, seed=unknown
length= 512 megabytes (2^29 bytes), time= 6.8 seconds
no anomalies in 178 test result(s)
rng=RNG_stdin32, seed=unknown
length= 1 gigabyte (2^30 bytes), time= 14.1 seconds
no anomalies in 192 test result(s)
rng=RNG_stdin32, seed=unknown
length= 2 gigabytes (2^31 bytes), time= 27.9 seconds
no anomalies in 204 test result(s)
rng=RNG_stdin32, seed=unknown
length= 4 gigabytes (2^32 bytes), time= 57.4 seconds
no anomalies in 216 test result(s)
rng=RNG_stdin32, seed=unknown
length= 8 gigabytes (2^33 bytes), time= 120 seconds
no anomalies in 229 test result(s)
rng=RNG_stdin32, seed=unknown
length= 16 gigabytes (2^34 bytes), time= 255 seconds
no anomalies in 240 test result(s)
rng=RNG_stdin32, seed=unknown
length= 32 gigabytes (2^35 bytes), time= 530 seconds
no anomalies in 251 test result(s)
rng=RNG_stdin32, seed=unknown
length= 64 gigabytes (2^36 bytes), time= 1110 seconds
Test Name Raw Processed Evaluation
[Low1/32]Gap-16:B R= +4.4 p = 1.0e-3 unusual
...and 262 test result(s) without anomalies
My computer is not very fast.(Ebay bargain.)
-
- Posts: 4315
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: FreeBASIC's PRNG #2
@dodicat
There is a lot of shifting going on there but it still comes in at 243MHz.
I think that this thread is showing that FB's suite of generators is in dire need of a serious overhaul.
There is a lot of shifting going on there but it still comes in at 243MHz.
I think that this thread is showing that FB's suite of generators is in dire need of a serious overhaul.
Re: FreeBASIC's PRNG #2
A TPD of 165 Watt! I would need to plug in 3 power supplies in my laptop for that. Not that it would fit with all the cooling requirements :-)deltarho[1859] wrote:I think that I will just pop down to the shops and get an Intel® Core™ i9-7980XE; that has 36 threads. It may be wise to have a word with my bank manager first though. <smile>
Re: FreeBASIC's PRNG #2
@dodicat - interesting algorithm. rho seems to indicate that it's one of FB's
Re: FreeBASIC's PRNG #2
Observation:
On my old Dell, double cpu xeon (Two of 'em, not cores) Win XP runs hotter than Scientific Linux.
On my old Dell, double cpu xeon (Two of 'em, not cores) Win XP runs hotter than Scientific Linux.
-
- Posts: 4315
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: FreeBASIC's PRNG #2
I have mentioned on a few occasions that a tight loop for measuring MHz is not particularly informative.
Here are runs of my 'real life' test where each generator is given 20 seconds to do the same task.
gcc 8.1 FB 1.06
With Knuth64 being a LCG it should leave everyone standing but that is not the case. With Knuth64 failing PractRand in the KB domain and both PCG32II and MsWs passing in the TB domain then we can write off Knuth64.
PCG32II is still holding it's own but paul doe's MsWs find is not far behind.
I will remove xoshiro256 from the test. It is fast but it has nothing else going for it.
Here are runs of my 'real life' test where each generator is given 20 seconds to do the same task.
gcc 8.1 FB 1.06
Code: Select all
32-bit
5 1.50
1 425.79
3 440.59
CMWC4096 463.84
4 474.16
CryptoRndII 475.04
2 486.63
RndMT 606.92
xoshiro256 721.62
MsWs 777.78
PCG32II 878.54
Knuth64 883.05
64-bit
5 1.59
1 532.52
RndMT 725.48
CMWC4096 809.45
3 840.66
CryptoRndII 970.62
4 981.61
2 1061.21
xoshiro256 1254.99
MsWs 1307.09
PCG32II 1382.72
Knuth64 1383.80
PCG32II is still holding it's own but paul doe's MsWs find is not far behind.
I will remove xoshiro256 from the test. It is fast but it has nothing else going for it.
Re: FreeBASIC's PRNG #2
Speaking of fast: you don't really need to use strings to pass binary data to PractRand:deltarho[1859] wrote:I will remove xoshiro256 from the test. It is fast but it has nothing else going for it.
Code: Select all
dim shared as ulongint x = 12, w = 0, s = &h8b5ad4cef9c2703b
function msws() as ulong
x *= x
w += s
x += w
x = ( x shr 32 ) or ( x shl 32 )
return( x )
end function
dim as string cmd = "RNG_test stdin32 -multithreaded"
dim as long fileHandle = freeFile()
dim as ulongint numbers = 262144 '' how many numbers to pass to PractRand
dim as ulong ptr mem = new ulong[ numbers ]
dim as ulong ptr address = mem
open pipe cmd for binary access write as fileHandle
do
for i as integer = 1 To numbers
*address = msws()
address += 1
next
put #fileHandle, , *cptr( ubyte ptr, mem ), numbers * sizeOf( ulong )
address = mem
sleep( 1, 1 )
loop until( inkey() <> "" )
close( fileHandle )
delete[] mem