If you need to create fast test with random number generator, you could use the code. But keep in mind that this code is not secure and was tested only in the test data generation.
Introduction
This is a kind of save point for the knowledge acquired during test data generation. The generator, using the code is faster than standard C library random functions, works almost everywhere and does not depend on the other things.
Background
The code created during the test data generator implementation. Standard library was too slow and there was no desire to get a dependency to the other libraries. Another intention was to make code to be cross platform compliable. The code will work on any SSE/SIMD compatible CPUs. It was not tested on RISC or ARM-alike CPUs.
Using the Code
The code itself is not big or complex:
#include <stdlib.h>
static unsigned long long g_seed;
void fast_srand(unsigned int seed)
{
g_seed = seed;
}
int fast_rand()
{
g_seed = (214013*g_seed+2531011);
return (g_seed>>32)&RAND_MAX;
}
The code is not fully mine. I found the main idea it on the Internet. I tried to compare the code with standard library functions (rand
/random
) and tried to read random data from /dev/urandom.
Performance and Randomness Tests
I was asked to compare performance and randomness of the generator from the article and the most available library generators.
Test Code
I wrote a test code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DEF_RANDOM_COUNT 10000
static unsigned long long g_seed;
void fast_srand(unsigned int seed)
{
g_seed = seed;
}
int fast_rand()
{
g_seed = (214013*g_seed+2531011);
return (g_seed>>32)&RAND_MAX;
}
int cStrToInt(const char* sz)
{
char* pEnd;
if(sz==NULL) {
return 0;
}
return strtol(sz,&pEnd, 10);
}
int main(int argc, char* argv[]) {
int i, n;
int randomCount = DEF_RANDOM_COUNT;
int randomType = 0;
int dontPrint = 0;
for(i=1; i<argc; i++) {
if(argv[i][0]=='-') {
switch(argv[i][1]) {
case 't':
if(i+1<argc) {
randomType = cStrToInt(argv[++i]);
}
break;
case 'c':
if(i+1<argc) {
randomCount = cStrToInt(argv[++i]);
}
break;
case 'p':
dontPrint = 1;
break;
}
}
else {
randomCount = cStrToInt(argv[i]);
}
}
if(randomCount<0) {
randomCount = DEF_RANDOM_COUNT;
}
switch(randomType) {
case 2:
srandom(time(NULL));
break;
case 1:
srand(time(NULL));
break;
default:
fast_srand(time(NULL));
break;
}
for(i=0; i<randomCount; i++) {
switch(randomType) {
case 2:
n = random();
break;
case 1:
n = rand();
break;
default:
n = fast_rand();
break;
}
if(dontPrint) {
continue;
}
printf("%d\n",fast_rand());
}
}
I saved test code as rndGenTest.c and compiled the code with the command below:
gcc rndGenTest.c -o rndGenTest
Performance
The performance comparison results on my Debian WSL were (first result for the code from article, second - srand
/rand
, third - srandom
/random
):
-bash $ time ./rndGenTest -p 10000000 ; time ./rndGenTest -p -t 1 10000000 ; time ./rndGenTest -p -t 2 10000000
real 0m0.034s
user 0m0.030s
sys 0m0.000s
real 0m0.071s
user 0m0.066s
sys 0m0.000s
real 0m0.057s
user 0m0.052s
sys 0m0.000s
Randomness
I also run on my Debian WSL a quick randomness test for all of these generators (first result for the code from article, second - srand
/rand
, third - srandom
/random
):
-bash $ ./rndGenTest 1000000 | sort -u | wc -l ; ./rndGenTest -t 1 1000000 | sort -u | wc -l ; ./rndGenTest -t 2 1000000
| sort -u | wc -l
999766
999762
999762
Points of Interest
I was really surprised with the code speed comparison. The code from the article could be twice faster than the library code. I think I can find an explanation why this had happened, but...
Anyway, the generator from the article is quite good to generate big test data.
History
- 19th February, 2024: Initial text
- 20th February, 2024: Append with test section
I came to the industry at the end of that times when the computer program executes as it was written. I saw a quite big machines, occupied more than 100 square meters for its central processor, but I started my professional activity as a programmer on IBM PC clones. There were different CPU architectures (68k, PowerPC, 386/486, SPARC...) when I began, but Intel defeated them all with Pentium CPU (marketing) family.
I saw the knowledge and technology fragmentation. I saw many technologies started, developed and retired. However, I have not seen many things yet.
I have some experience, but my experience is not perfectly comprehensive. I still have many things to learn and I still cannot make a poker face when I find out some aspects about how the things were designed and works. My experience does not make me an absolute expert in some areas, because these areas are changing. I know some things, but I also understand that some things I know could be useless for nowadays.