【问题标题】:Python: (Pathos) Multiprocessing vs. class methodsPython:(Pathos)多处理与类方法
【发布时间】:2015-05-21 05:35:01
【问题描述】:

我正在尝试通过多处理使用类方法并行化代码。基本结构如下:

# from multiprocessing import Pool
from pathos.multiprocessing import ProcessingPool as Pool

class myclass(object):
    def __init__(self):
        #some code
    def mymethod(self):
        #more code
        return another_instance_of_myclass



def myfunc(myinstance,args):
    #some code   
    test=myinstance.mymethod()
    #more code
    return myresult #not an instance,just a number

p=Pool()

result = p.map(myfunc,listwithdata)

在正常的多处理失败后,我意识到 Pickle 和多处理的问题,因此我尝试使用 multiprocessing.pathos 解决它。但是,我仍然得到

PicklingError: Can't pickle <type 'SwigPyObject'>: it's not found as__builtin__.SwigPyObjec

还有来自 pickle.py 的许多错误。除了这个实际问题之外,我不太明白为什么除了 myfunc 的最终结果之外还有其他东西被腌制。

【问题讨论】:

  • 似乎dill 不适用于开箱即用的 Swig。请参阅this question,它提供了使 Swig 对象可腌制的解决方案。你也许可以利用它。
  • 我必须承认,我什至花了一点时间才知道 SwigPy 对象的来源(我自己没有定义它)。事实证明,我使用的其中一个模块又使用了用 C 编写的数值库。挖掘所有那里看起来很难,但我会试一试。

标签: python pickle python-multiprocessing pathos


【解决方案1】:

pathos 使用dill,而dill 序列化类的方式与python 的pickle 模块不同。 pickle 通过引用序列化类。 dill(默认)直接序列化类,并且只能通过引用来选择。

>>> import dill
>>> 
>>> class Foo(object):
...   def __init__(self, x):
...     self.x = x
...   def bar(self, y):
...     return self.x + y * z
...   z = 1
... 
>>> f = Foo(2)
>>> 
>>> dill.dumps(f)  # the dill default, explicitly serialize a class
'\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x03Fooq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\r__slotnames__q\x0b]q\x0cU\n__module__q\rU\x08__main__q\x0eU\x03barq\x0fcdill.dill\n_create_function\nq\x10(cdill.dill\n_unmarshal\nq\x11Uyc\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00C\x00\x00\x00s\x0f\x00\x00\x00|\x00\x00j\x00\x00|\x01\x00t\x01\x00\x14\x17S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x01\x00\x00\x00xt\x01\x00\x00\x00z(\x02\x00\x00\x00t\x04\x00\x00\x00selft\x01\x00\x00\x00y(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x03\x00\x00\x00bar\x04\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x12\x85q\x13Rq\x14c__builtin__\n__main__\nh\x0fNN}q\x15tq\x16Rq\x17U\x01zq\x18K\x01U\x07__doc__q\x19NU\x08__init__q\x1ah\x10(h\x11Uuc\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00|\x01\x00|\x00\x00_\x00\x00d\x00\x00S(\x01\x00\x00\x00N(\x01\x00\x00\x00t\x01\x00\x00\x00x(\x02\x00\x00\x00t\x04\x00\x00\x00selfR\x00\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x08\x00\x00\x00__init__\x02\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x1b\x85q\x1cRq\x1dc__builtin__\n__main__\nh\x1aNN}q\x1etq\x1fRq utq!Rq")\x81q#}q$U\x01xq%K\x02sb.'
>>> dill.dumps(f, byref=True)  # the pickle default, serialize by reference
'\x80\x02c__main__\nFoo\nq\x00)\x81q\x01}q\x02U\x01xq\x03K\x02sb.'

不通过引用进行序列化更加灵活。然而,在极少数情况下,使用引用会更好(就像在酸洗基于 SwigPyObject 构建的东西时那样)。

我一直打算(大约 2 年)将 byref 标志暴露给 dump 内部的 pathos 调用,但还没有这样做。这样做应该是一个相当简单的编辑。我刚刚添加了一张票:https://github.com/uqfoundation/pathos/issues/58。当我在做的时候,也应该很容易打开替换pathos 使用的dumpload 函数……这样你就可以使用定制的序列化程序(即扩展那些dill 提供的序列化程序,或者使用其他序列化程序)。

【讨论】:

  • 太棒了!会定期检查您的票证,当然在编辑完成后尝试一下。
【解决方案2】:

在多处理函数中,进程间通信需要序列化。 Pickle 在这方面做得很差,而是通过 pip 安装dill。详细信息(有一个很好的星际迷航示例)可以在这里找到: http://matthewrocklin.com/blog/work/2013/12/05/Parallelism-and-Serialization/

【讨论】:

  • 感谢您的链接。通过星际迷航的例子,至少我明白了为什么必须腌制这些方法。但在上面的例子中,我已经在使用 pathos.multiprocessing,但仍然失败。
  • @barrios:我是pathosdill 的作者。 OP是正确的。 pathos 使用 dill 开箱即用。
  • 抱歉,不知道。
猜你喜欢
  • 1970-01-01
  • 2018-11-17
  • 1970-01-01
  • 2023-03-17
  • 2016-02-19
  • 2019-06-28
  • 2016-01-19
  • 1970-01-01
  • 2016-01-18
相关资源
最近更新 更多