所以我有一个我一直在研究的程序。运行需要一段时间,我试图通过使用多处理库将其某些部分卸载到多个进程来优化其运行时间。
然而,虽然我很确定我已正确实现了我的进程,并且我正在卸载的代码部分可以并行运行但我遇到的问题是代码在可变数量的循环之后挂起。它似乎并不缺乏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()