Python- How to make this program use multiprocessi

2019-03-07 00:58发布

问题:

In python 3, I have a simple dice roller program. What it does is ask the user for the amount of sides of a dice and how many times they would like to roll it.

This is accomplished by creating a list and each sublist represents a dice side. Every time a random number is generated, it is appended to the according sublist.

The results are displayed with a simple print procedure.

My query is how can I use multiprocessing to make it faster as it takes ~21 minutes to do 1 million rolls.

The code for the program is as follows:

import time
import random

roll = []#List for the results

def rng(side,reps):#rolls the dice 
    for i in range(reps):
        land = random.randint(1,side)
        print(land)
        roll[land-1].append(land)

def printR(side,reps):#Prints data
    for i, item in enumerate(roll):
        print('D'+str(i+1),'=''total ',total)

def Main():
    side = int(input('How many sides is the dice'))
    reps = int(input('How many rolls do you want to do?'))

    for i in range(side):#Creates empty arrays corresponding to amount of sides
        roll.append([])

    t0= time.clock()#Start timing dice roller

    rng(side,reps)

    t1 = time.clock()#End timing of dice roller

    printR(side,reps)#Print data
    times  = t1 - t0#Time
    print(round(times,3),'seconds')

Main()

回答1:

You don't need multiprocessing. All you need to do is use a better algorithm.

>>> import collections
>>> import random
>>> import time
>>> def f():
...     t = time.perf_counter()
...     print(collections.Counter(random.randint(1,6) for _ in range(1000000)))
...     print(time.perf_counter() - t)
...
>>> f()
Counter({2: 167071, 4: 166855, 3: 166681, 1: 166678, 5: 166590, 6: 166125})
2.207268591399186


回答2:

Choosing the alternate algorithm is probably the best plan, but for what it's worth, if you did want to use multiprocessing, you'd probably have a different problem to solve. For example, let's say you had a list of lists of numbers.

nums = [[1,2,3],[7,8,9],[4,5,6]]

Then you could have a function per-sub-list that maybe calculates and returns the sum of the numbers in the sub-set. Aggregate the results to get the full sum, probably more quickly than you would otherwise with a large enough data set. You could have a multiprogramming merge sort too, for example. Multiprogramming/threading is best when you have a number of tasks that don't interfere with each other and can be completed in isolation.

For your original problem, you'd probably have to think about how to keep track of total rolls per side so you could have a function per side calculating rolls, but then there would be the usual issue of figuring how to make sure counters are consistent / how to know when to stop.