带有悲情的 Python 多处理

Posted

技术标签:

【中文标题】带有悲情的 Python 多处理【英文标题】:Python multiprocessing with pathos 【发布时间】:2014-11-21 11:26:44 【问题描述】:

我正在尝试使用 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 不起作用 - 我的类的实例没有新属性。请帮助我,因为在花了一天时间之后,我不知道下一步该去哪里。

【问题讨论】:

【参考方案1】:

我是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

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

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

不过,pathos 内部计划使上述工作如您所料 - 原始对象 IS 已更新,但它还不能那样工作。

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

在此处从 github 获取 pathos:https://github.com/uqfoundation/pathos

【讨论】:

我在这里遇到了和 OP 一样的问题。我可以做import pathos,但import pathos.multiprocessing 给了我一个找不到模块的错误。这可能是什么原因? 问题是,我不明白 OP 的问题……由于英语的一些障碍以及最小的代码示例。也许我可以尝试另一种方法。也许所有依赖项都没有安装。你能import processing吗? from processing.pool import Pool 怎么样? from pathos.helpers import mp_helperfrom pathos.helpers import ProcessPool 怎么样? import ppfrom pathos.helpers import pp_helper 呢? from pathos.helpers import * 给出“没有名为助手的模块”。不知何故,并不是所有的悲情都对我有用,而且似乎是 OP。我是从 pip 安装的,是最新版本。 在包中,我有core、hosts、Launcher、LauncherSCP、LauncherSSH、pp_map、Server、Tunnel、util、XMLRPCRequestHandler、XMLRPCServer。就是这样,没有助手,没有多处理。 @Brideau:我正在将pathos 拆分成几个包(基本上是所有非标准依赖项),以确保所有东西都可以安装pip。新版本应该很快就会推出。【参考方案2】:

这就是我的处理方法 - 我将函数放在类外部并行运行,并在调用 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)

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

【讨论】:

以上是关于带有悲情的 Python 多处理的主要内容,如果未能解决你的问题,请参考以下文章

pathos:并行处理选项 - 有人可以解释其中的差异吗?

如何使用带有 YouTube API 的 Python 多处理进行抓取 [关闭]

带有 RPYC 的多处理 Python “ValueError:酸洗已禁用”

AI开发工程师的悲情与快乐,也许只有AI懂

python多处理日志记录:带有RotatingFileHandler的QueueHandler“文件被另一个进程使用”错误

在 python 中使用带有多处理的 matplotlib 保存多个图像(~50k)