多进程发生内存溢出的解决办法
前言
昨天在编写一个多进程程序时,由于自己考虑不周,程序在启动后发生了内存溢出的故障。导致自己的程序卡死崩溃,电脑也陷入了死机黑屏的状态。见识到内存溢出的巨大威害后,觉得自己有必要好好了解一下编写多进程程序时的注意事项,特进行一个总结。
Bug复现
下面的这个程序是自己抽象简化后的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| import multiprocessing
import time
from random import randint
def func():
flag = randint(0, 1)
if flag:
time.sleep(2)
if __name__ == '__main__':
for _ in range(256):
process = multiprocessing.Process(target=func)
process.start()
|
抽象化后的程序主体就是这样子的,目标函数会由于情况的不同而选择立即退出或者说等待两秒再退出。
由于需要创建的进程可能会出现两秒的延时,当出现延时的进程十分多的时候就会发生内存溢出的惨案!
解决办法
1. 等待进程运行完毕
既然造成内存溢出的原因是同时运行的进程太多了,那我们就等待一个进程运行完后再运行另外一个进程不久行了吗?
1
2
3
4
5
6
7
8
9
10
11
| def func():
flag = randint(0, 1)
if flag:
time.sleep(2)
if __name__ == '__main__':
for _ in range(256):
process = multiprocessing.Process(target=func)
process.start()
process.join() # 等待进程运行退出
|
不过这样子和不使用多进程有什么区别吗。。。。真是一个睿(ruo)智的办法!
2. 创建进程池
我们限制一个最大进程数,只要开的进程数小于这个最大进程数,我们就为新任务创建进程,如果开的进程数大于等于了这个最大进程数,我们就让后面的新任务等待前面的任务完成之后再为他创建进程。
这样就能保证我们不会同时创建太多的进程,也就不会导致内存溢出的Bug了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| import multiprocessing
import time
from random import randint
def func():
flag = randint(0, 1)
if flag:
time.sleep(2)
if __name__ == '__main__':
pool = multiprocessing.Pool(multiprocessing.cpu_count()) # 设置进程池最大进程数为电脑CPU数量
for _ in range(256):
pool.apply_async(func)
pool.close()
pool.join()
|
这才真的是一个睿智的办法!
注意事项
创建多进程时一定要注意任务里有没有会阻塞进程的事件,如果有,一定要给他加一个超时机制!
一定要限制程序创建的最大进程数!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| ////////////////////////////////////////////////////////////////////
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
////////////////////////////////////////////////////////////////////
|