Question
Small python programs: Your task is to parallelize risk_serial.py. Create two programs, one using threads (risk_thr.py) and one using multiple processes (risk_mp.py). Manage the threads
Small python programs: Your task is to parallelize risk_serial.py. Create two programs, one using threads (risk_thr.py) and one using multiple processes (risk_mp.py). Manage the threads and processes yourself dont use the futures module. For the threads program, fork a separate thread for each simulation. Rather than returning the result from run_simulations() you should put it in a queue. You cant use queue.task_done(), needed for queue.join(), because the threads are putting items into the queuenot taking them out.
Because the Python statistics functions don't work on a queue, youll have to get() the items from the queue and put them in a list in order to print the simulation statistics.
Using multiple processes is a bit more involved because you don't want to start a separate process for each simulationin fact, you should use the number of processors available to the program. You can find the number of processors using multiprocessing.cpu_count(). The number of simulated battles is not likely to be evenly divisible by the number of processorsso one processor may have to do some additional simulations. For example, if you have 4 processors to run 50 simulations, three processors will do 12 simulations while one will do 14 simulations. You can determine how to apportion simulations among processors using integer division (num_simulations // num_processors) and modulo (num_simulations % num_processors).
Make a list of processes then start them in one loop and join them in another loop. Once again, you'll have to move the results from the queue into a list before printing the statistics (by the way, be sure your queue for this program is a multiprocessing queue). NOTE: I used a global queue on Linux but I had to make it local to main(), and pass it to run_simulations(), on Windows.
Try your programs, as well as risk_serial.py, with 25, 50, 75, and 100 simulations. Include a short report (text or Word document) giving the results of these experiments. Explain your resultswhich program is fastest, and why? Which program is slowest, and why? Also, in your report, document the number of cores on your test system.
Risk_serial.py is below:
#Risk.py: Simulate Risk battles
#Rules are at http://www.hasbro.com/common/instruct/risk.pdf
import sys
import random
import time
import statistics as stats
def roll(attack_dice, defend_dice):
'''Carry out a roll for both sides
Return a tuple (attack_loss, defend_loss)'''
attack_roll = [] #Accumulates rolls of attacker's dice
for i in range(0, attack_dice): #Carry out attacker's rolls
attack_roll.append(random.randint(1, 6))
defend_roll = [] #Accumulates rolls of defender's dice
for i in range(0, defend_dice): #Carry out defender's rolls
defend_roll.append(random.randint(1, 6))
attack_roll.sort()
attack_roll.reverse() #Put attacker's rolls in descending order
defend_roll.sort()
defend_roll.reverse() #Put defender's rolls in descending order
attack_loss = 0 #This will count number of losees for attacker
defend_loss = 0 #Number of losses for defender
for i in range(0, len(defend_roll)): #Compare attacker's rolls with defender's
if attack_roll[i] > defend_roll[i]: #Defender loses if attacker's is higher
defend_loss = defend_loss + 1
else:
attack_loss = attack_loss + 1 #Else attacker loses (defender wins ties)
#print(attack_roll, defend_roll, attack_loss, defend_loss)
return attack_loss, defend_loss #Return a tuple with number losses for each player
def run_simulations(num_simulations, num_armies, attack_dice, defend_dice):
results = []
for i in range(num_simulations):
attacknum = num_armies
defendnum = num_armies
while attacknum > 1 and defendnum > 0: #Attacker needs at least 2 to continue
if attacknum > 3: #Check number of attacking armies
aroll = attack_dice #if > 3, roll all of attacker's dice
else:
aroll = 2 #Else attacker rolls 2 dice
if defendnum > 1: #Check number of defending armies
droll = defend_dice #if > 1, roll all of defender's dice (max is 2)
else:
droll = 1 #Else defender can only roll 1 die
result = roll(aroll, droll)
#Update number of armies for each player
attacknum = attacknum - result[0]
defendnum = defendnum - result[1]
#print("Attackers:", attacknum, "Defenders:", defendnum)
#Append number of attacker's armies at end of each simulation
#Assume defender has 0 armies (if attacker has 1 then defender won)
results.append(attacknum)
return results
def main(num_simulations):
num_armies = 10000 #Number of armies for both attacker and defender at outset
num_attack_dice = 3 #Number of dice for attacker when holding enough armies
num_defend_dice = 2 #Number of dice for defender when holding enough armies
#Carry out simulations
results = run_simulations(num_simulations, num_armies,
num_attack_dice, num_defend_dice)
#Print statistics
print(round(stats.mean(results), 2), round(stats.stdev(results), 2),
stats.median(results))
if __name__ == "__main__":
num_simulations = int(sys.argv[1])
start = time.time()
main(num_simulations)
elapsed_time = time.time() - start
print("Elapsed time: {}".format(elapsed_time))
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started