文章目录

  • 一、简介
  • 二、选择合适的启动方式
  • 三、手动终止所有的进程
  • 小结

一、简介

这里简单介绍在Python中使用多进程编程的时候容易遇到的情况和解决办法,有助于排查和规避某类问题,但是具体问题还是需要具体分析,后续会补充更多的内容。

二、选择合适的启动方式

  1. Python多进程编程非常需要注意启动方式,有些库会在fork模式下出现很诡异的阻塞或显存泄漏。如果需要跨平台使用,优先选择spawn方式,如果涉及到 GPU、PyTorch、OpenCV 视频流、TensorRT、OpenVINO ,同样优先选择spawn方式,避免继承GPU上下文。有的时候会存在 多线程多进程 混用的情况,可以选择spawnforkserver这两种方式。 spawn启动方式通常更安全、更稳定。

    启动方式平台默认机制优点缺点适用场景
    forkLinux / macOS子进程直接复制父进程的内存空间(写时复制),从 fork() 返回处继续执行创建速度快,占用内存少继承父进程线程状态可能死锁,继承 GPU/文件句柄可能出错,不支持 Windows纯计算、多进程间状态共享简单、无 GPU/大文件句柄的场景
    spawnWindows启动全新的 Python 解释器进程,从头执行 __main__ 模块的代码跨平台一致,状态干净,不继承父进程线程/句柄/GPU context启动慢,初始化开销大,需要 if __name__ == "__main__":GPU 深度学习、跨平台项目、多线程+多进程混合、需要隔离状态的场景
    forkserverLinux / macOS先启动一个 “fork server” 进程,之后所有子进程由它 fork 出来避免从主进程直接 fork(减少死锁风险),比 spawn 快只在类 Unix 系统可用,需额外启动 server,复杂度高多线程+多进程并存、需要避免主进程 fork 的高并发服务
  2. 可以通过调用multiprocessing.set_start_method('spawn')来指定子进程的启动方式,通常写在if __name__ == "__main__":里,force=True参数可以强制重置启动方式(但通常不建议随便用,除非确定没别的进程创建了子进程)。

    import multiprocessing as mpdef worker(name):print(f"Worker {name} running...")if __name__ == "__main__":# 强制统一 spawnmp.set_start_method("spawn", force=True)  # "fork" 或 "forkserver" processes = []for i in range(3):p = mp.Process(target=worker, args=(i,))p.start()processes.append(p)for p in processes:p.join()
    
  3. 使用 PyAV 调用h264_qsv(Intel Quick Sync Video)硬件加速解码时,也会受多进程启动方式的影响,QSV 是基于英特尔硬件加速的编码解码技术,需要在进程中正确初始化硬件上下文。如果使用fork,子进程会复制父进程的内存空间,但硬件设备上下文(如 QSV 的硬件句柄、驱动状态等)通常不能被正确继承或共享,导致解码失败、死锁或崩溃。使用spawn,子进程是全新启动,独立初始化硬件上下文,能避免因上下文继承带来的问题,提高稳定性。

    多进程启动方式对 PyAV + h264_qsv 硬解码的影响推荐做法
    fork可能导致硬件上下文冲突,解码异常不推荐
    spawn子进程独立初始化硬件上下文,稳定性高推荐,尤其多进程并发的时候
  4. 在使用fork启动多进程的时候,部分常用的 计算机视觉 (CV)和 点云处理 相关库可能会出现问题,任何涉及 GPU上下文、线程池或多线程加速的库,在fork多进程启动方式下都可能出现资源继承异常、死锁、崩溃等问题。点云库中,Open3DPCL 较为复杂,fork时要特别注意。

    库/模块说明与常见问题
    OpenCV (cv2)GPU模式(CUDA)在fork后可能资源异常或崩溃,多线程环境下死锁;CPU模式一般安全,但多线程仍需注意。
    Open3D内部使用线程池和GPU(部分功能),fork启动时可能导致线程池状态异常或GPU资源不可用。
    PCL / python-pcl底层多线程和GPU支持(部分平台),fork后可能出现线程死锁或资源冲突,尤其在GPU加速时。
    PyTorchfork后CUDA上下文继承出错,导致报错、卡死;多线程资源也可能异常。
    TensorFlowfork后session、资源无法正常初始化,多线程管理导致崩溃。
    OpenVINO线程池和设备初始化受fork影响,可能导致设备资源冲突或初始化失败。
    TensorRTGPU上下文和优化缓存fork后不稳定,可能导致初始化失败或运行错误。
    matplotlibGUI线程在fork后可能卡死或异常。

三、手动终止所有的进程

  1. 多进程中 Ctrl+CSIGINT 信号)后程序没有全部退出,最常见原因就是信号没有传递给子进程,或者子进程没能响应退出请求。fork导致资源继承异常也经常是根源。列出当前系统中所有正在运行的 Python 进程及其详细信息。

    ps aux | grep python
    
  2. 在多进程场景下,torch.utils.data.DataLoader是常见的导致进程无法退出的元凶之一,尤其是在num_workers > 0时。有的情况默认不监听结束信号,有的情况收不到结束信号。显式处理可能比较麻烦。

  3. 一个比较安全的写法是在主进程捕获SIGINT,然后主动杀掉自己启动的所有子进程。直接一次性结束整个进程树。

    import multiprocessing as mp
    import signal
    import sys
    import os
    import psutildef kill_all_children(timeout=3):"""终止当前进程的所有子进程(递归),先尝试终止,再强制杀死超时未结束的子进程"""proc = psutil.Process(os.getpid())children = proc.children(recursive=True)# 尝试终止for child in children:try:child.terminate()except Exception as e:print(f"[警告] 无法终止 PID={child.pid}: {e}", file=sys.stderr)# 等待超时,获取仍然存活的子进程gone, alive = psutil.wait_procs(children, timeout=timeout)# 强制杀死仍然存活的进程for child in alive:try:child.kill()except Exception as e:print(f"[错误] 无法强制终止 PID={child.pid}: {e}", file=sys.stderr)def signal_handler(sig, frame):   # 回调函数print(f"\n[退出] 捕获信号 {sig},终止子进程并退出...")try:kill_all_children()except Exception as e:print(f"[错误] 终止子进程时出错: {e}", file=sys.stderr)finally:sys.exit(130 if sig == signal.SIGINT else 143)  # 130 = Ctrl+C 退出, 143 = SIGTERM 退出def main(args):# 启动多个进程的示例processes = []for _ in range(4):p = mp.Process(target=worker_function)p.start()processes.append(p)for p in processes:p.join()if __name__ == "__main__":signal.signal(signal.SIGINT, signal_handler)   # 注册信号和回调函数signal.signal(signal.SIGTERM, signal_handler)mp.set_start_method('spawn', force=True)args = parse_args()main(args)
    
  4. 或者更简单直接的立即杀掉所有进程,终端更干净。可以根据实际情况考虑如何使用。

    import multiprocessing as mp
    import signal
    import sys
    import os
    import psutildef kill_all_processes():proc = psutil.Process(os.getpid())for child in proc.children(recursive=True):child.kill()proc.kill()def signal_handler(sig, frame):print("\n[退出] 捕获 Ctrl+C,终止所有进程...")kill_all_processes()sys.exit(0)def main(args):# 启动多个进程的示例processes = []for _ in range(4):p = mp.Process(target=worker_function)p.start()processes.append(p)for p in processes:p.join()if __name__ == "__main__":signal.signal(signal.SIGINT, signal_handler)signal.signal(signal.SIGTERM, signal_handler)mp.set_start_method('spawn', force=True)args = parse_args()main(args)
    

小结

以上内容来自相关资料和个人实践,具体情况还请具体分析,可以参考这里提到的几个关键点,有助于排查问题,如有问题欢迎在评论区指正,谢谢!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92887.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92887.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/92887.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ansible部署应用

目录Ansible概述1:什么是Ansible2:Ansible的架构组成3:Ansible与SaltStack的对比安装部署Ansible服务1:系统环境设置2:安装Ansible(第一台)2:配置主机清单3:修改Ansible配…

疏老师-python训练营-Day44预训练模型

浙大疏锦行 知识点回顾: 预训练的概念常见的分类预训练模型图像预训练模型的发展史预训练的策略预训练代码实战:resnet18 作业: 尝试在cifar10对比如下其他的预训练模型,观察差异,尽可能和他人选择的不同尝试通过ctrl进…

AI入门学习--如何写好prompt?

写好Prompt(提示词)是驾驭AI模型的核心技能。以下是结合测试工程师需求的 结构化方法论 和 黄金模板一、prompt设计金字塔终极心法: Prompt 对AI的测试需求文档,需像设计测试用例一样:可执行:明确输入输出…

Linux编程 IO(标准io,文件io,目录io)

标准IO C语言标准IO概述标准IO&#xff08;Standard Input/Output&#xff09;是C语言中用于处理文件和数据流的一组函数库&#xff0c;定义在<stdio.h>头文件中。与低级IO&#xff08;如read/write&#xff09;相比&#xff0c;标准IO提供了缓冲机制&#xff0c;提高了数…

C# WPF本地Deepseek部署

模型下载地址 using LLama; using LLama.Common; using System; using System.IO; using System.Threading.Tasks; using System.Windows; using System.Windows.Input;namespace YF_Talk {public partial class MainWindow : Window{private LLamaWeights _model;private LLa…

【Abp.VNext】Abp.Vnext框架模块学习

1、Abp.Vnext-集成 Volo.Abp.Core2、Abp.vNext-Web模块 Volo.Abp.AspNetCore.MVC框架&#xff08;framework文件夹&#xff09; 七、Abp.vNext-应用模块-Identity身份认证 业务模块&#xff08;modules文件夹->identity&#xff09; 1、添加领域模型 Volo.Abp.Identity.Doma…

【完整源码+数据集+部署教程】火柴实例分割系统源码和数据集:改进yolo11-rmt

背景意义 研究背景与意义 在计算机视觉领域&#xff0c;实例分割技术作为一种重要的图像处理方法&#xff0c;近年来得到了广泛的关注和应用。实例分割不仅能够识别图像中的物体类别&#xff0c;还能精确地分割出每个物体的轮廓&#xff0c;提供更为细致的视觉信息。这一技术在…

飞算JavaAI云原生实践:基于Docker与K8s的自动化部署架构解析

一、飞算JavaAI详细介绍 1.1 飞算JavaAI飞算JavaAI是飞算云智推出的一款革命性Java开发辅助工具&#xff0c;它通过人工智能技术深度赋能传统软件开发流程&#xff0c;特别为大学生课程设计、毕业设计等实践教学环节提供了强有力的技术支持。在当前高校计算机相关专业教学中&am…

小程序打通美团核销:解锁到店综合业态私域密码,赋能6000+门店破局增长

数字化浪潮奔涌而来&#xff0c;棋牌室、台球厅、亲子乐园等线下综合业态面临经营转型的关键节点。小程序与美团核销功能的深度耦合&#xff0c;正成为撬动私域流量的核心杠杆&#xff0c;为超6000家门店打通了一条低成本、高转化的经营快车道。过往经营模式中&#xff0c;线上…

Linux Shell:Nano 编辑器备忘

打开文件 sudo nano /etc/apt/sources.list选中多行&#xff0c;然后删除 用方向键将光标定位到要删除的起始位置按下 Alt A 设置锚点用方向键选择要删除的区域 (以上 3 步是为了选中文本)用 Ctrl K(剪切) 或 Alt D(直接删除) 全选并删除 按下 Alt \ 将光标移动到文件开头…

常见的设计模式(2)单例模式

目录 一、版本一&#xff1a;禁用构造与拷贝 二、版本二&#xff1a;注册析构函数/嵌套垃圾回收 &#xff08;1&#xff09;使用atexit注册程序结束时的函数 &#xff08;2&#xff09;使用对象嵌套垃圾回收 三、版本三&#xff1a;线程安全 四、版本四&#xff1a;编译器…

JAiRouter 0.2.1 更新啦:内存优化 + 配置合并 + IP 限流增强,运维体验再升级

JAiRouter 0.2.1 更新啦&#xff1a;内存优化 配置合并 IP 限流增强&#xff0c;运维体验再升级 如果你已经在 0.2.0 生产环境中稳定运行&#xff0c;那么这篇更新会让你无痛升级&#xff0c;直接“更轻、更稳、更省心”。 &#x1f4ce; 官方仓库 & issue 直达 https://…

学习嵌入式第二十六天

文章目录IO(续上)1.标准IO1.标准IO的接口2.流的定位2.文件IO1.概念&#xff1a;2.系统调用和库函数3.文件IO函数接口习题IO(续上) 1.标准IO 1.标准IO的接口 fwrite 原型&#xff1a;size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream); 功能&#xff1…

GDB 程序启动参数设置深度指南

GDB 程序启动参数设置深度指南 1. 概述 在程序调试过程中&#xff0c;正确设置启动参数对于验证程序行为、重现特定场景至关重要。GDB提供多种灵活的方式设置启动参数&#xff0c;特别是当您需要调试命令行参数处理逻辑或配置敏感型应用时。 2. 参数设置的核心方法 2.1 启动GDB…

Autudl华为昇腾系列NPU简介和部署推理yolo11 yolov8 yolov5分割模型

0.配置Autudl 下面图片是我所租的昇腾卡和具体环境版本&#xff0c;太具体的就不说了&#xff0c;有需要的话我单独出一期Autudl租显卡的教程&#xff0c;主要是为了学习昇腾环境如何运行Yolo系列模型。 0.1华为昇腾芯片&#xff08;Ascend&#xff09;简介 1.Ascend 310&…

什么是JSP和Servlet以及二者的关系

JSP&#xff08;JavaServer Pages&#xff09; 是“HTML 里写 Java”的模板技术&#xff0c;最终会被容器转换成 Servlet。Servlet 是“Java 里写 HTML”的 Java 类&#xff0c;直接继承 javax.servlet.http.HttpServlet&#xff0c;用来接收/响应 HTTP 请求。Servlet 是什么 纯…

【WonderTrader源码详解 1】【环境搭建 2】【编译安装WonderTrader】

一、引言 本篇来讲述如何搭建 wondertrader 和 wtpy 二、wondertrader 2.1 源码下载 # /home/leo/sda_1.6TBgit clone https://gitee.com/wondertrader/wondertrader.gitgit clone https://gitee.com/wondertrader/wtpy.git2.2 源码编译 cd /home/leo/sda_1.6TB/wondertrader/s…

hutool 作为http 客户端工具调用的一点点总结

场景一&#xff1a;客户端timeout 的时间给的很短//100毫秒 private static final int HTTP_TIMEOUT_MS 1 * 100; response HttpUtil.createPost(patrolresultconfirmUrl).body(JSONObject.toJSONString(search)).header("Authorization", token).timeout(HTTP_TI…

基于MongoDB/HBase的知识共享平台的设计与实现

标题:基于MongoDB/HBase的知识共享平台的设计与实现内容:1.摘要 在当今信息爆炸的时代&#xff0c;知识的有效共享和管理变得愈发重要。本研究的目的是设计并实现一个基于MongoDB/HBase的知识共享平台&#xff0c;以满足大规模知识数据的存储、高效查询和快速共享需求。方法上&…

PHP数组操作:交集、并集和差集

1. 交集&#xff08;Intersection&#xff09;交集是指两个集合中都存在的元素。$array1 [1, 2, 3, 4]; $array2 [3, 4, 5, 6];$intersection array_intersect($array1, $array2); print_r($intersection); // 输出: Array ( [2] > 3 [3] > 4 )2. 并集&#xff08;Uni…