unique random number generation using threads - c++

I have a program which use pthreads. In each thread a random number is generated using the rand() (stdlib.h) function. But it seems like every thread is generating the same random number. What is the reason for that??.. Am I doing something wrong??.. Thanks

rand() is pseudo-random and not guaranteed to be thread-safe, regardless, you need to seed rand():
std::srand(std::time(0)); // use current time as seed for random generator
See std::rand() at cppreference.com for more details.
A sample program may look like this:
#include <cstdlib>
#include <iostream>
#include <boost/thread.hpp>
boost::mutex output_mutex;
void print_n_randoms(unsigned thread_id, unsigned n)
{
while (n--)
{
boost::mutex::scoped_lock lock(output_mutex);
std::cout << "Thread " << thread_id << ": " << std::rand() << std::endl;
}
}
int main()
{
std::srand(std::time(0));
boost::thread_group threads;
for (unsigned thread_id = 1; thread_id <= 10; ++thread_id)
{
threads.create_thread(boost::bind(print_n_randoms, thread_id, 100));
}
threads.join_all();
}
Note how the pseudo-random number generator is seeded with the time only once (and not per thread).

Related

Thread separated random int generation in C++

I need to genetate three .txt files filled with random int, calling the generate function in sepatared threads.
The problem is that as a result I have the same values in every .txt files.
A function that gererates and writes values:
void generateMoves(int limit, std::string outputPath) {
//open fstream
std::ofstream fout;
fout.open(outputPath);
if (!fout.is_open()) {
std::cout << "Error reading " << outputPath << " file. Exiting..." << std::endl;
exit(1);
}
static thread_local std::mt19937 generator;
std::uniform_int_distribution<int> distribution(1, 3);
//generating & writing moves
for (int i = 0; i < limit; i++) {
int value;
value = distribution(generator);
fout << value << std::endl;
}
fout.close();
}
I call threads like this from main():
int limit = 1000;
std::thread player1(generateMoves, limit, "player1.txt");
std::thread player2(generateMoves, limit, "player2.txt");
std::thread player3(generateMoves, limit, "player3.txt");
player1.join();
player2.join();
player3.join();
So, how do I separate int generation correctly?
Edit: Following the comment below, I putted diffent seed into each thread and everything works fine now. The random generation looks like this now:
// put different *s* into each thread
srand(s);
//generating & writing
for (int i = 0; i < limit; i++) {
int value;
value = rand() % 3 + 1;
fout << value << std::endl;
}
As the comments state, all your generators have been created from the same default seed. It suffices to give each generator a different seed:
std::random_device rd1;
static thread_local std::mt19937 generator(rd1());
This uses the (very slow) std::random_device, but only to generate a unique seed for the mt generator.

Remove finished threads from vector

I have a number of jobs and I want to run a subset of them in parallel. E. g. I have 100 jobs to run and I want to run 10 threads at a time. This is my current code for this problem:
#include <thread>
#include <vector>
#include <iostream>
#include <atomic>
#include <random>
#include <mutex>
int main() {
constexpr std::size_t NUMBER_OF_THREADS(10);
std::atomic<std::size_t> numberOfRunningJobs(0);
std::vector<std::thread> threads;
std::mutex maxThreadsMutex;
std::mutex writeMutex;
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0, 2);
for (std::size_t id(0); id < 100; ++id) {
if (numberOfRunningJobs >= NUMBER_OF_THREADS - 1) {
maxThreadsMutex.lock();
}
++numberOfRunningJobs;
threads.emplace_back([id, &numberOfRunningJobs, &maxThreadsMutex, &writeMutex, &distribution, &generator]() {
auto waitSeconds(distribution(generator));
std::this_thread::sleep_for(std::chrono::seconds(waitSeconds));
writeMutex.lock();
std::cout << id << " " << waitSeconds << std::endl;
writeMutex.unlock();
--numberOfRunningJobs;
maxThreadsMutex.unlock();
});
}
for (auto &thread : threads) {
thread.join();
}
return 0;
}
In the for loop I check how many jobs are running and if a slot is free, I add a new thread to the vector. At the end of each thread I decrement the number of running jobs and unlock the mutex to start one new thread. This solves my task but there is one point I don't like. I need a vector of size 100 to store all threads and I need to join all 100 threads at the end. I want to remove each thread from vector after it finished so that the vector contains a maximum of 10 threads and I have to join 10 threads at the end. I think about passing the vector and an iterator by reference to the lambda so that I can remove the element at the end but I don't know how. How can I optimize my code to use a maximum of 10 elements in the vector?
Since you don't seem to require extremely fine-grained thread control, I'd recommend approaching this problem with OpenMP. OpenMP is an industry-standard directive-based approach for parallelizing C, C++, and FORTRAN code. Every major compiler for these languages implements it.
Using it results in a significant reduction in the complexity of your code:
#include <iostream>
#include <random>
int main() {
constexpr std::size_t NUMBER_OF_THREADS(10);
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0, 2);
//Distribute the loop between threads ensuring that only
//a specific number of threads are ever active at once.
#pragma omp parallel for num_threads(NUMBER_OF_THREADS)
for (std::size_t id(0); id < 100; ++id) {
#pragma omp critical //Serialize access to generator
auto waitSeconds(distribution(generator));
std::this_thread::sleep_for(std::chrono::seconds(waitSeconds));
#pragma omp critical //Serialize access to cout
std::cout << id << " " << waitSeconds << std::endl;
}
return 0;
}
To use OpenMP you compile with:
g++ main.cpp -fopenmp
Generating and directly coordinating threads is sometimes necessary, but the massive number of new languages and libraries designed to make parallelism easier speaks to the number of use cases in which a simpler path to parallelism is sufficient.
The keyword "thread pool" helped me much. I tried boost::asio::thread_pool and it does what I want in the same way as my first approach. I solved my problem with
#include <thread>
#include <iostream>
#include <atomic>
#include <random>
#include <mutex>
#include <boost/asio/thread_pool.hpp>
#include <boost/asio/post.hpp>
int main() {
boost::asio::thread_pool threadPool(10);
std::mutex writeMutex;
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0, 2);
std::atomic<std::size_t> currentlyRunning(0);
for (std::size_t id(0); id < 100; ++id) {
boost::asio::post(threadPool, [id, &writeMutex, &distribution, &generator, &currentlyRunning]() {
++currentlyRunning;
auto waitSeconds(distribution(generator));
writeMutex.lock();
std::cout << "Start: " << id << " " << currentlyRunning << std::endl;
writeMutex.unlock();
std::this_thread::sleep_for(std::chrono::seconds(waitSeconds));
writeMutex.lock();
std::cout << "Stop: " << id << " " << waitSeconds << std::endl;
writeMutex.unlock();
--currentlyRunning;
});
}
threadPool.join();
return 0;
}

random_shuffle and srand() give me the same result every time

I'm trying to produce do some processing on a random permutation of the alphabet, however each permutation produces the same result despite using srand(myseed)
I have included the <algorithm> header.
string create_permutation(unsigned seed)
{
srand(seed);
string permutation = ALPHABET;
random_shuffle(permutation.begin(), permutation.end());
return permutation;
}
cout << create_permutation(2) << endl; // or 3, 4, 5 etc
// continuously returns 'XQACKHSLOJ,TRBZNGV.W FIUEYDMP
Any help would be greatly appreciated.
EDIT: Minimal, Complete, and Verifiable example
EDIT 2: adjustment to mcve
#include <iostream>
#include <algorithm>
using namespace std;
const string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
string create_permutation(unsigned seed)
{
srand(seed);
string permutation = ALPHABET;
random_shuffle(permutation.begin(), permutation.end());
return permutation;
}
int main(){
cout << create_permutation(2) << endl; // or 3, 4, 5 etc
// continuously returns 'XQACKHSLOJ,TRBZNGV.W FIUEYDMP
return 0;
}
The problem
The shuffles aren't random because shuffle_random is using the same seed for the random number generator each time it is called.
srand does not seed the random_shuffle function, it seeds rand and random_shuffle usually calls rand, but does not have to.
random_shuffle has two forms:
One that takes 2 arguments (begin/end iterators)
One that takes 3 (begin/end iterator and a random generator).
You have demonstrated that you know how to use the first form, but the problem with the first form is that it is implemented differently on different platforms and with different compilers. It may not use rand() at all, which is the function that srand seeds.
You should use the 3 argument form and provide the random number generator as a parameter to the function.
You can follow this detailed answer to learn how to make your own random number generator, or you can provide rand() to the random_shuffle function as the random number generator.
When you seed the random number generator, you set the starting point for an algorithm that will provide a sequence of psuedorandom numbers. If you always use the same seed, the algorithm will always have the same starting point and always generate the same sequence of numbers.
Every time you call srand, you reset the seed and reset the starting point for the algorithm.
A common bug here is to repeatedly call srand. Unless you have a very good reason not to (and if you do, you probably shouldn't use rand and srand at all. Look to the <random> library) you should call srand once at the beginning of the program to seed the generator once and ever after use that seed.
srand is also quite expensive. From a performance standpoint, you don't want to call it often.
So: since every call to create_permutation calls srand with the seed parameter and create_permutation is always called with the same seed value, for a given implementation of the random number generator, create_permutation will always use the same random number sequence and thus generate the same permutation.
A quick example that will generate different permutations, so long as the program is not run more often than once per second is
#include <iostream>
#include <string>
#include <algorithm>
#include <ctime>
const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
std::string create_permutation()
{
std::string permutation = ALPHABET;
std::random_shuffle(permutation.begin(), permutation.end());
return permutation;
}
int main(){
srand(time(NULL)); // caveat: time's minimum resolution is 1 second.
// multiple executions of this program within 1
// second will get the same time and use the same seed.
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
return 0;
}
A more modern approach:
#include <random>
#include <algorithm>
#include <iostream>
#include<string>
const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
std::random_device rd; // Warning: implementation of this is allowed to be stupid and
// return the same value every time. Does not work in mingw 4.8
// Can't speak for 4.9 or greater
std::mt19937 randomizer(rd());
std::string create_permutation()
{
std::string permutation = ALPHABET;
std::shuffle(permutation.begin(), permutation.end(), randomizer);
return permutation;
}
int main()
{
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
}

How to generate 64 bit random numbers?

I'm implementing universal hashing and using the following universal hash function :
h(k)=((A*k)mod 2^64) rsh 64-r
where A is a random number between
2^61 and 2^62.
The rand() function in C++ has return type integer and it can't generate that big numbers. So how can i generate random numbers in this range? (numbers should be very random i.e. every number should have equal probability to be selected)
Note:
long long int random=rand();
doesn't work as the number returned by rand is int.
In C++11 you can use the random header and std::uniform_int_distribution along with a 64-bit instance of std::mersenne_twister_engine this should do what you want (see it live):
#include <iostream>
#include <random>
#include <cmath>
int main()
{
std::random_device rd;
std::mt19937_64 e2(rd());
std::uniform_int_distribution<long long int> dist(std::llround(std::pow(2,61)), std::llround(std::pow(2,62)));
std::cout << std::llround(std::pow(2,61)) << std::endl;
std::cout << std::llround(std::pow(2,62)) << std::endl;
for (int n = 0; n < 10; ++n) {
std::cout << dist(e2)<< ", " ;
}
std::cout << std::endl ;
}
If C++11 is not an option then it seems there is source code available for several 64-bit Mersenne Twister implementations.
((long long)rand() << 32) | rand()
EDIT: that's assuming that rand() produces 32 random bits, which it might not.

Program is generating same random numbers on each run? [duplicate]

This question already has answers here:
Why does rand() yield the same sequence of numbers on every run?
(7 answers)
Closed 5 years ago.
I just finished coding a Minesweeper type game, and everything's good except for that each time I run the application, it generates the same number (I ran it 3 different times, saved the output to 3 text files and used the diff command in Linux, it didn't find any differences). It's seeded by time(NULL) so it should change every time, right?
Here's my code:
main.cpp
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <string>
#include "Minesweeper/box.h"
#include <cstdio>
int main(int argc, char** argv){
using namespace std;
bool gameOver = false;
int x, y, score = 0;
const int HEIGHT = 10;
const int WIDTH = 10;
unsigned int Time = time(0);
cout << "Welcome to Minesweeper. " << endl;
//setup grid
Box grid[10][10];
for(int i = 0; i < WIDTH; i++)
for(int n = 0; n < HEIGHT; n++){
unsigned int value = rand() %100 + 1;
cout << value << endl;
if(value <= 38){
grid[i][n].setFill(MINE);
//cout << i << "," << n << " is mined." << endl;
}
else
grid[i][n].setFill(EMPTY);
}
for(int r = 0; r < WIDTH; r++)
for(int l = 0; l < HEIGHT; l++)
if(grid[r][l].getFill() == EMPTY)
cout << r << "," << l << " - EMPTY." << endl;
else if (grid[r][l].getFill() == MINE)
cout << r << "," << l << " - MINE." << endl;
while(!gameOver){
cout << "Enter coordinates (x,y): ";
scanf("%i,%i",&x,&y);
if(grid[x][y].getFill() == MINE)
gameOver = true;
else{
cout << "Good job! (You chose " << x << "," << y << ")" << endl;
score++;
}
}
cout << "You hit a mine! Game over!" << endl;
cout << "Final score: " << score << endl;
getchar();
return EXIT_SUCCESS;
}
It's seeded by time(NULL)
If it is, I can't see it. In fact, a search for it in your code returns nothing. The default behaviour, if you don't explicitly seed, is the same as if you had seeded it with the value 1.
You need to explicitly state something like:
srand (time (NULL));
at the start of main somewhere (and make sure you do this once and once only).
Though keep in mind this makes it dependent on the current time - if you start multiple jobs in the same second (or whatever your time resolution is), they'll start with the same seed.
From the C standard (on which C++ is based for these compatibility features):
The srand function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand. If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.
You need to seed randomizer. Call srand() at the beginning.
To add to the answers by others, you can use the Mersenne Twister Algorithm, which is a part of the C++11 library. Its fast becoming a standard in many common softwares to generate random numbers.
For example, this is the function I wrote, which I use often to generate random numbers in my other codes:
std::vector<double> mersennetwister(const int& My,const int& Mz,
const int& Ny,const int& Nz)
{
int ysize = (My + 2*Ny + 1);
int zsize = (Mz + 2*Nz + 1);
int matsize = ysize*zsize;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
// Seeding the generator with the system time
std::mt19937_64 generator (seed);
// Calling the Mersenne-Twister Generator in C++11
std::uniform_real_distribution<double> distribution(0,1);
// Specifying the type of distribution you want
std::vector<double> randarray(matsize,0);
// Saving random numbers to an array
for (int i=0;i<matsize;++i)
{
randarray[i] = distribution(generator); // Generates random numbers fitting the
// Distribution specified earlier
}
return(randarray);
}
Bottomline: C++11 has some excellent features for numerical operations and it would be a good idea to look into them. As for the Mersenne Twister, http://en.wikipedia.org/wiki/Mersenne_twister