This question already has answers here:
Multiprocessing: How to use Pool.map on a function defined in a class?
(17个答案)
3年前关闭。
问题描述
我有一些代码刚刚开始尝试在Python 3.5中加速。我正在尝试使用
从顺序上讲,代码更简单。
使整个事情复杂化的是,程序的顶层通过传递函数
这可以正常工作。但这很慢。这是我尝试使用多处理模块重写Momma类的尝试。
然后我尝试运行它:
但是我得到了错误:
对this stackoverflow question的回答是“只有在模块的顶层定义了功能,这些功能才是可腌制的”。该语句看起来似乎要实现此目的的唯一方法是通过在
我的问题##
(编辑了一下)
有什么解决方法吗?假设我不能在类之外定义映射函数。还要假设在
顺便说一句,以下代码不会引发错误,但是可能会继续进行某些复制,因为构成的Baby对象没有任何反应。
您需要在
现在,您可以从
因此,现在,当您调用
我上面链接的一个答案说,您也可以执行以下操作:
...将全局方法放入类。
(17个答案)
3年前关闭。
问题描述
我有一些代码刚刚开始尝试在Python 3.5中加速。我正在尝试使用
multiprocessing
模块来完成此任务。这是一个最小的示例来演示我正在尝试做的事情。从顺序上讲,代码更简单。
Momma_Serial
类内部有一个Baby
对象的列表。有时,我们想对每个调用Baby.evolve()
方法。实际上,将有很多这些Baby
对象(在此示例中只有100个)。这是寻求并行性的最初动机。使整个事情复杂化的是,程序的顶层通过传递函数
Baby
来告诉如何在许多pass_this_func()
对象中的每个对象上完成此操作。此函数是Momma_Serial.evolve_all_elems()
的参数,并传递给该momma对象内的所有小baby对象。class Baby:
def __init__(self, lol):
self.lol = lol
def evolve(self, f):
self.lol = f(self.lol)
def pass_this_func(thing):
return( 2 * thing )
class Momma_Serial:
def __init__(self, num):
self.my_list = [Baby(i) for i in range(num)]
def evolve_all_elems(self, the_func):
for baby in self.my_list:
baby.evolve(the_func)
momma1 = Momma_Serial(100)
[baby.lol for baby in momma1.my_list]
momma1.evolve_all_elems(pass_this_func)
[baby.lol for baby in momma1.my_list]
这可以正常工作。但这很慢。这是我尝试使用多处理模块重写Momma类的尝试。
import multiprocessing as mp
class Momma_MP:
def __init__(self, num):
self.my_list = [Baby(i) for i in range(num)]
def evolve_all_elems(self, the_func):
num_workers = 2
def f(my_obj):
my_obj.evolve(the_func)
with mp.Pool(num_workers) as pool:
pool.map(f, self.my_list)
然后我尝试运行它:
momma2 = Momma_MP(100)
[baby.lol for baby in momma2.my_list]
momma2.evolve_all_elems(pass_this_func) #error comes here
# [baby.lol for baby in momma2.my_list]
但是我得到了错误:
AttributeError: Can't pickle local object 'Momma_MP.evolve_all_elems.<locals>.f'
对this stackoverflow question的回答是“只有在模块的顶层定义了功能,这些功能才是可腌制的”。该语句看起来似乎要实现此目的的唯一方法是通过在
Momma_MP
类之外定义一个函数。但是我真的不想这样做,因为这会给我的代码带来很多问题。我的问题##
(编辑了一下)
有什么解决方法吗?假设我不能在类之外定义映射函数。还要假设在
Momma()
顶级脚本环境中未实例化__main__
。另外,我也不想偏离这个程序设计,因为我希望所有这些Baby()实例都被抽象掉了。我不希望实例化实例或与Momma()
实例进行交互的场所/程序不必担心或知道与Baby()
类有关的任何事情。这些额外的限制使问题与情况here略有不同。顺便说一句,以下代码不会引发错误,但是可能会继续进行某些复制,因为构成的Baby对象没有任何反应。
def outside_f(obj):
obj.evolve(pass_this_func)
class Momma_MP:
def __init__(self, num):
self.my_list = [Baby(i) for i in range(num)]
def evolve_all_elems(self, the_func):
num_workers = 2
with mp.Pool(num_workers) as pool:
pool.map(outside_f, self.my_list)
momma2 = Momma_MP(100)
[baby.lol for baby in momma2.my_list]
momma2.evolve_all_elems(pass_this_func)
[baby.lol for baby in momma2.my_list] # no change here?
最佳答案
我将尝试给出一个其他地方找不到的答案(请参见上面的评论)。我将假设您有具有不同f()
功能的不同类型的Momma。
您可以使一个功能evolver()
:
def evolver(baby):
momma = baby.momma
momma.evolve(baby)
您需要在
self.momma
的__init__()
中分配Baby
,将Momma
实例传递给Baby
:class Baby:
def __init__(self, lol, momma):
self.lol = lol
self.momma = momma
现在,您可以从
Momma
派生来覆盖evolve()
方法,以专门化evolve()
函数。因此,现在,当您调用
pool.map(evolver, babies)
时,它将把baby
传递给evolver()
,然后,它将要求momma
传递给evolve()
baby
。我上面链接的一个答案说,您也可以执行以下操作:
class Momma:
evolver = staticmethod(evolver)
...将全局方法放入类。
09-25 19:39