Python如何在类中进行多处理?

The*_*ear 15 python multiprocessing

我有一个代码结构,如下所示:

Class A:
  def __init__(self):
    processes = []
    for i in range(1000):
      p = Process(target=self.RunProcess, args=i)
      processes.append[p]

    # Start all processes
    [x.start() for x in processes]

  def RunProcess(self, i):
    do something with i...
Run Code Online (Sandbox Code Playgroud)

主要脚本:

myA = A()
Run Code Online (Sandbox Code Playgroud)

我似乎无法让它运行.我收到运行时错误" 在当前进程完成其自举阶段之前,已尝试启动新进程. "

如何让多个处理工作?如果我使用线程,它可以正常工作,但它和顺序一样慢...而且我也担心多次处理也会很慢,因为创建进程需要更长的时间?

任何好的提示?提前谢谢了.

Hal*_*Ali 8

我可以在您的代码中看到几个语法问题:

  • argsProcess期望一个元组,你传递一个整数,请将第5行更改为:

    p = Process(target=self.RunProcess, args=(i,))

  • list.append是一个方法,传递给它的参数应该包含在内(),而不是[]请将第6行更改为:

    processes.append(p)

正如@qarma指出的那样,在类构造函数中启动进程并不是一个好习惯.我将按如下方式构造代码(调整您的示例):

import multiprocessing as mp
from time import sleep

class A(object):
    def __init__(self, *args, **kwargs):
        # do other stuff
        pass

    def do_something(self, i):
        sleep(0.2)
        print('%s * %s = %s' % (i, i, i*i))

    def run(self):
        processes = []

        for i in range(1000):
            p = mp.Process(target=self.do_something, args=(i,))
            processes.append(p)

        [x.start() for x in processes]


if __name__ == '__main__':
    a = A()
    a.run()
Run Code Online (Sandbox Code Playgroud)

  • 为什么这不会抛出错误,因为它无法腌制该函数?我认为绑定函数不能被腌制。 (3认同)

Mik*_*rns 6

它应该简化您使用的过程Pool。就速度而言,启动过程确实需要时间。但是,使用a Pool(而不是运行njobsProcess应尽可能快地使其与进程一起运行。Pool(如下所示)的默认设置是使用最大可用进程数(即,您拥有的CPU数量),并在工作完成后立即将新工作分配给工人。您不会获得njobs并行方式,但是您将获得CPU可以处理的尽可能多的并行度,而不会超额使用处理器。我正在使用pathos,它有一个分支,multiprocessing因为它比标准的要强大一些multiprocessing……而且,我也是作者。但是您可能会multiprocessing为此使用。

>>> from pathos.multiprocessing import ProcessingPool as Pool
>>> class A(object):
...   def __init__(self, njobs=1000):
...     self.map = Pool().map
...     self.njobs = njobs
...     self.start()
...   def start(self):
...     self.result = self.map(self.RunProcess, range(self.njobs))
...     return self.result
...   def RunProcess(self, i):
...     return i*i
... 
>>> myA = A()
>>> myA.result[:11]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> myA.njobs = 3
>>> myA.start()  
[0, 1, 4]
Run Code Online (Sandbox Code Playgroud)

开始的Pool内部有点奇怪的设计__init__。但是,如果要执行此操作,则必须从类似self.result…的结果中获取结果,并且可以self.start用于后续调用。

到达pathos这里:https : //github.com/uqfoundation

  • 这将返回cPickle.PicklingError:无法腌制<type'function'>:属性查找__builtin __。function失败。有任何想法吗? (2认同)

Dim*_*nek 1

一个实际的解决方法是分解你的类,例如:

class A:
    def __init__(self, ...):
        pass

    def compute(self):
        procs = [Process(self.run, ...) for ... in ...]
        [p.start() for p in procs]
        [p.join() for p in procs]

    def run(self, ...):
        pass

pool = A(...)
pool.compute()
Run Code Online (Sandbox Code Playgroud)

当您在内部分叉一个进程时__init__,类实例self可能不会完全初始化,因此要求子进程执行是很奇怪的self.run,尽管从技术上来说,是的,这是可能的。

如果不是这样,那么这听起来像是这个问题的一个例子:

http://bugs.python.org/issue11240