Shark
Shark

Reputation: 321

How to generate random numbers in multiple processes at the same time?

How can I generate random numbers in C for multiple processes being run at exactly the same time?

I wanted to use srand and rand but I don't know how (maybe using the process ID?).

Upvotes: 3

Views: 4850

Answers (2)

Douglas B. Staple
Douglas B. Staple

Reputation: 10946

After years and years of weird errors from poor random seeds, I eventually wrote a code to get random numbers from /dev/urandom, which are the same random numbers used for SSL. In my code I used these "good" random numbers to seed the C stdlib rand() function, which was sufficent for my task as long as it got a good seed:

#include <stdio.h>
#include <stdlib.h>

//HOW MANY BITS IN A CHAR? THIS MACRO IS USUALLY DEFINED
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif

//PATH TO RANDOM NUMBER GENERATOR
const char inPath[]="/dev/urandom";

//EXTRACTS A PSEUDORANDOM unsigned long FROM THE OPERATING SYSTEM VIA /dev/urandom
unsigned long get_urandom(){

  //OPEN INPUT STREAM
  FILE *inFile;
  inFile=fopen(inPath,"r");

  //FAILED TO OPEN STREAM
  if(inFile==NULL){
    fprintf(stderr, "# Failed to open random device %s\n", inPath);
    return 0;
  }

  //HOW MANY BITS IN A CHAR? HOW MANY CHARS IN AN UNSIGNED LONG?
  const int bitsInChar  = CHAR_BIT;
  const int charsInLong = sizeof(unsigned long) / sizeof(char);

  //GET RANDOM UNSIGNED LONG ONE CHARACTER AT A TIME
  unsigned long randomSeed=0;
  for(int i=0; i<charsInLong; i++)
    randomSeed |= fgetc(inFile) << i*bitsInChar;

  //CLOSE STREAM AND RETURN
  fclose(inFile);
  return randomSeed;

}

int main(){

  // We can use the above function directly to get our random numbers, but this is slow.
  printf("We can get random numbers from the OS via get_urandom: %u\n", get_urandom());  

  // Or we can just call get_urandom once, to use as a seed for the stdlib rand() function.
  unsigned int randomSeed=get_urandom();
  srand(randomSeed);
  printf("Or, using a random seed from get_urandom: %u\n", randomSeed);
  printf("We can get random numbers from stdlib, e.g.: %u\n", rand());
}

Here's the same code again with the function rewritten in C++:

#include <fstream>
using namespace std;

//HOW MANY BITS IN A CHAR? THIS MACRO IS USUALLY DEFINED
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif

//EXTRACTS A PSEUDORANDOM unsigned long FROM THE OPERATING SYSTEM VIA /dev/urandom
unsigned long get_urandom(const char inPath[]="/dev/urandom"){

  //OPEN INPUT STREAM
  ifstream inFile(inPath);

  //FAILED TO OPEN STREAM
  if(inFile.fail()){
    fprintf(stderr, "# Failed to open random device %s\n", inPath);
    return 0;
  }

  //HOW MANY BITS IN A CHAR? HOW MANY CHARS IN AN UNSIGNED LONG?
  const int bitsInChar  = CHAR_BIT;
  const int charsInLong = sizeof(unsigned long) / sizeof(char);

  //GET RANDOM UNSIGNED LONG ONE CHARACTER AT A TIME
  unsigned long randomSeed=0;
  for(int i=0; i<charsInLong; i++)
    randomSeed |= inFile.get() << i*bitsInChar;

  //CLOSE STREAM AND RETURN
  inFile.close();
  return randomSeed;

}

int main(){

  // We can use the above function directly to get our random numbers, but this is slow.
  printf("We can get random numbers from the OS via get_urandom: %u\n", get_urandom());  

  // Or we can just call get_urandom once, to use as a seed for the stdlib rand() function.
  unsigned int randomSeed=get_urandom();
  srand(randomSeed);
  printf("Or, using a random seed from get_urandom: %u\n", randomSeed);
  printf("We can get random numbers from stdlib, e.g.: %u\n", rand());
}

Upvotes: 1

Julien Fouilh&#233;
Julien Fouilh&#233;

Reputation: 2658

You can use a different seed for each process, based on the process id for example :

srand(getpid());

And then just use rand().

Upvotes: 13

Related Questions