简体   繁体   English

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

[英]How can I parallelize method calls on an array of objects?

I have a simulation that consists of a list of objects. 我有一个包含对象列表的模拟。 I'd like to call a method on all of those objects in parallel, since none of them depends on the other, using a thread pool. 我想使用线程池在所有这些对象上并行调用一个方法,因为它们都不依赖于另一个。 You can't pickle a method, so I was thinking of using a wrapper function with a side effect to do something like the following: 您不能腌制方法,因此我正在考虑使用具有副作用的包装器功能来执行以下操作:

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

However, the function call doesn't have the intended side effect on the actual objects in the array. 但是,函数调用对数组中的实际对象没有预期的副作用。 Is there a way to handle this simply with a thread pool and map, or do I have to do everything in terms of raw function calls and tuples/lists/dicts (or get more elaborate with multiprocessing or some other parallelism library)? 有没有一种方法可以通过线程池和映射来简单地处理此问题,还是我必须按照原始函数调用和元组/列表/字典进行所有操作(或者对多处理或其他并行库进行更详细的说明)?

The main source of confusion is that multiprocessing uses separate processes and not threads. 造成混乱的主要原因是, multiprocessing使用单独的进程而不是线程。 This means that any changes to object state made by the children aren't automatically visible to the parent. 这意味着,子级对对象状态所做的任何更改都不会自动显示给父级。

The easiest way to handle this in your example is to have wrapper return the new value, and then use the return value of Pool.map : 在您的示例中,处理此问题的最简单方法是让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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM