为什么会有进程池的概念?
当我们开启50个进程让他们都将100这个数减1次减到50,你会发现特别慢!
效率问题,原因:
1,开辟内存空间。因为每开启一个进程,都会开启一个属于这个进程池的内存空间,因为进程与进程之间数据是完全隔离的。
2,并且这些独立的内存空间会有许多寄存器,堆栈,文件等,他们存着这个进程里面的变量和数据等。所以生成这些东西都会耗时。
3,生成这么多进程,都需要系统调度,这个也会耗时。不仅这样,还会涉及到进程使用cpu的时候,当a进程使用一段时间cpu,b进程要去使用cpu,za和b中间的节点不仅要记录a进程执行到这,还要调用b进程之前执行的结果,所以在这个节点不仅涉及到cpu的切换,还涉及到寄存器,堆栈等包含的数据,还有内存空间的切换。
所以,我们不会无休止的去开启进程,而是设计一个池子,这个池子就是进程池。
进程池的含义?
python中的进程池,在你还没有创建进程之前,先创建一个属于进程的池子。这个池子指定能存放多少个进程,比如说5个进程,因此会先创建这5个进程。当任务进来的时候,比如说50个任务需要50个进程去处理,但是不会生成50个进程,而是排队去进程池里面拿进程处理任务,所以同一时刻最多有5个进程在处理任务,当任务处理完毕,不会将进程销毁,而是放回到进程池,在让其他任务进来让这些进程处理。
所以,进程池的优点有:
1,提高效率,节省开辟进程和开辟内存空间的时间及销毁进程的时间。
2,节省内存空间。
更高级的进程池:
这种进程池不给设置固定数量的进程,而是有一个范围,比如最少3个进程,最多30个进程。当任务或用户量增加时,进程池里面的进程数量会加加加,一直加到最大值,当任务或用户量减少,造成很多进程长时间没用,就会减减减,直到减到最小值。这样做的好处会系统回收用不到的进程,会给操作系统减负。
但是python里面只有第一种进程池,他不会将进程池进行收缩。
怎么使用?如下代码:
from multiprocessing import Pool def func(n): for i in range(3): print(n +1) # 将传入的值打印三次,1到10每个值打印三次 if __name__ == "__main__": pool = Pool(5) # 创建了一个包含5个进程的进程池 pool.map(func, range(10)) # 这样用map就起进程了,另外range(10)这个位置传的值一定要是可迭代的,map只能传可迭代的。10个任务
# map是异步的,并且不需要close()和join(),并且把每一个返回值放到一个列表中,直接显示出来。
进程池的效率测试:
from multiprocessing import Pool import time def func(n): for i in range(10): # 将1到100,每个数打印十次 print(n +1) if __name__ == "__main__": start = time.time() pool = Pool(5) pool.map(func, range(100)) # 一百个任务 t2 = (time.time() - start) print(t2) # 打印花费时间,时间是0.26130008697509766
然后看起100个进程去处理相同数量的任务:
from multiprocessing import Process import time def func(n): for i in range(10): # 同样将1到100,每个数打印十次 print(n+1) if __name__ == "__main__": t1 = time.time() p_list = [] for i in range(100): p = Process(target=func, args=(i,)) p_list.append(p) p.start() for p in p_list: p.join() t2 = (time.time() - t1) print(t2) # 3.882610321044922
对比时间差别太大了,进程池的5个进程却比创建100个进程做同样的事儿快的太多了。
合并到同一个代码里面再看效果:
from multiprocessing import Process, Pool import time
def func(n): for i in range(10): print(n + 1) if __name__ == "__main__": t1 = time.time() pool = Pool(5) pool.map(func, range(100)) t2 = time.time() - t1 t3 = time.time() p_list = [] for i in range(100): p = Process(target=func, args=(i,)) p_list.append(p) p.start() for p in p_list: p.join() t4 = time.time() - t3 print(t2, t4)
打印结果:
0.2582840919494629 4.1498963832855225
所以,进程池的效率比开多个进程效率高得多。