快速结论:在 vLLM 上为 Gemma 4 多模态模型启用 encoder CUDA graph(cudagraph_mm_encoder: true)并开启视频输入时,捕获阶段会按 max_frames_per_batch 为每个预算分配整幅图像尺寸的 dense pixel buffer,导致出现 CUDA out of memory。优先排查捕获 dummy 的内存占用与预算行数是否被合理限制。
适用环境:Issue 已确认环境:vLLM 0.31.1rc1.dev159+g4274ae956(main @ 4274ae956c,预编译 wheel),torch 2.13.0+cu132,torchvision 0.28.0,transformers 5.19.0,CUDA 13.2,驱动 595.91.07,单卡 RTX 5090 32 GB(sm_120),模型 nvidia/Gemma-4-26B-A4B-NVFP4。
最快修复方案:暂无已合入的一步修复版本。Issue 作者已验证的临时规避方式是关闭 encoder CUDA graph(不启用 cudagraph_mm_encoder),工作负载可正常启动;真正的行数上限修复由 #61092 实现。
注意事项:关闭 encoder CUDA graph 只是配置层规避,不解决分配逻辑本身的问题;#61092 中的行数上限在 L40S + gemma-4-E2B-it 视频场景验证可启动,但视频输出与 eager 的一致性还需 #60687。Issue 场景为单卡 RTX 5090 上的视频路径验证,非生产负载。
问题场景
用户通过 vllm serve 启动 Gemma 4 多模态模型,开启 fp8 KV cache、--limit-mm-per-prompt '{"image": 1, "video": 1}'、--media-io-kwargs '{"video": {"num_frames": 32}}',并在 --compilation-config 中设置 {"cudagraph_mm_encoder": true}。引擎在 encoder CUDA graph 捕获阶段崩溃,此时尚未进入正常推理。
报错原文
INFO [encoder_cudagraph.py:208] EncoderCudaGraphManager initialized with paths={'default': [70, 140, 280, 560, 1120, 2240, 4096]}, max_batch_size=58, max_frames_per_batch=1856, use_dp=False, capture_axes=()
...
File ".../vllm/v1/worker/encoder_cudagraph.py", line 324, in _capture_budget_graph
output = self.model.encoder_cudagraph_forward({**values}, path=path)
File ".../vllm/model_executor/models/gemma4_mm.py", line 1994, in encoder_cudagraph_forward
inputs_embeds = vt.patch_embedder(
File ".../transformers/models/gemma4/modeling_gemma4.py", line 624, in forward
pixel_values = 2 * (pixel_values - 0.5)
torch.OutOfMemoryError: CUDA out of memory. Tried to allocate 6.69 GiB. GPU 0 has a total capacity of 31.36 GiB of which 4.42 GiB is free.
原因分析
Issue 给出的根因链路如下:
- 用户未显式设置时,
EncoderCudaGraphManager.__init__推导出max_batch_size = min(4096 // 70, 70) = 58,max_frames_per_batch = 58 * 32 = 1856。 - 在 Qwen2.5-VL / Qwen3-VL / GLM-4.1V 中,
max_frames_per_batch只决定预算如何跨帧铺开(cu_seqlens、捕获网格),像素 buffer 接近 token 预算。但 Gemma 4 的prepare_encoder_cudagraph_capture_inputs把它当作 dense pixel buffer 的行数,每行按整幅图像尺寸分配。 - 结果是每个预算都分配 1856 行,token 预算并不会缩小行数;280 token 预算和 4096 token 预算拿到同样大的
(1856, 2520, 768)bf16 buffer。 - 每个预算的 dummy 作为 graph 的
input_buffers保留,7 个预算合计约 38.5 GiB bf16 dummy 输入,32 GB 卡在捕获完成前即失败。 - 此外捕获从最大预算开始,先对整块 dummy 做一次 eager forward(1856 × 2520 ≈ 4.7M patch token 一次送入 vision tower),而该路径不像 eager encoder 那样使用
_encoder_chunk分块。
环境排查
- 确认 vLLM 版本,是否包含 encoder CUDA graph 中按
token_budget // 70限制捕获行数的修复(#61092)。 - 确认 torch、transformers、CUDA 版本与驱动是否与上述已知环境一致。
- 确认显卡显存:32 GB 卡在该分配规模下必然不足。
- 确认启动参数中是否启用了
cudagraph_mm_encoder,以及视频帧数num_frames、--max-num-batched-tokens的取值。 - 启动日志中检查
max_batch_size与max_frames_per_batch的推导值,判断捕获行数是否异常偏大。
解决步骤
- 可优先尝试:从
--compilation-config中移除或关闭cudagraph_mm_encoder,让 workload 先能启动。Issue 中报告该配置规避可让视频路径启动,但这不是对分配问题的修复。 - 关注 #61092:该 PR 将捕获行数限制为
token_budget // 70,4096 预算下从 1856 行降为 58 行;其中还提到在 L40S 上 gemma-4-E2B-it 视频 + encoder CG 可以启动。 - 升级到包含该行数上限修复的 vLLM 版本后,再恢复
cudagraph_mm_encoder: true验证。 - 若需要视频输出与 eager 路径一致,还需等待/包含 #60687 的相关修复。
验证方法
用相同启动参数重新启动引擎:若不再在 encoder CUDA graph 捕获阶段出现 CUDA out of memory,且日志中 max_frames_per_batch 对应的捕获行数与 token 预算的比例合理,说明行数上限生效;随后再跑一次视频输入请求,确认能正常返回并与 eager 模式输出做对比。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。

![[Roadmap] vLLM Roadmap Q3 2026](https://www.chat-gpts.plus/wp-content/uploads/2026/10/48168-07ca8ed3-768x403.jpg)
