如何在python中使用多处理
我是python新手,我想在下面的代码中进行并行编程,并希望使用python中的多处理来实现。那么如何修改代码呢?我一直在使用Pool搜索这个方法,但发现我可以遵循的示例有限。有人能帮我吗?多谢各位 请注意,setinner和setouter是两个独立的函数,因此我希望使用并行编程来减少运行时间如何在python中使用多处理,python,multiprocessing,Python,Multiprocessing,我是python新手,我想在下面的代码中进行并行编程,并希望使用python中的多处理来实现。那么如何修改代码呢?我一直在使用Pool搜索这个方法,但发现我可以遵循的示例有限。有人能帮我吗?多谢各位 请注意,setinner和setouter是两个独立的函数,因此我希望使用并行编程来减少运行时间 def solve(Q,G,n): i = 0 tol = 10**-4 while i < 1000: inneropt,partition,x =
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
def求解(Q,G,n):
i=0
tol=10**-4
当我<1000时:
inneropt,partition,x=setinner(Q,G,n)
outeropt=setouter(Q,G,n)
如果(外层-内层)/(1+abs(外层)+abs(内层))
很难并行化需要对来自不同任务的相同共享数据进行变异的代码。所以,我假设setinner
和setouter
是非变异函数;如果不是这样,事情会更复杂
第一步是决定你想同时做什么
一件显而易见的事情是同时执行
setinner
和setouter
。它们彼此完全独立,并且总是需要同时完成。所以,这就是我要做的。而不是这样做:
inneropt,partition,x = setinner(Q,G,n)
outeropt = setouter(Q,G,n)
…我们希望将这两个函数作为任务提交到池中,然后等待这两个函数都完成,然后获取这两个函数的结果
concurrent.futures
模块(在Python2.x中需要一个第三方后台端口)比多处理模块(在2.6+中的stdlib中)更容易执行“等待两者都完成”之类的操作,但在这种情况下,我们不需要任何花哨的东西;如果其中一个提前完成,我们就没有什么事情要做,直到另一个完成为止。所以,让我们继续:
当然,你可以让这个更漂亮
例如,假设您很少需要超过几百次迭代,因此总是计算1000次迭代是浪费的。您可以在启动时推送第一个N,然后在循环中每次推送一个(或者每N次再推N个),这样您就不会进行超过N次浪费的迭代。您无法在完美并行性和最小浪费之间获得理想的折衷,但您通常可以很好地调整它
此外,如果任务实际上不需要那么长的时间,但是您有很多任务,那么您可能需要对它们进行批处理。一个非常简单的方法是使用一个map
变量,而不是apply_async
;这可能会使您的获取代码稍微复杂一些,但它会使排队和批处理代码变得非常简单(例如,在chunksize
为10的100个参数列表上映射每个func
只不过是两行简单的代码)。该代码缩进不正确,并且会出现sytax错误。你能纠正你的代码吗?顺便说一句,这段代码可能使用了一些矩阵或图形库,这些矩阵或图形库可能是作为C扩展模块构建的,并且可能在不持有GIL(如NumPy)的情况下运行缓慢的操作,因此你可以只使用线程化
而不是多处理
,或者甚至在相关的情况下进行自动数据并行(如SciPy或KDT的某些部分,如果您正确配置和安装了先决条件),在这种情况下,多处理
实际上会降低您的速度…3个函数(setInner、setouter、updateGraph)的相对运行时间是多少?Q,G,n
对象大吗?你会在每次迭代中更新几乎所有的值(我假设它们是复合对象)还是只更新其中的一小部分?对于一些明确定义的用例,比如将两个函数设置为异步运行,lelo helper包是有用的-(在这种情况下,它可能只需要修饰setinner和setoutter即可):@jsbueno:看起来很酷。我担心Python中的自动惰性对象,因为实际上不可能覆盖Python中所有有用的表达式,因此最终可能会得到minval
而不是实际计算结果。(在C++中,这不是问题,因为(a)在您可以过载的事情中,分配、复制和转换为<代码> t& < /COD>,并且(b)静态类型通常以Python不能的方式强制严格,但是它显然会在OP的情况下工作,因为他立即解包一个,并将另一个传递给abs
…@jsbueno:事实上,经过再三考虑……在OP的情况下,将第一个结果解包为三个变量显然会受阻,这意味着他需要以与我的回答相同的方式重写代码(执行操作,然后获得结果),以实际获得任何并行性。尽管仅仅撤销这两个调用将是一个快速而肮脏的解决办法。@abanert-我不同意不能覆盖所有有用的表达式。包“lelo”可能包含错误,但要在Python中使用值,必须通过“dunder”(\uuuu NAME\uuu
)方法之一。纯assignemnt是不可重写的,但assignment所做的只是将惰性对象本身绑定到另一个名称。当它被打印、比较、序列化时,必须获取它的值。
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
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