10.4.17 进程池
有些情况下,所要完成的工作可以分解并独立地分布到多个工作进程,对于这种简单的情况,可以用Pool类来管理固定数目的工作进程。会收集各个作业的返回值并作为一个列表返回。池(pool)参数包括进程数以及启动任务进程时要运行的函数(对每个子进程调用一次)。
import multiprocessing
def do_calculation(data):
return data * 2
def start_process():
print('Starting',multiprocessing.current_process().name)
if __name__ == '__main__':
inputs = list(range(10))
print('Input :',inputs)
builtin_outputs =list(map(do_calculation,inputs))
print('Built-in:',builtin_outputs)
pool_size = multiprocessing.cpu_count() * 2
pool = multiprocessing.Pool(
processes=pool_size,
initializer=start_process,
)
pool_outputs = pool.map(do_calculation,inputs)
pool.close() # No more tasks
pool.join() # Wrap up current tasks.
print('Pool :',pool_outputs)
map()方法的结果在功能上等价于内置map()的结果,只不过各个任务会并行运行。由于进程池并行地处理输入,可以用close()和join()使任务进程与主进程同步,以确保完成适当的清理。
运行结果:
默认地,Pool会创建固定数目的工作进程,并向这些工作进程传递作业,直到再没有更多作业位置。设置maxtasksperchild参数可以告诉池在完成一些任务之后要重新启动一个工作进程,来避免长时间运行的工作进程消耗更多的系统资源。
import multiprocessing
def do_calculation(data):
return data * 2
def start_process():
print('Starting',multiprocessing.current_process().name)
if __name__ == '__main__':
inputs = list(range(10))
print('Input :',inputs)
builtin_outputs = list(map(do_calculation,inputs))
print('Built-in:',builtin_outputs)
pool_size = multiprocessing.cpu_count() * 2
pool = multiprocessing.Pool(
processes=pool_size,
initializer=start_process,
maxtasksperchild=2,
)
pool_outputs = pool.map(do_calculation,inputs)
pool.close() # No more tasks
pool.join() # Wrap uo current tasks.
print('Pool :',pool_outputs)
池完成其分配的任务时,即使并没有更多工作要做,也会重新启动工作进程。从下面的输出可以看到,尽管只有10个任务,而且每个工作进程一次可以完成两个任务,但是这里创建了8个工作进程。
运行结果: