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

相关推荐
前端付豪1 天前
LangChain链 写一篇完美推文?用SequencialChain链接不同的组件
人工智能·python·langchain
曲幽1 天前
FastAPI实战:打造本地文生图接口,ollama+diffusers让AI绘画更听话
python·fastapi·web·cors·diffusers·lcm·ollama·dreamshaper8·txt2img
老赵全栈实战1 天前
Pydantic配置管理最佳实践(一)
python
阿尔的代码屋1 天前
[大模型实战 07] 基于 LlamaIndex ReAct 框架手搓全自动博客监控 Agent
人工智能·python
AI探索者2 天前
LangGraph StateGraph 实战:状态机聊天机器人构建指南
python
AI探索者2 天前
LangGraph 入门:构建带记忆功能的天气查询 Agent
python
FishCoderh2 天前
Python自动化办公实战:批量重命名文件,告别手动操作
python
躺平大鹅2 天前
Python函数入门详解(定义+调用+参数)
python
曲幽2 天前
我用FastAPI接ollama大模型,差点被asyncio整崩溃(附对话窗口实战)
python·fastapi·web·async·httpx·asyncio·ollama
两万五千个小时2 天前
落地实现 Anthropic Multi-Agent Research System
人工智能·python·架构