You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python multiprocessing使用中进程丢失问题排查求助

问题描述

我使用Python的multiprocessing包,通过Pool.map方法将415700个仿真任务并行分配到40个进程(对应40核CPU)。初始运行正常,但一段时间后执行的进程数量大幅减少,导致迭代效率下降。例如,运行1-2天后,仍有近200000个任务待执行,但仅约10个进程在运行,且无任何报错信息。手动停止重启后,40个进程可恢复正常运行。

我未设置chunksize参数,但认为这并非问题所在,仍有大量任务在队列中。后续测试计划使用imap或imap_unordered并设置chunksize参数以优化性能。

补充环境与实现细节:

  • 操作系统:CentOS Linux 7
  • 运行方式:通过SSH连接服务器,在tmux会话中运行
  • Python版本:3.8.0
  • 工作函数无返回值,仅通过Filelock将数据保存至CSV文件,使用functools.partial为工作函数添加固定参数
  • 约半数情况下,工作函数会通过subprocess.call调用HEASOFT的battblocks软件

请问进程丢失的原因可能是什么?


可能的原因分析

1. subprocess.call调用引发的进程阻塞或异常

约半数任务依赖外部工具battblocks,如果这个工具存在以下问题,会直接拖垮Python子进程:

  • battblocks本身有内存泄漏、死锁或长时间无响应的情况,subprocess.call会一直等待它执行完毕,对应的Python进程就会被挂起,看起来像"丢失"了
  • 没处理battblocks的标准输出/错误流,当输出缓冲区被占满时,进程会被卡死(subprocess.call默认不捕获输出,缓冲区满会直接阻塞进程)
  • battblocks崩溃但没返回非零退出码,或者Python进程没捕获到异常,导致该进程无法处理后续任务,只能闲置

2. 文件锁(Filelock)导致的进程阻塞

工作函数用Filelock写CSV时,如果锁的逻辑有问题:

  • 锁未正确释放:比如写入时触发异常,没通过try/finally确保锁被释放,其他进程会一直等锁,被阻塞的进程自然无法继续工作
  • 高并发下锁竞争太激烈,大量进程陷入等待状态,实际能运行的进程数就会锐减

3. Python子进程隐性崩溃或资源耗尽

  • 内存泄漏:工作函数或battblocks存在内存泄漏,长时间运行后,部分进程占用内存过高,被CentOS的OOM Killer(内存不足杀手)直接终止,系统不会通知Python主进程,进程池里的可用进程就会越来越少
  • 未捕获的异常:工作函数里有未处理的异常(比如CSV写入的IO错误、subprocess调用的异常),multiprocessing.Pool的子进程遇到未捕获异常会直接退出,主进程不会自动补充新进程(除非设置maxtasksperchild),随着异常进程增多,可用进程数逐步减少

4. Python 3.8multiprocessing.Pool的机制缺陷

Python 3.8的进程池在某些场景下有隐性问题:

  • 子进程异常退出后,主进程不会自动补充新进程,导致可用进程数慢慢变少
  • Pool.map是批量分配任务的,要是某个子进程处理的批量任务出问题,会导致该进程挂起或退出,后续任务分配也会受影响

5. CentOS系统的资源限制

  • 进程数上限:系统对单个用户的最大进程数设置过低,长时间运行后,subprocess创建的battblocks进程加Python子进程,达到上限后无法创建新进程,部分Python进程就没法继续执行
  • 资源调度问题:CentOS的进程调度器可能降低了部分Python进程的优先级,或者系统负载过高导致这些进程被挂起,看起来像是停止运行

6. tmux/SSH会话的隐性异常

虽然在tmux里运行,但如果SSH连接出现隐性中断(比如网络波动),可能导致部分进程的标准输入输出被阻塞,进而影响进程的运行状态


排查与解决建议
  • 给subprocess.call加上stdout=subprocess.PIPE和stderr=subprocess.PIPE(或者重定向到日志文件),避免缓冲区满阻塞;同时捕获subprocess.CalledProcessError异常,确保外部命令出错时进程能正常退出并被回收
  • 把Filelock的使用放在try/finally块里,保证锁一定会被释放;可以考虑让每个进程写入独立临时文件,最后再合并,减少锁竞争
  • 设置Pool的maxtasksperchild参数,让每个子进程处理一定数量的任务后自动退出重启,避免内存泄漏或隐性异常积累
  • 监控系统资源:用top/htop看进程的内存、CPU占用,用dmesg检查是否有进程被OOM Killer终止
  • 升级Python到3.8.x的最新补丁版,或者直接升级到3.9+版本,修复multiprocessing的已知问题
  • 测试imap/imap_unordered配合chunksize,不仅能优化任务分配,还能更快发现单个任务的异常

内容的提问来源于stack exchange,提问作者Miguel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 05:45:28