python多进程multiprocessing——spawn启动方式解析

下面我来详细讲解这段代码以及"spawn"到底是什么。

1. 代码逐行解析

python 复制代码
import multiprocessing

# 检查当前的进程启动方式是否为 "spawn"
if multiprocessing.get_start_method() != "spawn":
    # 如果不是,则强制将其设置为 "spawn"
    multiprocessing.set_start_method("spawn", force=True)
  • multiprocessing.get_start_method(): 获取当前系统默认创建新进程的方式。
  • multiprocessing.set_start_method("spawn", force=True) : 将创建新进程的方式设置为 spawnforce=True 表示即使之前已经设置过(或有默认值),也要强行覆盖。

2. 什么是 spawn

在 Python 中,创建一个新的子进程主要有三种模式:forkspawnforkserver

spawn 是其中一种最"干净"但启动较慢的模式。

形象的比喻:
  • Fork (克隆) :这是 Linux/Unix 的默认模式。就像把父进程这个人瞬间"复印"了一份。
    • 优点:速度极快,子进程继承了父进程的所有内存和资源。
    • 缺点:如果父进程已经很乱了(比如已经开启了多线程,或者持有了某些锁),克隆出来的子进程可能会带着这些"坏毛病",导致死锁或程序崩溃。
  • Spawn (新生) :这是 Windows 和 macOS 的默认模式。就像按照说明书重新雇佣了一个新员工。
    • 优点非常安全和干净。子进程会启动一个新的 Python 解释器,只加载必要的资源。它不会继承父进程混乱的内存状态或锁。
    • 缺点启动速度慢。因为要重新初始化 Python 环境和导入模块。

3. 为什么要用这段代码?

通常在以下几种情况下,你会看到这段代码:

  1. 跨平台兼容性

    • Linux 默认用 fork,Windows 默认用 spawn。为了保证代码在 Linux 和 Windows 上行为一致,开发者会强制指定为 spawn
  2. 深度学习(PyTorch/TensorFlow)与 CUDA

    • 这是最常见的原因。如果你在使用 PyTorch 进行 GPU 训练,CUDA 运行时不支持 fork
    • 如果在已经初始化了 CUDA 上下文的主进程中使用 fork 创建子进程,程序会报错或卡死。因此,PyTorch 的 DataLoader 等组件通常要求使用 spawn
  3. 多线程与多进程混用

    • 如果你的主程序中已经启动了多个线程 ,然后再尝试 fork 一个进程 ,非常容易导致死锁(因为 fork 会复制锁的状态,但不会复制持有锁的线程)。使用 spawn 可以避免这个问题。

4. 使用 spawn 的注意事项

如果你强制使用了 spawn,你的代码必须遵守一个严格的规则:

所有的启动代码必须放在 if __name__ == '__main__': 保护块之下。

因为 spawn 会重新导入你的脚本文件来初始化子进程。如果你不加这个保护块,子进程在导入文件时,又会尝试启动新的孙子进程,导致无限递归循环报错。

错误示例:

python 复制代码
import multiprocessing
multiprocessing.set_start_method("spawn", force=True)

def func():
    print("hello")

# 这里会报错,因为子进程import时会再次执行这行
p = multiprocessing.Process(target=func) 
p.start()

正确示例:

python 复制代码
import multiprocessing

def func():
    print("hello")

if __name__ == '__main__':
    # 必须放在这里面
    multiprocessing.set_start_method("spawn", force=True)
    p = multiprocessing.Process(target=func)
    p.start()
    p.join()

总结

这段代码是为了确保多进程程序的稳定性和跨平台兼容性 ,特别是在涉及 GPU 计算或复杂多线程环境时,通过牺牲一点点启动速度(使用 spawn),换取更安全、干净的进程运行环境。

相关推荐
nvvas3 小时前
Java 入门(四):数组——数据的集合管理
java·开发语言
Ticnix3 小时前
多租户 RAG:让每个用户只检索到自己的知识库
后端·python·agent
ID34610744203 小时前
【课程设计】基于Spring Boot+Vue的游戏账号租赁系统的设计与实现-计算机毕设 附源码50345
javascript·vue.js·spring boot·python·node.js·php·课程设计
夏雪coding3 小时前
RAG 要不要上向量库:720 个 chunk 用 numpy 点积就够了
python·aigc·ai编程
Ticnix3 小时前
我删了 200 行 if-else,把决策逻辑全写进了 System Prompt
python·llm·agent
谢白羽3 小时前
在4×B300用SGLang部署DeepSeek-V4.1 Flash优化实录
笔记·python·llm·llama·sglang
Y3815326624 小时前
SERP 数据清洗实战:字段标准化、日期解析与去重键
开发语言·数据库·python·python数据库
君顾14 小时前
本地城市低空经济管理系统定制:城市级低空运营平台架构与落地实战
java·开发语言·飞手
苏苏susuus4 小时前
核密度估计(KDE)与高斯核(概念分享)
人工智能·python·ocr
宸津-代码粉碎机4 小时前
微服务线上踩坑复盘:接口超时、负载倾斜隐形问题根治方案(生产级配置)
java·大数据·人工智能·python·spring