为啥用multiprocessing?
*现在cpu都多核了, 写大型程序你还在用单线程的传统写法?很不fashion而且效率很低, 你out了。
*那用multi-threading不就结了?C语言可以, 编译完执行没问题。 但是python这种解释型的语言用多线程就不行了, python的multithreading效率并不高。据说是受制于GIL (global interpreter lock) 的锁机制, 该锁只能工作于单个cpu core。这样别的cpu core干着急也帮不上忙。
*那怎么办呢? 自己fork一堆子进程,然后管理呗? 呵呵,DIY?这不是重新造轮子吗。
*亲, 用python现成的multiprocessing库吧。支持多个cpu core,简直就是为了多核cpu打造的, python 2.6之后都支持。
来点sample,
*sample 1, 创建process, target=f 函数名, args传递参数
from multiprocessing import Process
def f(name):
print 'hello', name
if __name__ == '__main__':
p = Process(target=f, args=('bob',))
p.start()
p.join()
*sample2.1, 支持队列
from multiprocessing import Process, Queue
def f(q):
q.put([42, None, 'hello'])
if __name__ == '__main__':
q = Queue()
p = Process(target=f, args=(q,))
p.start()
print q.get() # prints "[42, None, 'hello']"
p.join()
Sample 2.2, 支持Pipe
from multiprocessing import Process, Pipe
def f(conn):
conn.send([42, None, 'hello'])
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=f, args=(child_conn,))
p.start()
print parent_conn.recv() # prints "[42, None, 'hello']"
p.join()
Sample3, 支持Pool, 雇一群worker来干活
from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__':
pool = Pool(processes=4) # start 4 worker processes
result = pool.apply_async(f, (10,)) # evaluate "f(10)" asynchronously
print result.get(timeout=1) # prints "100" unless your computer is *very* slow
print pool.map(f, range(10)) # prints "[0, 1, 4,..., 81]"
it = pool.imap(f, range(10))
print it.next() # prints "0"
print it.next() # prints "1"
print it.next(timeout=1) # prints "4" unless your computer is *very* slow
import time
result = pool.apply_async(time.sleep, (10,))
print result.get(timeout=1) # raises TimeoutError
其他高级的特性, 比如Manager类,shared memory,请看官网文档,参考文献2
注意事项:
* 在UNIX平台上,当某个进程终结之后,该进程需要被其父进程调用wait,否则进程成为僵尸进程(Zombie)。所以,有必要对每个Process对象调用join()方法 (实际上等同于wait)。对于多线程来说,由于只有一个进程,所以不存在此必要性。
* multiprocessing提供了threading包中没有的IPC(比如Pipe和Queue),效率上更高。应优先考虑Pipe和Queue,避免使用Lock/Event/Semaphore/Condition等同步方式 (因为它们占据的不是用户进程的资源)。
* 多进程应该避免共享资源。在多线程中,我们可以比较容易地共享资源,比如使用全局变量或者传递参数。在多进程情况下,由于每个进程有自己独立的内存空间,以上方法并不合适。此时我们可以通过共享内存和Manager的方法来共享资源。但这样做提高了程序的复杂度,并因为同步的需要而降低了程序的效率。
Reference:
[1] http://www.ibm.com/developerworks/aix/library/au-multiprocessing
[2] http://docs.python.org/2/library/multiprocessing.html
[3] http://blog.csdn.net/jj_liuxin/article/details/3564365
[4] http://www.cnblogs.com/vamei/archive/2012/10/12/2721484.html