1. multiprocessing模块介绍
Python中的multiprocessing模块是一个用于支持多进程编程的标准库,通过multiprocessing可以同时在多个CPU上运行Python代码,从而实现多进程编程,增强程序的并发处理能力,提升编程效率。multiprocessing实现了Unix/Linux下的fork()方法来创建进程,然而,由于Windows系统不支持fork()方法,所以multiprocessing在Windows系统下另外开发了一个Python模块,称为“代理模块”。
2. multiprocessing模块使用方法
2.1 创建进程
multiprocessing模块提供了多个类可用于创建进程,常用的有Process和Pool。Process类可以创建单个进程,Pool类可以创建一组进程,称为进程池。创建进程的方法与线程类似,首先需要创建一个进程对象,如下所示:
import multiprocessing
def worker():
print("This is worker")
p = multiprocessing.Process(target=worker)
p.start()
代码中的multiprocessing.Process类用于创建一个进程实例,其中target参数用于指定需要在进程中执行的函数,start()方法用于启动进程。
2.2 进程间通信
多个进程之间可以使用队列、管道等方式进行通信,multiprocessing模块中提供了Pipe、Queue等工具类,用于实现进程间通信。下例演示了两个进程之间通过管道进行通信的过程:
import multiprocessing
def worker(conn):
conn.send('worker to main')
print('from main:', conn.recv())
if __name__ == '__main__':
parent_conn, child_conn = multiprocessing.Pipe()
p = multiprocessing.Process(target=worker, args=(child_conn,))
p.start()
print('from worker:', parent_conn.recv())
parent_conn.send('main to worker')
p.join()
代码中两个进程之间通过Pipe类进行通信,先创建一个管道,调用Pipe方法得到管道的两个端点parent_conn和child_conn,父进程parent_conn对管道写,子进程child_conn对管道读,故其中一个进程先调用recv()方法来接收消息,另一个进程再调用send()方法来发送消息。
3. 进程池Pool的用法
常用的创建Pool的方式为multiprocessing.Pool,其中也可以传递参数processes来指定进程池的大小,默认是CPU核心数。对于CPU密集型任务,将进程数量设置为CPU核心数较为合理。下例演示了如何使用进程池创建多个进程来执行任务:
import multiprocessing
import time
def worker(num):
time.sleep(1)
print(num)
if __name__ == '__main__':
pool = multiprocessing.Pool()
for i in range(5):
pool.apply_async(worker, (i,))
pool.close()
pool.join()
上述代码中,首先通过multiprocessing.Pool()创建进程池对象,然后通过apply_async方法向进程池中添加任务,其中worker为任务函数,(i,)为任务函数的参数。
4. 进程池中map、imap、imap_unordered方法的用法
4.1 map方法
map()方法可以向进程池中传入多个参数,并自动均分参数到各个进程中,并返回各进程的执行结果,比较适用于小数据规模的处理。以下是一段使用map方法的示例:
import multiprocessing
import time
def worker(x):
return x ** 2
if __name__ == '__main__':
pool = multiprocessing.Pool()
results = pool.map(worker, [1, 2, 3, 4, 5])
print(results)
pool.close()
上述代码中,我们定义了一个worker()方法用来执行任务,然后使用Pool的map()方法来执行任务,传入的参数为[1,2,3,4,5]。执行任务之后,map()方法会自动将不同参数分配到不同的进程中,并将各进程的结果汇总起来。
4.2 imap方法
imap()方法是map()方法的改进,它可以实现异步处理,即不要等所有进程都做完,就可以立即获取结果。当进程池已满时,imap()方法会自动阻塞,直到有进程空闲出来。
import multiprocessing
import time
def multisq(n):
return n*n
if __name__ == '__main__':
pool = multiprocessing.Pool()
results = pool.imap(multisq, [1,2,3,4,5])
print(list(results))
pool.close()
上述代码中,我们定义了一个multisq()方法,用来执行任务,并传入参数[1,2,3,4,5]。我们通过Pool的imap()方法来执行任务,得到的结果是一个迭代器。需要使用list()函数转换为列表,才能得到结果。此外,imap_unordered()方法与imap()方法类似,不同之处是,结果的顺序与调用顺序不一定一致,取决于该进程最先完成任务的进程。
5. 实际应用
在实际应用中,多进程处理常用于计算密集型任务,其实就是指需要大量计算和处理的任务,包括数据的处理、模型的训练以及启动大量子进程等。在实际操作中,需要根据任务特性选择不同进程管理方案,比如使用Pool可以方便地实现进程池,不需要关注进程的创建和结束,便于调度。而对于需要更精细控制的场景,可以使用Process类来手动创建和结束进程。
6. 总结
本文介绍了Python中的multiprocessing模块的使用方法,包括如何创建进程、进程间通信、进程池等。为了提高多进程的处理效率,介绍了进程池中的map、imap、imap_unordered方法的使用。此外,本文还提到了多进程处理的实际应用场景,需要根据具体的任务特性来选择合适的进程管理方案。