我正在尝试使用multiprocessing
的Pool.map()
函数来同时划分工作。当我使用以下代码时,它工作得很好:
import multiprocessing
def f(x):
return x*x
def go():
pool = multiprocessing.Pool(processes=4)
print pool.map(f, range(10))
if __name__== '__main__' :
go()
但是,当我在更面向对象的方法中使用它时,它就不起作用了。它给出的错误消息是:
PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup
__builtin__.instancemethod failed
当下面是我的主程序时,就会发生这种情况:
import someClass
if __name__== '__main__' :
sc = someClass.someClass()
sc.go()
下面是我的someClass
类:
import multiprocessing
class someClass(object):
def __init__(self):
pass
def f(self, x):
return x*x
def go(self):
pool = multiprocessing.Pool(processes=4)
print pool.map(self.f, range(10))
有谁知道这个问题是什么,或者是一个简单的解决方法?
发布于 2009-11-30 06:16:15
问题是多进程必须要在进程间进行访问,而绑定的方法是不可访问的。解决方法(无论您是否认为它“容易”;-)是将基础结构添加到您的程序中,以允许对此类方法进行酸洗,并将其注册到copy_reg标准库方法中。
例如,Steven Bethard对this thread的贡献(接近线程的末尾)展示了一种完全可行的方法,它允许通过copy_reg
进行方法酸化/取消酸化。
发布于 2014-01-25 09:11:46
所有这些解决方案都很丑陋,因为除非您跳出标准库,否则多处理和酸洗都会受到破坏和限制。
如果您使用一个名为pathos.multiprocesssing
的multiprocessing
分支,则可以直接在多处理的map
函数中使用类和类方法。这是因为使用了dill
而不是pickle
或cPickle
,而且dill
几乎可以序列化python中的任何内容。
pathos.multiprocessing
还提供了异步映射函数…它还可以使用多个参数(例如map(math.pow, [1,2,3], [4,5,6])
) map
函数
请参阅:What can multiprocessing and dill do together?
和:http://matthewrocklin.com/blog/work/2013/12/05/Parallelism-and-Serialization/
>>> import pathos.pools as pp
>>> p = pp.ProcessPool(4)
>>>
>>> def add(x,y):
... return x+y
...
>>> x = [0,1,2,3]
>>> y = [4,5,6,7]
>>>
>>> p.map(add, x, y)
[4, 6, 8, 10]
>>>
>>> class Test(object):
... def plus(self, x, y):
... return x+y
...
>>> t = Test()
>>>
>>> p.map(Test.plus, [t]*4, x, y)
[4, 6, 8, 10]
>>>
>>> p.map(t.plus, x, y)
[4, 6, 8, 10]
明确地说,你可以在第一时间做你想做的事情,如果你想做的话,你可以从解释器做。
>>> import pathos.pools as pp
>>> class someClass(object):
... def __init__(self):
... pass
... def f(self, x):
... return x*x
... def go(self):
... pool = pp.ProcessPool(4)
... print pool.map(self.f, range(10))
...
>>> sc = someClass()
>>> sc.go()
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>>
发布于 2011-08-08 04:40:36
您还可以在someClass()
中定义一个__call__()
方法,该方法调用someClass.go()
,然后将someClass()
的一个实例传递给池。这个对象是可拾取的,它工作得很好(对我来说)……
https://stackoverflow.com/questions/1816958
复制相似问题