Multiprocessing code to calculate pi never finishes

Question:

I want to calculate pi. The procedure is simple:

  1. Make a 1×1 square and draw a circle in the square. Then divide by 4.
  2. Take two random values (x, y).
  3. If x2 + y2 ≤ 1 than the point is in the circle.
  4. Repeat the above N times.
  5. Count the inner points (I’ll call it K) and divide by all number of executions and multiply by four. (4 * K / N == Pi)

The more iterations, the more accurate the calculation.

For doing fast, I use multiprocessing library. But the multiprocessing code never finishes. What’s the problem?

import timeit
start = timeit.default_timer()

import random
from multiprocessing import Pool

N = 1000000
process_num = 4

def make_pi(end):
    count_inbound = 0
    for x in range(end):
        the_x = random.random()
        the_y = random.random()
        if((the_x**2 + the_y**2) <= 1):
            count_inbound += 1
    return count_inbound

# Multiprocessing.
p = Pool(processes = process_num)
count_in = p.map(make_pi, [N/process_num for x in range(process_num)])
print(4*sum(count_in)/N)

# Normal.
##print(4*make_pi(N)/N)

stop = timeit.default_timer()
print(stop - start)
Asked By: Shwan

||

Answers:

I have test the same code on my mac.
It works just fine.

0.25 for multi process and 0.45 for single process.

Just change

[N/process_num for x in range(process_num)]

to
[int(N/process_num for x in range(process_num)]

Answered By: Alex Xu

Self answer.

the problem is process need to be closed.

so i add just one line.

if __name__ == "__main__":

than my code do work!

import timeit
start = timeit.default_timer()

import random
from multiprocessing import Pool

N = 1000000
process_num = 4

def make_pi(end):
    count_inbound = 0
    for x in range(end):
        the_x = random.random()
        the_y = random.random()
        if((the_x**2 + the_y**2) <= 1):
            count_inbound += 1
    return count_inbound

if __name__ == "__main__":
    #multiprocessing code
    p = Pool(processes = process_num)
    count_in = p.map(make_pi, [int(N/process_num) for x in range(process_num)])
    print(4*sum(count_in)/N)

    #normal code
    #print(4*make_pi(N)/N)

    stop = timeit.default_timer()
    print(stop - start)
Answered By: Shwan
import time
import random
from multiprocessing import Pool
start = time.perf_counter()

N = 100000000
process_num = 96

def calc_pi(end):
    count_inbound = 0
    for x in range(end):
        the_x = random.random()
        the_y = random.random()
        if((the_x**2 + the_y**2) <= 1):
            count_inbound += 1
    return count_inbound

if __name__ == "__main__":

    multi_processing = 1
    #multiprocessing code    

    if multi_processing == 1: 
        p = Pool()
        #add with statement so that pool will close automatically. 
        with p:
            count_in = p.map(calc_pi, [int(N/process_num) for x in range(process_num)])
        print(4*sum(count_in)/sum([int(N/process_num) for x in range(process_num)]))
        #You want to do a division by sum([int(N/process_num) for x in range(process_num)]) to preserve accuracy
    else: 
        #normal code
        print(4*calc_pi(N)/N)

finish = time.perf_counter()
print (f'Finished in {finish - start} seconds')
Answered By: Rohit M
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.