如何在python中使用多处理

我是python的新手,我想在下面的代码中进行并行编程,并希望在python中使用多处理来完成它.那么如何修改代码呢?我一直在使用Pool搜索方法,但发现了我可以遵循的有限示例.有人可以帮帮我吗?谢谢.

请注意,setinner和setouter是两个独立的函数,我想使用并行编程来减少运行时间.

def solve(Q,G,n):
    i = 0
    tol = 10**-4

    while i < 1000:

        inneropt,partition,x = setinner(Q,G,n)
        outeropt = setouter(Q,G,n)

        if (outeropt - inneropt)/(1 + abs(outeropt) + abs(inneropt)) < tol:
            break

        node1 = partition[0]
        node2 = partition[1]

        G = updateGraph(G,node1,node2)
        if i == 999:
            print "Maximum iteration reaches"
    print inneropt
最佳答案
很难并行化需要改变来自不同任务的相同共享数据的代码.所以,我将假设setinner和setouter是非变异函数;如果那不是真的,情况会更复杂.

第一步是决定你想要并行做什么.

一个显而易见的事情是同时做setinner和setouter.他们完全相互独立,总是需要完成.所以,这就是我要做的.而不是这样做:

inneropt,partition,x = setinner(Q,G,n)
outeropt = setouter(Q,G,n)

…我们希望将两个函数作为任务提交给池,然后等待两者完成,然后获取两者的结果.

concurrent.futures模块(需要Python 2.x中的第三方反向端口)使得比多处理模块(位于2.6中的stdlib中)更容易执行“等待两者都完成”之类的事情,但是这种情况下,我们不需要任何花哨的东西;如果其中一个提前完成,我们无论如何都要做,直到另一个完成.所以,让我们坚持使用multiprocessing.apply_async

pool = multiprocessing.Pool(2) # we never have more than 2 tasks to run
while i < 1000:
    # parallelly start both tasks
    inner_result = pool.apply_async(setinner, (Q, G, n))
    outer_result = pool.apply_async(setouter, (Q, G, n))

    # sequentially wait for both tasks to finish and get their results
    inneropt,partition,x = inner_result.get()
    outeropt = outer_result.get()

    # the rest of your loop is unchanged

您可能希望将池移动到函数外部,以便它永远存在,并且可以由代码的其他部分使用.如果没有,你几乎肯定想在功能结束时关闭池. (多处理的更高版本允许您在with语句中使用池,但我认为这需要Python 3.2,因此您必须明确地执行它.)

如果您想要并行完成更多工作怎么办?好吧,没有重组循环,没有其他明显的事情要做.在从setinner和setouter返回结果之前,你不能执行updateGraph,这里没有别的东西.

但是,如果你可以重新组织事物,以便每个循环的setinner独立于之前的所有内容(使用你的算法可能或不可能 – 不知道你在做什么,我无法猜测),你可以推动2000任务在前面排队,然后根据需要抓取结果循环.例如:

pool = multiprocessing.Pool() # let it default to the number of cores
inner_results = []
outer_results = []
for _ in range(1000):
    inner_results.append(pool.apply_async(setinner, (Q,G,n,i))
    outer_results.append(pool.apply_async(setouter, (Q,G,n,i))
while i < 1000:
    inneropt,partition,x = inner_results.pop(0).get()
    outeropt = outer_results.pop(0).get()
    # result of your loop is the same as before

当然,你可以做这个发烧友.

例如,假设您很少需要超过几百次迭代,因此总是计算1000次迭代是浪费的.你可以在启动时按下第一个N,然后每次通过循环再推一次(或者每N次更多N次),这样你就不会做多于N浪费的迭代 – 你无法在完美的并行性和最小的并行性之间取得理想的权衡浪费,但你通常可以很好地调整它.

此外,如果任务实际上没有那么长时间,但你有很多,你可能想要批量处理它们.一个非常简单的方法是使用其中一个地图变体而不是apply_async;这可能会使您的获取代码变得更加复杂,但它使得排队和批处理代码完全无关紧要(例如,将每个func映射到100个参数的列表上,其中10个块的大小只是两行简单的代码).

转载注明原文:如何在python中使用多处理 - 代码日志