Skip to content

Python multiprocessing #10

@warvyvr

Description

@warvyvr

1 简介

最近一段时间由于用到了Python的multiprocessing,在这里对multiprocessing的使用做一个总结。
由于CPython使用GIL (Global Interpreter Lock)来是的Python能够定位和访问要执行的代码的位置,那么造成了Python在multithread的情况下,仍然是串行执行的方式。
由于GIL是进程级别的,那么multiprocessing就是用多进程的方式来进行并行执行来提高系统CPU使用率的目的。

2 基本代码样式

multithread和multiprocessing的代码基本类似,可以使用函数作为worker的执行主体,也可以使用类继承的方式来执行worker的执行单元。
multi-thread version:

from threading import Thread
class MyThread(Thread):
    def __init__(self):
        Thread.__init__(self):
    def run(self):
        a, b = 0, 1
        for i in range(0,100000):
            a, b = b, a+b

if __main__ == "__main__":
    t = MyThread()
    t.start()
    t.join()

multiprocessing version:

from multiprocessing import Process
class MyProcess(Process):
    def __init__(self):
        Thread.__init__(self):
    def run(self):
        a, b = 0, 1
        for i in range(0,100000):
            a, b = b, a+b

if __main__ == "__main__":
    p = MyProcess()
    p.start()
    print p.pid
    print p.join()
    print p.exitcode

3 性能

由于GIL问题导致多线程的性能问题远低于多进程,甚至数倍于单线程版本:
performance

4 apply和map函数

applymap函数分别用于启动单一进程和启动一批次的worker进程的函数,例如

def foo(arg):
  return isprime(arg)

for i in range(0,10):
    result = apply(foo, i)          

上述例子并不是一个真实的多进程使用的apply函数的例子,该函数启动foo进程用于计算该参数是否是个质数。并将结果返回,当apply函数返回后,进入下一i的循环,再次启动另外一个新的实例来执行。也就是说该进程用apply启动的方式是阻塞方式(相对于main进程来说)。
如果主进程不希望被阻塞,那么使用apply_async函数,该函数需要另外一个callback参数,该参数用于指定的一个接收该进程返回结果的处理函数。该回调函数将接收一个为AsyncResult类型的参数。进程foo的执行结果在AsyncResult.get()中。该函数被main进程调用,而不是worker process。被apply_async启动起来的进程是不能保证进程的启动顺序的,这一点要注意。apply(foo)相当于apply_async_foo).get()`

map函数用于启动一组函数,map函数接收一个可以迭代的集合并将该集合均分到启动的函数中,例如:

 a = range(0,100)
def foo(args):
  return [isprime(i) for i in args]

pool=MultiProcessing.Pool(foo,number=10)
results=pool.map(foo,a, 10)

上述大致的代码将启动10个foo进程,每一个将处理10个数字。返回的结果也将保存在一个数组中。
map函数也有对应的async版本 -- map_async,同样也不能保证进程的执行顺序。

如果使用async版本的启动函数,那么在主进程中需要使用pool.join来等待worker进程的结束。

4 RPC

可以使用Multiprocessing中的Pipe或者Queue来进行进程通信,Pipe也可以通过MultiProcessing.Manager将该对象绑定到端口上来实现cross node的通信。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions