如何在对象数组上并行化方法调用?

2021-04-11 15:35:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个由对象列表组成的模拟。我想对所有这些对象并行调用一个方法,因为它们都不依赖于另一个,使用线程池。无法对方法进行pickle,因此我考虑使用一个具有副作用的包装器函数来执行以下操作:

from multiprocessing import Pool

class subcl:
    def __init__(self):
        self.counter=1
        return
    def increment(self):
        self.counter+=1
        return

def wrapper(targ):
    targ.increment()
    return

class sim:
    def __init__(self):
        self.world=[subcl(),subcl(),subcl(),subcl()]
    def run(self):
        if __name__=='__main__':
            p=Pool()
            p.map(wrapper,self.world)

a=sim()
a.run()
print a.world[1].counter #should be 2

但是,函数调用不会对数组中的实际对象产生预期的副作用。有没有一种方法可以简单地用线程池和映射来处理这个问题,或者我必须按照原始函数调用和元组/列表/dicts来做所有事情(或者用多处理或其他一些并行性库来做得更详细些)?在

1条回答
网友
1楼 ·

混淆的主要原因是multiprocessing使用单独的进程而不是线程。这意味着子对象对对象状态所做的任何更改都不会自动对父对象可见。在

在您的示例中,处理此问题的最简单方法是让wrapper返回新值,然后使用Pool.map的返回值:

from multiprocessing import Pool

class subcl:
    def __init__(self):
        self.counter=1
        return
    def increment(self):
        self.counter+=1
        return

def wrapper(targ):
    targ.increment()
    return targ                                        # <<<<< change #1

class sim:
    def __init__(self):
        self.world=[subcl(),subcl(),subcl(),subcl()]
    def run(self):
        if __name__=='__main__':
            p=Pool()
            self.world = p.map(wrapper,self.world)     # <<<<< change #2

a=sim()
a.run()
print a.world[1].counter # now prints 2

相关问题