18

我正在尝试使用 Python 的 pathos 将计算指定为单独的进程,以便使用多核处理器加速它。我的代码组织如下:

class:
   def foo(self,name):
    ...
    setattr(self,name,something)
    ...
   def boo(self):
      for name in list:
         self.foo(name)

由于我在使用 multiprocessing.Pool 时遇到了酸洗问题,所以我决定尝试一下 pathos。我尝试过,如先前主题中所建议的那样:

import pathos.multiprocessing

但它导致错误:没有模块多处理 - 我在最新的 pathos 版本中找不到。

然后我尝试修改 boo 方法:

def boo(self):
 import pathos
 pathos.pp_map.pp_map(self.foo,list)

现在没有抛出错误,但 foo 不起作用 - 我的类的实例没有新属性。请帮帮我,因为在花了一天时间之后,我不知道下一步该去哪里。

4

2 回答 2

38

我是pathos作者。我不确定您想从上面的代码中做什么。但是,我也许可以阐明一些观点。这是一些类似的代码:

>>> from pathos.multiprocessing import ProcessingPool
>>> class Bar:
...   def foo(self, name):
...     return len(str(name))
...   def boo(self, things):
...     for thing in things:
...       self.sum += self.foo(thing)
...     return self.sum
...   sum = 0
... 
>>> b = Bar()
>>> results = ProcessingPool().map(b.boo, [[12,3,456],[8,9,10],['a','b','cde']])
>>> results
[6, 4, 5]
>>> b.sum
0

所以上面发生的情况是,实例的boo方法被调用 where被传递给一个新的 python 进程,然后对每个嵌套列表进行评估。可以看到结果是正确的……len("12")+len("3")+len("456") 是6,以此类推。Barbb.boo

但是,你也可以看到,当你看的时候b.sum,它神秘地静止了0。为什么b.sum还是零?好吧,multiprocessing(因此也是pathos.multiprocessing)所做的,是将您通过映射传递给其他 python 进程的任何内容复制一份……然后(并行)调用复制的实例并返回被调用的方法调用的任何结果。请注意,您必须返回结果,或打印它们,或记录它们,或将它们发送到文件,或以其他方式。它们无法像您预期的那样返回到原始实例,因为它不是发送到其他处理器的原始实例。实例的副本被创建,然后被丢弃——每个副本都有自己的sum属性增加了,但原始的 `b.sum' 没有改变。

然而,内部有计划pathos像您所期望的那样进行上述工作 - 原始对象更新,但它还没有像那样工作。

编辑:如果您使用 安装pip,请注意最新发布的版本已有pathos几年历史,可能无法正确安装,或者可能无法安装所有子模块。一个新pathos版本正在等待中,但在那之前,最好从 github 获取最新版本的代码,然后从那里安装。主干大部分稳定在开发中。pip我认为您的问题可能是由于安装中的“新” -“旧”不兼容,并非所有软件包都已pathos安装。如果pathos.multiprocessing丢失,这是最有可能的罪魁祸首。

pathos从 github获取: https ://github.com/uqfoundation/pathos

于 2014-10-28T22:16:08.230 回答
0

这就是我的处理方法 - 我将函数放在类外部并行运行,并在调用 pool.map 时将对象作为 arg 传递。然后,我返回要重新分配的对象。

from pathos.multiprocessing import ProcessingPool


def boo(args):
    b, things = args
    for thing in things:
        b.sum += b.foo(thing)
    return [b, b.sum]

class Bar:
    def __init__(self):
       self.sum = 0
    def foo(self, name):
       return len(str(name))

pool = ProcessingPool(2)
b1 = Bar()
b2 = Bar()
print(b1, b2)

results = pool.map(boo, [[b1, [12,3,456]],[b2, ['a','b','cde']]])

b1, b1s = results[0]
b2, b2s = results[1]
print(b1,b1s,b1.sum)
print(b2, b2s, b2.sum)

输出:

(<__main__.Bar instance at 0x10b341518>, <__main__.Bar instance at 0x10b341560>)
(<__main__.Bar instance at 0x10b3504d0>, 6, 6)
(<__main__.Bar instance at 0x10b350560>, 5, 5)

map请注意,如@Mike McKerns 所述,b1 和 b2 不再与调用之前相同,因为它们的副本是为了传递。但是,它们所有属性的值都是完整的,因为它们被传递、返回和重新分配。

于 2020-12-07T01:07:30.920 回答