什么是多进程?
多进程 Multiprocessing 和多线程 threading 类似, 他们都是在 python 中用来并行运算的. 不过既然有了 threading, 为什么 Python 还要出一个 multiprocessing 呢? 原因很简单, 就是用来弥补 threading 的一些劣势, 比如在 threading 教程中提到的GIL.
上一节我们了解到了多线程,多线程和多进程的运用十分相似:
#多进程和多线程进行比较
import multiprocessing as mp
import threading as td
def job(a,b):
print("aaa")
def adding():
t=td.Thread(target=job,args=(1,2))
p=mp.Process(target=job,args=(1,2))
t.start()
p.start()
t.join()
p.join()
if __name__=="__main__":
adding()
存储进程输出
Queue的功能是将每个核或线程的运算结果放在队里中, 等到每个线程或核运行完毕后再从队列中取出结果, 继续加载运算。原因很简单, 多线程调用的函数不能有返回值, 所以使用Queue存储多个线程运算的结果
import multiprocessing as mp
from queue import Queue
def job(q):
res=0
for i in range(1000):
res+=i+i**2
q.put(res)
def adding_mp():
res1=mp.Process(target=job,args=(q,))
res2 = mp.Process(target=job, args=(q,))
res1.start()
res1.join()
res2.start()
res2.join()
if __name__=="__main__":
q=mp.Queue()
adding_mp()
res1=q.get()
res2 = q.get()
print(res1+res2)
Multiprocessing和Threading的对比
可以运行下面例子看出来,多线程比什么多不用还要慢一点(对于纯运算,没用到多核的优势)
当运算工作量很大时(累加10000000),多进程的优势就体现出来了,快了近一倍(可能是我双核)
但是如果工作量不大(可以把100000000改小试试),多进程反而慢,可能是因为创建进程的时间更长
import multiprocessing as mp
import threading as td
import time
def job(q):
res = 0
for i in range(10000000):
res += i+i**2+i**3
q.put(res)
def multcore(): #多进程运算
q = mp.Queue()
p1 = mp.Process(target=job, args=(q,)) #加逗号说明args是可迭代的东西后面还能加东西
p2 = mp.Process(target=job, args=(q,))
p1.start()
p2.start()
p1.join()
p2.join()
res1 = q.get()
res2 = q.get()
print('multcore:',res1+res2)
def normal(): #什么都不用
res = 0
for _ in range(2):
for i in range(10000000):
res += i + i ** 2 + i ** 3
print('normal:',res)
def multithread(): #多线程
q = mp.Queue()
t1 = td.Thread(target=job, args=(q,)) # 加逗号说明args是可迭代的东西后面还能加东西
t2 = td.Thread(target=job, args=(q,))
t1.start()
t2.start()
t1.join()
t2.join()
res1 = q.get()
res2 = q.get()
print('multthread:',res1 + res2)
if __name__ == '__main__':
st = time.time()
normal()
st1 = time.time()
print('normal time:',st1 - st)
multithread()
st2 = time.time()
print('multithread time:',st2 - st1)
multcore()
st3 = time.time()
print('mulcore time:',st3 - st2)
进程池pool: 进程池就是我们将所要运行的东西,放到池子里,Python会自行解决多进程的问题
import multiprocessing as mp
import threading as td
import time
def job(x):
return x*x
def multcore():
pool = mp.Pool(processes=2) #定义一个pool,定义数字告诉系统使用几个核
# mp.Process不能接受返回值,但是pool可以接受返回值
res = pool.map(job,range(10000)) #往pool放入函数和传入的值,会自动分配给每个进程
print(res)
res = pool.apply_async(job,(2,)) #传入一个值给一个核运行
print(res.get()) #拿出返回值
multi_res = [pool.apply_async(job,(i,)) for i in range(10)] #通过迭代传入多个值
print([res.get() for res in multi_res]) #结果也要一个个拿
if __name__ == '__main__':
multcore()
lock锁:
import multiprocessing as mp
import time
def job(v, num, l):
l.acquire() # 锁住
for _ in range(5):
time.sleep(0.1)
v.value += num # 获取共享内存
print(v.value)
l.release() # 释放
def multicore():
l = mp.Lock() # 定义一个进程锁
v = mp.Value('i', 0) # 定义共享内存
p1 = mp.Process(target=job, args=(v,1,l)) # 需要将lock传入
p2 = mp.Process(target=job, args=(v,3,l))
p1.start()
p2.start()
p1.join()
p2.join()
if __name__ == '__main__':
multicore