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) : 将创建新进程的方式设置为 spawn。force=True 表示即使之前已经设置过(或有默认值),也要强行覆盖。

2. 什么是 spawn?

在 Python 中,创建一个新的子进程主要有三种模式:fork、spawn 和 forkserver。

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),换取更安全、干净的进程运行环境。

相关推荐
qianbo_insist21 小时前
# 在 Qwen3.5-2B 上把 GDN-1 无损换成 GDN-2:一次完整的架构手术实验(负结果)
人工智能·pytorch·python·架构
多弗朗皮卡丘21 小时前
C++的IO流
开发语言·c++·io流·文件io流
骑着蜗牛撵大象3271 天前
AI Agent 工程化开发实战(三):用 StateGraph 给智能体搭一条可回放的状态流水线
java·开发语言·jvm·ai·状态管理·langgraph·stategraph
itmigrate1 天前
Rust 里的所有权误区:不是不写 clone 就叫高性能
开发语言·后端·rust
Brilliantwxx1 天前
【Linux】 文件访问与路径解析:目录、文件名、dentry、路径缓冲与 dcache 全解析
linux·运维·服务器·开发语言·spring
摇滚侠1 天前
《On Java 中文版 基础卷》阅读笔记 初始化和清理 08
java·开发语言·笔记
xiangyun611 天前
C++ 手撕 shared_ptr:引用计数与控制块到底长什么样?
开发语言·c++·算法·面试·stl
专注仿真1 天前
Agentic RAG算法详解
人工智能·python·大模型训练·控制算法
XiYang-DING1 天前
P4009.和为K的子数组个数 & P5522.异或和为 k 的子数组个数
java·开发语言
学习论之费曼学习法1 天前
无人值守AI内容矩阵实战(8):标题 A/B 实验的 6 个工程实现细节,隔日对比与自动判胜
人工智能·python·算法·矩阵·自动化·a/b测试·内容矩阵