Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

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

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Databases Illuminated

Authors: Catherine M. Ricardo, Susan D. Urban, Karen C. Davis

4th Edition

1284231585, 978-1284231588

More Books

Students also viewed these Databases questions