并行执行实例方法[上一步:多重处理-实例变量被覆盖]

时间:2018-09-02 09:32:15

标签: python python-3.x multiprocessing

Pythonists,

这是我的班级定义,

class Test():
    def __init__(self, num):
        self.num = num
        self.out_come = multiprocessing.Manager.list()

    def func1(self):
        for n in range(self.num):
            self.out_come.append(numpy.random.randn(1)[0])
        return self.out_come

我正在实例化:

obj_l = []
for lettr in list(string.ascii_uppercase)[:5]:
    lettr = Test(0.2) # Initiating the class
    obj_l.append(lettr)

我想按以下方式并行运行实例方法:

proc = []
for n in range(len(obj_l)):
    proc.append(multiprocessing.Process(target=obj_l[n].func1, args=(param[n],))

for p in proc: p.start()
for p in proc: p.join()

但是,当我尝试访问函数self.out_come的结果时。我对所有对象都得到相同的结果。 self.out_come似乎被覆盖。如果我错了,请纠正我,并建议我如何并行运行实例方法。

EDIT-1:

问题似乎出在multiprocessing.Manager.list()上。寻找获得这项工作的方法。非常感谢您的帮助。

EDIT-2:

multiprocessing.Manager.list()只是访问self.out_come类的Test实例的代理。看起来,这种方式我只能访问代理,而不能访问每个单独的self.out_come实例。

我尝试了另一种使用Threading的方法。我无法实现自己想要的目标:每个self.out_come都要单独处理。但是,由于GIL,我没有任何提速。本质上,无需任何并行化即可串行运行。

我尝试使用multiprocessing.Queue,但没有成功。

还有其他建议/想法吗? (数字或Cython)

2 个答案:

答案 0 :(得分:2)

我认为您看到的问题是所有进程共享相同的随机种子,如果我修复代码中的错误并将随机种子添加到分布式函数中,那么一切似乎都可以正常工作。尝试用随机种子波纹管注释掉该行,然后再次运行。

import multiprocessing
import string
import numpy

class Test():
    def __init__(self, num):
        self.num = num
        self.out_come = multiprocessing.Manager().list()

    def func1(self):
        numpy.random.seed(self.num)
        for n in range(self.num):    
            self.out_come.append(numpy.random.randn(1)[0])
        return self.out_come

obj_l = []
for s in range(1, 6):
    lettr = Test(s) # Initiating the class
    obj_l.append(lettr)

proc = []
for n in range(len(obj_l)):
    proc.append(multiprocessing.Process(target=obj_l[n].func1))

for p in proc:
  p.start()
for p in proc:
  p.join()

for i in obj_l:
    print(i.out_come)

# [1.6243453636632417]
# [-0.4167578474054706, -0.056266827226329474]
# [1.7886284734303186, 0.43650985051198943, 0.09649746807200862]
# [0.05056170714293955, 0.499951333237829, -0.9959089311068651, 0.6935985082913116]
# [0.44122748688504143, -0.33087015189408764, 2.43077118700778, -0.2520921296030769, 0.10960984157818278]

还有几件事要记住,您不能将方法发送到另一个进程。您实际上正在做的是发送整个实例,然后在该实例上调用方法。我建议将您的分布式函数编写为具有显式参数的顶级函数,这样就可以清除进程之间传递的内容。这将有助于调试:)。

最后,我强烈建议您查看multiprocessing.Pool及其map方法,尤其是map_asyncimap_unordered。如果您可以将工作量表示为具有显式返回的函数,而不是对共享对象进行有状态的操作,那么从长远来看,编写代码和提高性能将更加容易。

答案 1 :(得分:-1)

为了完成而将其发布为答案:

对于那些想并行执行实例方法的人来说,Python似乎很困难。

我找到了一种使用CharmPy的方法。尽管这要求您所有类都是Chare父类的子类,但这是可以实现的,IMO。

它是在Charm++之上编写的,但是它是用C ++编写的分布式计算平台。

对那些人来说,这很有帮助,干杯!