多处理成员函数

时间:2018-04-03 17:36:48

标签: python multiprocessing

我有一个对象列表,需要调用每个对象的成员函数。是否可以使用多处理?

我写了一个我想做的简短例子。

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())

1 个答案:

答案 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