Click here to Skip to main content
15,887,027 members
Articles / Programming Languages / C
Tip/Trick

Fast SSE Pseudo Random Number Generator

Rate me:
Please Sign up or sign in to vote.
3.67/5 (3 votes)
19 Feb 2024CPOL2 min read 5.1K   1   7
The thing that could generate pseudo random numbers faster than standard library does
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:

C++
/* definition for RAND_MAX constant */
#include <stdlib.h>
/* random number storage */
static unsigned long long g_seed;

/**
 * Used to seed the generator
 * @param seed initializing "generator"
 */
void fast_srand(unsigned int seed)
{
    g_seed = seed;
}

/**
 * Compute a pseudo random integer. Output value in range [0, RAND_MAX]
 * @return pseudo random integer
 */
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:

C++
/* definition for RAND_MAX constant */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DEF_RANDOM_COUNT 10000
/* random number storage */
static unsigned long long g_seed;

/**
 * Used to seed the generator
 * @param seed initializing "generator"
 */
void fast_srand(unsigned int seed)
{
    g_seed = seed;
}

/**
 * Compute a pseudo random integer. Output value in range [0, RAND_MAX]
 * @return pseudo random integer
 */
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':/* type */
                    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:

Terminal
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):

Terminal
-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):

Terminal
-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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) NetCracker
Russian Federation Russian Federation
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.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Shao Voon Wong3-Mar-24 18:57
mvaShao Voon Wong3-Mar-24 18:57 
SuggestionRandomness Pin
wmjordan19-Feb-24 14:09
professionalwmjordan19-Feb-24 14:09 
GeneralRe: Randomness Pin
Alexey Shtykov20-Feb-24 2:05
professionalAlexey Shtykov20-Feb-24 2:05 
GeneralRe: Randomness Pin
wmjordan22-Feb-24 15:27
professionalwmjordan22-Feb-24 15:27 
GeneralRe: Randomness Pin
wmjordan22-Feb-24 16:55
professionalwmjordan22-Feb-24 16:55 
QuestionWhat is new or original here? Pin
Mircea Neacsu19-Feb-24 3:35
Mircea Neacsu19-Feb-24 3:35 
AnswerRe: What is new or original here? Pin
Alexey Shtykov20-Feb-24 2:05
professionalAlexey Shtykov20-Feb-24 2:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.