引子
因为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()