在while循环中进行多处理,程序会在一段时间后挂起

时间:2017-04-27 19:29:46

标签: python loops multiprocessing

所以我有一个我一直在研究的程序。运行需要一段时间,我试图通过使用多处理库将其某些部分卸载到多个进程来优化其运行时间。

然而,虽然我很确定我已正确实现了我的进程,并且我正在卸载的代码部分可以并行运行但我遇到的问题是代码在可变数量的循环之后挂起。它似乎并不缺乏RAM。

请查看下面的代码。我已经包含了原始代码,新代码,涉及的不同功能和运行时代码。

我会尽快回答任何问题。

原始代码:

rStack = randStack()
listMaster=[]
while True:     
    if len(listMaster) == 0: #Checks if list is empty. A Python list will evaluate False if there is nothing in it.
        pt = randomSpherePt()# Generate point on sphere
        pt.append(R) # append rho
        listMaster = np.asarray(pt) # Add point to master list
        rStack.push(pt) # Add point to random stack
    else:
        parentPT = rStack.pop() #Grab an 'active' point
        i=1
        while i <= n:
            # Create candidate point in the annulus r1 to r2 around the parent point
            newPT = randAnnulus(parentPT, r1, r2, R)
            #determine if it is less than r1 from any point in the master list. If so throw it out and move on, otherwise keep it and exit loop
            angles = GCD_Angle(newPT, listMaster, method = None)
            test = angles < r1/R
            if test.any():
                pass
            else:
                listMaster = np.vstack((listMaster, newPT))
                rStack.push(newPT)
                break
            i += 1
        if i >= n: #If the loop fails to generate a valid candidate point remove parent point from consideration.
            pass
        else:
            rStack.push(parentPT)
    if rStack.empty(): #if the random stack is empty after a cycle, there are no more point to place. End loop
        break
return listMaster

多处理代码:

rStack = randStack()
listMaster=[]
while True:     
    if len(listMaster) == 0: #Checks if list is empty. A Python list will evaluate False if there is nothing in it.
        pt = randomSpherePt()# Generate point on sphere
        pt.append(R) # append rho
        listMaster = np.asarray(pt) # Add point to master list
        rStack.push(pt) # Add point to random stack
    else:
        parentPT = rStack.pop() #Grab an 'active' point
        output = mup.Queue()
        processes = [mup.Process(target=annuliPts,args=(parentPT, r1, r2, R, listMaster,output)) for x in range(n)]
        for p in processes:
            print "Starting process ", p
            p.start()
        for p in processes:
            p.join()
            print "Stoping process ", p

        if output.empty():
            print "No points"
            pass
        else:
            results = [output.get() for p in processes]
            index = rand.choice(np.arange(len(results)))
            newPT = results[index]
            rStack.push(parentPT)
            rStack.push(newPT)
            listMaster = np.vstack((listMaster,newPT))
        print "Finishing pop and mup set"
    if rStack.empty(): #if the random stack is empty after a cycle, there are no more point to place. End loop
        break
    return listMaster

辅助代码:

class randStack():
    '''
    This is a random access stack.
    '''
    def __init__(self):
        self.array = []

    def empty(self):
        return len(self.array) <= 0

    def length(self):
        return len(self.array)

    def push(self,x):
        self.array.append(x)

    def pop(self):
        n = len(self.array)

        if n <= 0:
            raise IndexError('Cannot pop from empty stack')
        elif n == 1:
            return self.array.pop()
        else:
            i = np.random.randint(0,n)
            self.array[i], self.array[-1] = self.array[-1],self.array[i]

        return self.array.pop()

def GCD_Angle(pt1,pt2, method = 'vector'):

    if method != 'vector':
        # theta1,phi1,rho1 = pt1
        # theta2,phi2,rho2 = pt2
        del_theta = abs(pt1[0]-pt2[...,0])

        t1 = np.cos(pt2[...,1]) * np.sin(del_theta)
        t2 = np.cos(pt1[...,1]) * np.sin(pt2[...,1]) - np.sin(pt1[...,1]) * np.cos(pt2[...,1]) * np.cos(del_theta)

        top = np.sqrt(t1**2 +t2**2)
        bot = np.sin(pt1[...,1]) * np.sin(pt2[...,1]) + np.cos(pt1[...,1]) * np.cos(pt2[...,1]) * np.cos(del_theta)

        cent_angle = np.arctan2(top,bot)
        return cent_angle

    else:
        pt1c = sph_to_cart(pt1)
        pt2c = sph_to_cart(pt2)
        try:
            V = np.cross(pt1c,pt2c,axisb=1)
            top = np.sqrt(np.sum(V**2,axis=1))
            bot = np.inner(pt1c,pt2c)[0]
        except:
            V = np.cross(pt1c,pt2c)
            top = np.sqrt(np.sum(V**2))
            bot = np.inner(pt1c,pt2c)
        angles=np.arctan2(top,bot)
    return angles       

def randomSpherePt():
    '''Generates a random point on a unit sphere. This method retrieves the machine epsilon (minimal floating point precision) 
    and uses it to generate a float on the all inclusive range [0,1]'''
    epsi = np.finfo(float).eps
    u_1 = rand.uniform(0,1 + epsi)
    u_2 = rand.uniform(0,1 + epsi)

    lam = math.acos(2.0*u_1 - 1.0) - math.pi / 2.0
    phi = 2.0 * math.pi * u_2

    return [lam,phi]

def randAnnulus(pt,r1,r2,R):
    '''This function generates a random point in the annulus "r" to "R" around the point "pt".'''

    theta, phi, rho = pt

    epsi = np.finfo(float).eps

    u_1 = rand.uniform(0, (1 + epsi))
    u_2 = rand.uniform(0, (1 + epsi))

    # generate alphha (azimuth) direction of point
    alpha = 2.0 * math.pi * u_1

    # generate arc distance lambda from point in range r-R (assume on unit sphere)
    lam = math.sqrt(u_2*(r2**2-r1**2)+r1**2)


    # generate spherical coordinates
    phi2 = math.asin(math.cos(alpha)*math.sin(lam)*math.cos(phi) + math.sin(phi)*math.cos(lam))
    theta2 = theta - math.acos((math.cos(lam) - math.sin(phi)*math.sin(phi2)) / (math.cos(phi)*math.cos(phi2)))

    # return coords
    return np.array([theta2,phi2,rho])

运行时代码:

import numpy as np
import os, math
import logging
from numpy.core.umath_tests import inner1d
import multiprocessing as mup
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

rand = np.random

if __name__ == '__main__':
    fig = plt.figure()
    ax = Axes3D(fig)
    mup.log_to_stderr() 
    logger = mup.get_logger()
    logger.setLevel(logging.INFO)
    print "Starting program"
    sph_array = sphere_Poisson_Dist(r1 = 10, r2 = 20, R = 100)
    cart_array = sph_to_cart(sph_array)
    print "Pushing data to visuals"
    x = cart_array[...,0]
    y = cart_array[...,1]
    z = cart_array[...,2]

    ax.scatter(x,y,z)
    plt.show()

0 个答案:

没有答案