理解Python多进程apply_async与get方法及任务延迟问题
针对你的代码与疑问的详细解答
先结合你的多进程代码场景,逐个拆解你的问题:
1. 提交给进程池的任务是立即执行,还是要等到调用get()时才执行?
当你调用pool.apply_async(process_chunk, (work,))的瞬间,任务就已经被送入进程池的任务队列了。只要进程池中有空闲的工作进程,任务就会立刻开始执行——完全不需要等到你调用job.get()。
这对你的长队列场景非常友好:读取进程一边往work_q里塞数据块,进程池一边就会分配空闲worker处理,是并行推进的,不会出现“等队列耗尽才开始处理”的低效情况。
2. 若任务立即执行,函数结果存储在何处?
任务执行完成后,结果会被暂存在ApplyResult对象(也就是你代码里的job变量)的内部缓存中。这个缓存是由Python的multiprocessing模块通过进程间通信(比如管道)维护的:子进程把计算结果传递回主进程,主进程将结果存在job对应的缓存里,直到你调用job.get()时再取出。
3. 延迟调用get(),子进程会被阻塞吗?
不会。子进程执行完任务、把结果传递给主进程缓存后,就彻底完成了这个任务的工作——它要么去进程池的任务队列取下一个任务执行,要么在无任务时进入空闲等待状态,绝对不会因为主进程没调用get()而阻塞。
真正会阻塞的只有主进程调用job.get()的时刻:如果对应任务还在执行,主进程会在这里等待结果返回;如果任务已经执行完毕,就直接从缓存里取结果,不会等待。
关于Done reading chunks!到Processing job {job_idx}的长延迟原因
这个延迟的本质是主进程在等待最后一批任务执行完毕:
- 当你打印
Done reading chunks!时,只是说明读取进程已经把所有数据块都放入work_q,并且读取进程已经被终止,但进程池里的worker可能还在处理最后一批数据块(尤其是当数据块数量远大于n_workers时,后面提交的任务可能还在排队或执行中)。 - 你在循环提交完所有任务后,才开始逐个调用
job.get()。第一个job.get()会卡住主进程,直到对应的任务执行完成,这中间的等待时间就是最后一批任务的执行耗时,所以会出现明显的延迟。
内容的提问来源于stack exchange,提问作者Bram Vanroy
相关产品推荐
相关产品推荐

