Roulette Wheel Picture

“Sahara Hotel and Casino 2” by Antoine Taveneaux - Own work. Licensed under Creative Commons Attribution-Share Alike 3.0 via Wikimedia Commons

Roulette Simulation

An American Roulette wheel has 38 slots: 18 are red, 18 are black, and 2 are green, which the house always wins. When a person bets on either red or black, the odds of winning are 18/38, or 47.37% of the time.

Our next is example is a simulation of spinning the Roulette wheel. We have a main simulation loop that is similar to the coin-flipping example. The code for determining a win on each spin is more involved than flipping a coin, and the sequential version, rouletteSimulation_seq.cpp is decomposed into several methods. Look at this original code file to see how we run the simulations using increasing numbers of random spins of the wheel.

The function that actually runs a single simulation of the Roulette wheel, called spinRed(), is quite simple. It generates a random number to represent the slot that the ball ends up in and gives a payout according to the rules of Roulette.

//spin the wheel, betting on RED
//Payout Rules:
//  0..17 you win (it was red)
// 18..35 you lose (it was black)
// 36..37 house wins (green) - you lose half
int spinRed(int bet, unsigned int *seed) {
	int payout;
	int slot = rand_rIntBetween(1,38, seed);
	/* if Windows
	int slot = randIntBetween(1,38);
	 */
	if (slot <= 18) //simplify odds: [0..17]==RED
		payout = bet;	//won
	else if (slot <= 36) //spin was 'black'-lose all
		payout = -bet;	//lost
	else //spin was green - lose half
		payout = -(bet/2); //half-back
	return payout;
} // spinRed

Note

The sequential version of the simulation takes a fair amount of time. Note how long. Also note how many simulated random spins it takes before the distribution of spins accurately reflects the house odds.

Parallelism to the Rescue

We add OpenMP parallelism as in the coinFlip example, by running the loop of random spins for each trial on several threads. This code is in this file that you can download: rouletteSimulation_omp.cpp The actual simulation function is getNumWins():

/*********************** getNumWins ************/ 
int getNumWins(int numSpins, unsigned int seed) {
//always bet 'red' & count wins
	static int wins;//our counter
	int spin;		//loop cntrl var
	int myBet = 10; //amount we bet per spin

	wins = 0;	//clear our counter
	
/***  OMP ***/    
#pragma omp parallel for num_threads(nThreads) default(none) \
    shared(numSpins, myBet) \
	private(spin, seed) \
	reduction(+:wins)
	for (spin=0; spin<numSpins; spin++){
		//spinRed returns +/- number (win/lose)
		if (spinRed(myBet, &seed) > 0) //a winner!
			wins++;
	}	////  end forked parallel threads
	
	return wins;
}  //getNumWins

Notes about this code: numSpins and myBet are shared between threads while spin is the loop index and unique to each thread. When using rand_r() as the thread-safe random number generator in linux/unix, the seed should be private to each thread also. Like the previous example, we combine the partial results from each thread with reduction(+:wins).