RuntimeError: Cannot re-initialize CUDA in forked subprocess.

该问题出现在 vLLM CI 的 fork 模式 EngineCore 测试中,具体涉及:

快速结论:此报错出现在 vLLM 的 fork 模式 EngineCore 子进程启动时,通常是因为父进程在 fork 之前就已经初始化了 CUDA。优先检查近期合并的 PR #46750 是否引入了模块级别的 CUDA 调用。

问题场景

该问题出现在 vLLM CI 的 fork 模式 EngineCore 测试中,具体涉及:

  • Engine (1 GPU) 测试:v1/engine/test_engine_core.py 系列测试(共 13 个失败案例,如 test_engine_core、test_engine_core_advanced_sampling、test_engine_core_concurrent_batches、test_encoder_instance_zero_kv_cache 等)
  • LoRA 4 测试:lora/test_default_mm_loras.py 中的 test_active_default_mm_lora 和 test_default_mm_lora_does_not_expand_string_reqs
  • 问题在 main 分支的 nightly CI 构建中可稳定复现(Build #75919,2026-07-02)

报错原文

RuntimeError: Cannot re-initialize CUDA in forked subprocess.
  To use CUDA with multiprocessing, you must use the 'spawn' start method

完整 traceback 位于 EngineCore 子进程的 KV-cache 初始化阶段:

File ".../vllm/v1/engine/core.py", line 1200, in run_engine_core
  engine_core = EngineCoreProc(*args, engine_index=dp_rank, **kwargs)
File ".../vllm/v1/engine/core.py", line 133, in __init__
  kv_cache_config = self._initialize_kv_caches(vllm_config)
File ".../vllm/v1/engine/core.py", line 247, in _initialize_kv_caches
  kv_cache_specs = self.model_executor.get_kv_cache_specs()
File ".../vllm/v1/executor/uniproc_executor.py", line 92, in collective_rpc
  ...
File ".../vllm/v1/worker/gpu_worker.py", line 667, in get_kv_cache_spec
  return self.model_runner.get_kv_cache_spec()
...
RuntimeError: Cannot re-initialize CUDA in forked subprocess. ...

原因分析

根本原因是父进程在 fork 之前就已经初始化了 CUDA。具体来说:

  • PR #46750(2026-06-29 合并)引入了 qwen_triton_warmup,其中包含模块级别的 FLA/Mamba 导入,这些导入会触发 CUDA 初始化
  • 导入链为:gpu_worker -> kernel_warmup -> qwen_triton_warmup
  • 这意味着在 pytest 主进程(父进程)中只需导入 gpu_worker,就会初始化 CUDA,导致后续 fork 子进程时出现 “Cannot re-initialize CUDA” 错误
  • 注意:此问题 不是 Triton 3.8 的 cuInit 问题(相关 Issue #46996),因为测试环境使用的是 Triton 3.7.1

环境排查

  • vLLM 版本:main 分支(2026-06-29 至 2026-07-01 期间引入回归)
  • PyTorch 版本:2.13.0(在二分测试中保持不变)
  • Triton 版本:3.7.1(排除 Triton 3.8 问题)
  • CUDA 状态:在 pytest 主进程中已经初始化(可通过 torch.cuda.is_initialized() 验证)
  • CI 镜像中的 FLASHINFER_VERSION:0.6.12 → 0.6.13(PR #46683,2026-06-29 更新,但非直接原因)

解决步骤

  1. 确认根因:检查 conftest.py 中添加 CUDA 初始化探测代码,找出触发 CUDA 初始化的确切导入位置:
    import traceback, torch.cuda
    _orig = torch.cuda._lazy_init
    def _probe(*a, **k):
        if not torch.cuda.is_initialized():
            traceback.print_stack()
        return _orig(*a, **k)
    torch.cuda._lazy_init = _probe
  2. 应用修复(PR #47539):此问题已通过 PR #47539 修复。修复策略是将 qwen_triton_warmup 中的模块级 CUDA 调用延迟到实际使用时再进行,确保父进程在 fork 前不会初始化 CUDA。
  3. 验证修复版本:确保 vLLM 版本 >= 0.23.1rc1.dev764+g576bf75d0(包含修复的 nightly 构建)
  4. 如果您遇到了相同的报错但无法升级,可尝试的临时方案(需根据实际情况验证):
    • 检查是否导入了 qwen_triton_warmup 相关的模块
    • 将 multiprocessing 的 start method 改为 spawn 而非 fork

验证方法

问题已由 PR #47539 修复。验证方式:

  • 在包含修复的版本中运行完整的 pytest v1/engine 测试套件
  • 使用 torch.cuda._lazy_init 探测确认父进程保持 CUDA 未初始化状态
  • 检查 nightly CI 构建(如 Build #76262)中 Engine (1 GPU) 和 LoRA 4 测试是否全部通过

参考来源

vllm-project/vllm #47446 – Bug: EngineCore fork spawn broken: ‘Cannot re-initialize CUDA in forked subprocess’

PR #47539 – 修复此问题的 Pull Request(已合并)

PR #46750 – 引入 qwen_triton_warmup 并导致回归的 Pull Request

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 16161

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注