Python多处理文档示例

时间:2013-08-11 05:15:22

标签: python multithreading multiprocessing

我正在尝试学习Python多处理。

http://docs.python.org/2/library/multiprocessing.html来自“要显示所涉及的各个进程ID,这是一个扩展示例:”

from multiprocessing import Process
import os

def info(title):
    print title
    print 'module name:', __name__
    if hasattr(os, 'getppid'):  # only available on Unix
        print 'parent process:', os.getppid()
    print 'process id:', os.getpid()

def f(name):
    info('function f')
    print 'hello', name

if __name__ == '__main__':
    info('main line')
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()

我究竟在看什么?我看到def f(name):在info('main line')完成后被调用,但是这个同步调用仍然是默认的。我看到相同的进程信息('主线')是def f(name)的父PID:但不确定那是什么'多处理'。

此外,使用join()“阻止调用线程,直到调用其join()方法的进程终止”。我不清楚调用线程是什么。在这个例子中,join()会阻塞什么?

1 个答案:

答案 0 :(得分:25)

multiprocessing如何运作,简而言之:

  • Process()在类Unix系统上产生(fork或类似的)原始程序的副本(在Windows上,缺少真正的fork,这很棘手,需要特殊的关心模块文档注意事项)。
  • 副本与原文进行通信,以确定(a)它是副本,(b)它应该关闭并调用target=函数(见下文)。
  • 此时,原件和副本现在不同且独立,并且可以同时运行。

由于这些是独立的进程,它们现在具有独立的全局解释器锁(在CPython中),因此两者都可以在多CPU盒上使用高达100%的CPU,只要它们不竞争其他更低的CPU级别(OS)资源。这就是“多处理”部分。

当然,在某些时候,您必须在这些假设独立的进程之间来回发送数据,例如,将一个(或多个)工作进程的结果发送回“主”进程。 (偶尔有一个例外,每个人都完全独立,但很少见......加上整个启动序列本身,由p.start()启动。)所以每个创建的Process实例 - {{1在上面的示例中,有一个与其父创建者的通信通道,反之亦然(它是一个对称连接)。 p模块使用multiprocessing模块将数据转换为字符串 - 可以隐藏在pickle文件中的相同字符串 - 并通过渠道发送数据,“向下”发送给工作人员发送论据等,并从工人那里“向上”发回结果。

最终,一旦你完成了获得结果,工作人员就完成了(通过从pickle.dump函数返回)并告诉父母它已经完成了。为了确保所有内容都被关闭和清理,父进程应该调用target=来等待工作者的“我已经完成”消息(实际上是Unix-ish sysems上的操作系统级p.join())。

这个例子有点傻,因为两条打印的消息基本上没有时间,所以“同时”运行它们没有可测量的收益。但是假设不是打印exit,而是hello来计算π的前100,000个数字(3.14159 ...)。然后,您可以生成另一个fProcess,其中包含另一个目标p2,用于计算e的前100,000个数字(2.71828 ...)。这些将独立运行。然后,父母可以调用gp.join()来等待两者完成(或者产生更多的工作人员来完成更多的工作并占用更多的CPU,甚至可以在一段时间内完成自己的工作)。