可能重复:
我怎么并行一个简单的Python循环?
我是很新的的Python(使用Python 3.2)和我有一个关于并行化的问题。 我有一个for循环,我想在Python 3.2使用“多”并行执行:
def computation:
global output
for x in range(i,j):
localResult = ... #perform some computation as a function of i and j
output.append(localResult)
总体而言,我想为一个范围的i = 0到J = 100执行此计算。 因此,我想创建一个数的每个调用函数“计算”与总范围的一个子进程。 如何任何想法做呢? 难道还有比使用多更好的办法?
更具体的,我想执行一个域分解和我有以下代码:
from multiprocessing import Pool
class testModule:
def __init__(self):
self
def computation(self, args):
start, end = args
print('start: ', start, ' end: ', end)
testMod = testModule()
length = 100
np=4
p = Pool(processes=np)
p.map(yes tMod.computation, [(length, startPosition, length//np) for startPosition in range(0, length, length//np)])
我得到一个错误信息提PicklingError。 任何想法可能是这里的问题?
JOBLIB是专门设计成环绕多处理用于简单的并行循环的目的。 我建议使用,而不是直接多处理拼杀。
简单的情况下,看起来是这样的:
from joblib import Parallel, delayed
Parallel(n_jobs=2)(delayed(foo)(i**2) for i in range(10)) # n_jobs = number of processes
一旦你了解它的语法很简单。 我们正在使用中产生的语法delayed
用于调用函数foo
包含在后面的括号它的参数。
在你的情况,您应该重写你与发电机语法循环,或定义另一个功能(即“工人”功能)执行单个循环迭代的操作和地点为呼叫到并行的生成语法。
在后一种情况下,你会做这样的事情:
Parallel(n_jobs=2)(delayed(foo)(parameters) for x in range(i,j))
其中foo
是一个函数定义来处理你的身体循环。 请注意,您不想追加到一个列表,因为水货反正返回一个列表。
在这种情况下,你可能要定义一个简单的函数来进行计算,并得到localResult
。
def getLocalResult(args):
""" Do whatever you want in this func.
The point is that it takes x,i,j and
returns localResult
"""
x,i,j = args #unpack args
return doSomething(x,i,j)
现在,在您的计算功能,你只是制造工人的游泳池和映射本地结果:
import multiprocessing
def computation(np=4):
""" np is number of processes to fork """
p = multiprocessing.Pool(np)
output = p.map(getLocalResults, [(x,i,j) for x in range(i,j)] )
return output
我已经删除了全球在这里,因为这是不必要的(全局通常是不必要的)。 在您的调用程序,你应该只是做output.extend(computation(np=4))
或类似的东西。
编辑
这是你的代码的“工作”的例子:
from multiprocessing import Pool
def computation(args):
length, startPosition, npoints = args
print(args)
length = 100
np=4
p = Pool(processes=np)
p.map(computation, [(startPosition,startPosition+length//np, length//np) for startPosition in range(0, length, length//np)])
请注意,你有没有因为你正在使用的实例方法为您的工作功能。 多启动新进程,并发送经由进程之间的信息pickle
,因此,仅可使用可被酸洗的对象。 需要注意的是它确实没有任何意义使用实例方法。 每个进程是父进程的一个副本,因此对状态,这发生在任何过程的变化不会传播回父反正。