我有一个对象列表,需要调用每个对象的成员函数。是否可以使用多处理?
我写了一个我想做的简短例子。
import multiprocessing as mp
class Example:
data1 = 0
data2 = 3
def compute():
self.val3 = 6
listofobjects = []
for i in range(5):
listofobjects.append(Example())
pool = mp.Pool()
pool.map(listofobjects[range(5)].compute())
答案 0 :(得分:2)
@abarnert指出了两个概念问题,超出了你的"伪代码"中的句法和使用问题。第一个是map
使用一个应用于输入元素的函数。第二个是每个子进程获得对象的副本,因此不会在原始文件中自动看到对属性的更改。这两个问题都可以解决。
要回答您的直接问题,请按以下方式将方法应用于您的列表:
with mp.Pool() as pool:
pool.map(Example.compute, listofobjects)
Example.compute
是一个未绑定的方法。这意味着它只是一个接受self
作为第一个参数的常规函数,使其非常适合map
。我还将池用作上下文管理器,建议不管是否发生错误,都要确保正确完成清理。
上面的代码不起作用,因为compute
的效果对于子进程是本地的。将它们传递回原始流程的唯一方法是将return
传递给map
的函数。如果您不想修改compute
,可以执行以下操作:
def get_val3(x):
x.compute()
return x.val3
with mp.Pool() as pool:
for value, obj in zip(pool.map(get_val3, listofobjects), listofobjects):
obj.val3 = value
如果您愿意修改compute
以返回其正在操作的对象(self
),您可以使用它来更有效地替换原始对象:
class Example:
...
def compute():
...
return self
with mp.Pool() as pool:
listofobjects = list(pool.map(Example.compute, listofobjects))
<强>更新强>
如果您的对象或其引用树的某些部分不支持pickling(通常用于在进程之间传递对象的序列化形式),您至少可以通过直接返回更新的值来摆脱包装函数compute
:
class Example:
...
def compute():
self.val3 = ...
return self.val3
with mp.Pool() as pool:
for value, obj in zip(pool.map(Example.compute, listofobjects), listofobjects):
obj.val3 = value