我正在尝试在python 3.6(Anaconda发行版)中启动多处理。我已经对我的内部函数(数值积分)进行了大量测试,因此我确信它有效。目前给我带来麻烦的是传递适当的范围,因为我得到一些“无”回报。
import multiprocessing
from multiprocessing import Pool
def chunkwise(t, size=2):
it = iter(t)
return zip(*[it]*size)
def sint(tupl):
print('arg = ',tupl)
#lower = float(tupl[0])
#upper = float(tupl[1])
exit()
#ans = scipy.integrate.quad(int2,lower,upper)
#return ans
n_CPUs = 6
smin = float(10000)
smax = float(np.inf)
smax_spacing = float(2.5*10**12)
srange = np.linspace(smin,smax_spacing,n_CPUs)
srange = np.append(srange,np.inf)
print('length srange = ',len(srange))
filler=[]
for i in range(len(srange)):
if i == 0:
filler.append(float(srange[i]))
elif srange[i] == srange[-1]:
filler.append(float(srange[i]))
else:
filler.append(float(srange[i]))
filler.append(float(srange[i]))
srange = np.array(filler)
srange = list(chunkwise(srange))
def main():
pool = Pool(processes=n_CPUs)
res1 = pool.map(sint,[(smin,float(smin*2)), (float(smin*2),float(smin*3))])#srange)
res = sum(res1)
pool.close()
pool.join()
return res
if __name__ =="__main__":
result = main()
我的一些调试过程可以在这里包含的代码中看到。目前,我只想查看传递给我的sint()函数的参数。当我打印结果时,我得到了结果
arg = (number,bigger number)
None
arg = (number2, bigger number2)
None
为什么这些“无”出现?目前,它们的存在导致溢出/ NaN在代码的非并行化版本中不存在。有没有办法让“无”出现?我尝试检查tupl,lower和upper中是否存在“None”,但Python似乎不想识别这些(不会打印我写的“未检测到”消息)。
任何帮助都将非常感谢!如果需要更多信息,请告诉我。
答案 0 :(得分:3)
一个问题是多处理为您所写的所有内容启动了一个单独的进程,它完全创建了一个单独的Python实例,因此您的代码实际上运行了多次放在全局范围内的所有内容。运行代码将返回
>>> length srange = 7
>>> length srange = 7
对我来说多次。您需要将其他代码移动到单独的函数中,或者只需在def main()
内调用它。然而,修复此问题仍然会导致nones,这似乎是由于您实际上没有在smin
中的映射函数pool.map
中返回任何内容。通常,您的结果将是None
个对象(并且总和也不能超过任何对象),但这里存在另一个问题。您的流程实际上并未关闭。
这可能是因为您致电退出,没有退货或任何事情,甚至不是None
。
您没有调用exit来结束映射功能,请查看multiprocessing以查看示例。只需使用普通函数作为映射器,无需使用系统调用。
即使这不是您想要的,这是一个简单的示例,用您的示例显示实际运行的多处理代码:
编辑:我没有意识到你发布的大部分内容都不是必需的,我鼓励你在发布问题时做出最小的可验证的例子,我已经缩小并改变了我发布的实际集成内容,我还建议您在提出问题并编写自己的代码时使用正确的命名约定,sint
和tupl
不是可用的描述性名称。我在这里所做的是向您展示如何使用您提供的相同scipy集成实用程序在并行中正确执行集成。您可以将integrated_function
替换为您自己的函数的代码,它应该可以使用相同的
from multiprocessing import Pool
from scipy import integrate
def integrated_function(x):
return x ** 2
def integration_process(integration_range):
print("thread launched, tuple = ", integration_range)
lower = float(integration_range[0])
upper = float(integration_range[1])
y, err = integrate.quad(integrated_function, lower, upper)
return y
def main():
# notice how we put this inside this main function
n_CPUs = 6
total_integration_range = 60000
integration_chunks = 6
integration_step = total_integration_range / integration_chunks
integration_ranges = [(i * integration_step, (i + 1) * integration_step) for i in range(integration_chunks)]
pool = Pool(processes=n_CPUs)
res1 = pool.map(integration_process, integration_ranges) # srange)
res = sum(res1)
print(res)
pool.close()
pool.join()
return res
if __name__ == "__main__":
result = main()
# thread launched, tuple = (0, 10000)
# thread launched, tuple = (10000, 20000)
# thread launched, tuple = (20000, 30000)
# thread launched, tuple = (30000, 40000)
# thread launched, tuple = (40000, 50000)
# thread launched, tuple = (50000, 60000)
# 72000000000000.0
如果您的功能足够复杂并且集成足够大,则多处理的开销应该足够低以使其更快,请注意在线程中打印导致您不想要的减速,所以外面的调试我鼓励你不要打印。
编辑:由于他们想要进行无限集成,我还会在这里发布我对代码的想法和补充,而不是在评论中留下它。从技术上讲,即使具有无限的积分范围,你实际上并没有无限积分,近似无限积分的具体数值方法超出了这个问题的范围,但是因为scipy.ntegrate.quad
是一个用途{{3} }执行它的集成(因此名称' quad
'),它修复了这个问题,可以将np.inf
作为约束。不幸的是,我不知道如何保证与此界限的连续性能,可能需要比其他所有集成更长的时间才能完成,或者可能需要更少的时间,这意味着将工作分成相等的块变得更难。但是,您只需要更改积分范围的最后一个边界,以包括该范围内的无穷大。
这种变化看起来像这样:
integration_ranges = [(i * integration_step, (i + 1) * integration_step) for i in range(integration_chunks)]
# we take the last element of the array, and all but the last element of the tuple,
# and make a new tuple with np.inf as the last element
integration_ranges[-1] = integration_ranges[-1][:-1] + (np.inf,)
执行此操作后,您的最后一个边界应该受无穷大限制,因此您的总积分范围实际上为0 - > inf,即使total_integration_range
不是无穷大