1.多进程的目的还是为了提升cpu的处理效率
- multiprocessing
- Process
- start 启动进程
- join 等待进程结束
- Process
-
案例一. 对列表分段求和
-
采用多进程
-
from multiprocessing import Process ,Pool import time import os import sys sys.path.append("/mnthis/qihao.huang/tools/") from utils import * def test(x,start,end): # x为一个list return sum(x[start:end]) print(get_now()) x=list(range(400000000)) p1=Process(target=test,args=(x,0,100000000,)) p2=Process(target=test,args=(x,100000000,200000000,)) p3=Process(target=test,args=(x,200000000,300000000,)) p4=Process(target=test,args=(x,300000000,400000000,)) p1.start() #启动进程 p2.start() p3.start() p4.start() p1.join() ##等待所有的子进程执行结束, 再执行主进程 p2.join() p3.join() p4.join() print(get_now())
输出:
-
2022-03-23 02:08:14
-
2022-03-23 02:11:59 只需要3分45秒
2.不采用多进程,顺序执行
print(get_now())
test(x,0,100000000)
test(x,100000000,20000000)
test(x,200000000,300000000)
test(x,300000000,400000000)
print(get_now())
输出:
2022-03-23 02:12:00
2022-03-23 02:25:59 需要13分59秒
2.如果管理很多个进程,怎么办?通过进程池来
- multiprocessing
- Pool 进程池
- apply 阻塞
- apply_async 非阻塞
- Pool 进程池
案例二. 进程池如何管理
1.非阻塞方式,采用apply_async
# 定义睡觉(sj)函数
def sj(x):
time.sleep(x)
print(get_now())
pool=Pool(processes=4) # 维持4个,
for i in [1,2,3,4,5,6]:
pool.apply_async(sj,args=(i,))
pool.close() # 不让新的进程进来的
pool.join()
print(get_now())
输出:
2022-03-23 03:24:26
2022-03-23 03:24:34 需要8秒,为什么是8秒?下面进行分析下
# 第1秒 进程1结束,进程5进去
# 第2秒,进程2结束,进程6进去
# 第3秒,进程3结束
# 第4秒,进程4结束
# 第5秒,
# 第6秒,进程5结束
# 第7秒
# 第8秒,进程6结束
2.阻塞方式,需要多少秒?21秒(1+2+3+4+5+6)
# 进程池的方式
print(get_now())
pool=Pool(processes=4) # 维持4个,
for i in [1,2,3,4,5,6]:
pool.apply(sj,args=(i,))
pool.close() # 不让新的进程进来的
pool.join()
print(get_now())
案例三. 子进程的结果如何拿到
- 调用get() 方法即可
import pandas as pd
pool=Pool(processes=4)
result=pd.DataFrame()
for ele in [[1,2],[2,3],[3,4]]:
result=pd.concat([result,pool.apply_async(get_data,args=(ele,)).get()],axis=1)
pool.close() # 不让新的进程进来的
pool.join()
print(get_now())
print(result)
案例四.map方式执行进程池,
其实就是把for循环改成map,直接返回List
import pandas as pd
pool=Pool(processes=cpu_count())
pool.map(get_data,[[1,2],[2,3],[3,4]])
3.针对同一份数据,并发会不会引起数据的混乱?
用Lock,即锁的方式进行解决
# 不加锁的方式
def getList(L,i):
print(L[:i])
if __name__ == '__main__':
ll=["1","2","3","4","5"]
manager = multiprocessing.Manager().Lock()
pool=Pool(processes=cpu_count())
for i in range(5):
pool.apply_async(getList,args=(ll,i,))
pool.close() # 不让新的进程进来的
pool.join()
# 加锁的方式,其实会串行执行
def getList(L,i,lock):
lock.acquire()
print(L[:i])
lock.release()
if __name__ == '__main__':
ll=["1","2","3","4","5"]
manager = multiprocessing.Manager().Lock()
pool=Pool(processes=cpu_count())
for i in range(5):
pool.apply_async(getList,args=(ll,i,lock,))
pool.close() # 不让新的进程进来的
pool.join()