引子
因为gil锁,就算python用了threading.Thread进行并发编程,一个cpu还是只能有一个线程同时执行。如何利用多个cpu呢,只有多进程了,每个进程中一个线程运行。
多进程
进程和线程的接口差不多,所以多进程的实现方式和多线程的实现方式也差不多。
调用方式一:
from multiprocessing import Process import time def f(name): time.sleep(1) print('hello',name,time.ctime()) if __name__ == '__main__': p_list = [] for i in range(3): #实例化对象 p = Process(target=f, args=('alvin',)) p_list.append(p) p.start() #开启进程1,2,3 for i in p_list: i.join() print('end')
hello yishu Thu May 3 14:51:26 2018 #可以看到,时间都是一样,当然了,我是四核cpu,利用了三个cpu,每个cpu同时开启一个进程。 hello yishu Thu May 3 14:51:26 2018 hello yishu Thu May 3 14:51:26 2018 end
通过继承的方式,开启多进程并行。
调用方式二:
from multiprocessing import Process import time class MyProce(Process): def __init__(self): super().__init__() #把父类Process的初始化初始化 def run(self): time.sleep(1) print("hello {} {}".format(self.name,time.ctime())) if __name__ == '__main__': p_list = [] for i in range(3): p = MyProce() p.start() p_list.append(p) for j in p_list: j.join() print("end")
进程通讯
进程不能同时共用同一份数据,和线程不一样。那,如何让进程之间互相交换全局变量呢?
进程通讯:让子进程取数据,主进程放数据。
pipe是双向管道。
from multiprocessing import Process, Pipe def f(conn): conn.send([12, {"name":"yuan"}, 'hello']) response=conn.recv() print("response",response) conn.close() print("q_ID2:",id(child_conn)) if __name__ == '__main__': parent_conn, child_conn = Pipe() print("q_ID1:",id(child_conn)) p = Process(target=f, args=(child_conn,)) p.start() print(parent_conn.recv()) # prints "[42, None, 'hello']" parent_conn.send("儿子你好!") p.join()
import multiprocessing as mp def job(q): res = 0 for i in range(1000): res += i #queue q.put(res) if __name__ == '__main__': q = mp.Queue() p1 = mp.Process(target=job, args= (q,)) p2 = mp.Process(target=job, args= (q,)) p1.start() p2.start() p1.join() p2.join() res1 = q.get() res2 = q.get() print(res1 + res2)
import multiprocessing as mp def job(x): return x*x def multicore(): pool = mp.Pool(processes=2) #只用2个核 自动分配进程和cpu res = pool.map(job,range(10)) print(res) rest = pool.apply_async(job,(2,)) #只能输入一个值 一次只能在一个进程算一个 print(rest.get()) muti_result = [pool.apply_async(job,(i,)) for i in range(10)] print([rest.get() for j in muti_result]) if __name__ == '__main__': multicore()