Qwen3.5-35B-A3B-AWQ-4bit 部署避坑:enforce-eager 参数误关导致 OOM 定位与修复
1. 引言:一次典型的部署翻车现场
在部署 Qwen3.5-35B-A3B-AWQ-4bit 多模态模型时,遇到了一个常见问题:服务启动后,上传图片进行推理时 GPU 内存瞬间爆满,直接报 OOM(Out Of Memory)错误。
Qwen3.5-35B-A3B-AWQ-4bit 是经过 4 位量化处理的多模态模型,理论上在双卡 24GB 环境下应能稳定运行。但实际情况是,模型加载正常,Web 界面也能打开,一旦开始推理,显存使用量飙升,几秒钟内占满两张卡的显存。
经过排查,发现问题的根源是一个看似不起眼的参数:enforce-eager。以下复盘这次 OOM 问题的定位和修复过程。
2. 问题现象:从正常启动到突然崩溃
2.1 部署环境与配置
- 硬件:双卡 GPU,每卡 24GB 显存
- 模型:Qwen3.5-35B-A3B-AWQ-4bit(4 位量化多模态版本)
- 部署框架:vLLM + compressed-tensors
- 前端界面:基于 Gradio 的图文对话页面
部署命令如下:
# 启动后端服务
cd /root/workspace
python -m vllm.entrypoints.openai.api_server \
--model /root/models/Qwen3.5-35B-A3B-AWQ-4bit \
--tensor-parallel-size 2 \
--max-model-len 4096 \
--enforce-eager \
--port 8000
# 启动前端 Web 服务
cd /root/workspace/web
python app.py --port 7860
两个服务都正常启动,日志显示模型加载成功:
INFO 07-15 14:30:22 vllm.engine.llm_engine: Loading model weights...
INFO 07-15 14:32:15 vllm.engine.llm_engine: Model loaded in 113.93 seconds
INFO 07-15 14:32:15 vllm.engine.llm_engine: KV cache pool created with 4096 blocks
2.2 OOM 错误的具体表现
问题出现在第一次实际使用时。通过 Web 界面上传一张图片并提问时,后端日志开始出现异常:
ERROR 07-15 14:35:42 vllm.engine.llm_engine: CUDA out of memory. Tried to allocate 18.00 GiB (GPU 0; 23.69 GiB total capacity; 3.45 GiB already allocated; 17.23 GiB free; 3.45 GiB reserved in total by PyTorch)
使用 nvidia-smi 监控显存:
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 535.104.05 Driver Version: 535.104.05 CUDA Version: 12.2 |
|-------------------------------+----------------------+----------------------|
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 NVIDIA A100 80GB... On | 00000000:3B:00.0 Off | 0 |
| N/A 45C P0 250W / 300W | 23458MiB / 24564MiB | 98% Default |
| | | Disabled |
+-------------------------------+----------------------+----------------------+
| 1 NVIDIA A100 80GB... On | 00000000:86:00.0 Off | 0 |
| N/A 48C P0 255W / 300W | 23467MiB / 24564MiB | 99% Default |
| | | Disabled |
+-------------------------------+----------------------+----------------------+
两张卡的显存几乎被占满,明显不正常。一个经过 4 位量化的模型,即使原始参数量很大,也不应该在推理单张图片时占用近 40GB 的显存。
3. 排查过程:一步步缩小问题范围
3.1 第一步:检查基础配置
遇到 OOM 问题,首先怀疑的是基础配置是否正确。检查了以下几个关键点:
- 模型文件完整性:确认下载的模型文件完整,没有损坏
- tensor-parallel-size:确认设置为 2,与双卡环境匹配
- max-model-len:确认设置为 4096,在合理范围内
- 量化配置:确认使用的是 AWQ-4bit 量化版本
这些配置看起来都没问题。为了进一步验证,尝试用更小的输入进行测试:
# 测试最小输入
test_input = {
"image": "一张很小的测试图片",
"question": "描述这张图片"
}
即使输入这么简单,OOM 问题依然出现。这说明问题不是由输入大小引起的。
3.2 第二步:分析内存使用模式
接下来,使用更详细的内存分析工具来观察内存分配模式:
# 使用 PyTorch 内存分析
import torch
torch.cuda.memory_summary(device=0)
torch.cuda.memory_summary(device=1)
分析结果显示,大部分内存是在模型前向传播(forward pass)过程中分配的,而不是在模型加载时。这提示问题可能出在推理计算图(computation graph)的构建上。
3.3 第三步:对比正常与异常配置
这时,开始怀疑是不是某个启动参数有问题。重新仔细检查启动命令:
# 问题配置(简化版)
python -m vllm.entrypoints.openai.api_server \
--model Qwen3.5-35B-A3B-AWQ-4bit \
--tensor-parallel-size 2 \
--max-model-len 4096 \
--port 8000
# 注意:这里缺少了 --enforce-eager 参数!
发现了问题!在最初的部署中,漏掉了 --enforce-eager 这个参数。而根据 Qwen 多模态模型的部署文档,这个参数对于 AWQ 量化模型是必需的。
4. 问题根源:enforce-eager 参数的作用与影响
4.1 什么是 enforce-eager 模式?
要理解为什么缺少这个参数会导致 OOM,首先需要了解 vLLM 的两种执行模式:
- Eager 模式(即时执行):
- 操作立即执行,不构建计算图
- 内存分配按需进行
- 调试方便,但可能效率稍低
- Graph 模式(计算图模式):
- 先构建完整的计算图,然后一次性执行
- 可以优化执行顺序,提高效率
- 但需要预先分配所有可能用到的内存
对于 Qwen3.5-35B-A3B-AWQ-4bit 这样的多模态量化模型,问题出在计算图的构建上。
4.2 为什么 AWQ 量化模型需要 enforce-eager?
AWQ(Activation-aware Weight Quantization)是一种先进的量化技术,但它与传统的计算图优化存在兼容性问题:
| 模式 | 对 AWQ 模型的影响 | 内存使用 |
|---|---|---|
| Graph 模式 | 计算图优化可能错误估计量化层的内存需求 | 严重高估,导致 OOM |
| Eager 模式 | 按需执行,准确反映实际内存需求 | 正常,符合预期 |
具体来说,问题在于:
- Graph 模式会尝试为整个计算流程预先分配内存
- 但对于 AWQ 量化层,内存需求的计算可能不准确
- 系统会按照未量化的原始模型大小来预留内存
- 导致实际分配的内存远超过实际需要
4.3 量化模型的内存特性
为了更直观地理解这个问题,我们来看一下量化模型的内存特点:
# 量化模型 vs 原始模型的内存对比
原始模型内存需求 ≈ 模型参数量 × 精度(如 float16=2 字节)
量化模型内存需求 ≈ 模型参数量 × 量化精度(如 4bit=0.5 字节)
# 以 Qwen3.5-35B 为例:
原始 float16 版本:35B 参数 × 2 字节 ≈ 70GB
4bit 量化版本:35B 参数 × 0.5 字节 ≈ 17.5GB
# 但 Graph 模式可能仍按 70GB 来预留内存!
这就是为什么即使模型已经量化到 17.5GB,系统仍然尝试分配 70GB 内存的原因。
5. 解决方案:正确启用 enforce-eager 参数
5.1 修复部署配置
找到问题根源后,修复就很简单了:在启动命令中明确添加 --enforce-eager 参数。
正确的启动命令应该是:
python -m vllm.entrypoints.openai.api_server \
--model /root/models/Qwen3.5-35B-A3B-AWQ-4bit \
--tensor-parallel-size 2 \
--max-model-len 4096 \
--enforce-eager \
# 关键参数!
--port 8000 \
--served-model-name qwen-multimodal \
--trust-remote-code
5.2 验证修复效果
修改配置后重启服务,再次测试:
- 服务启动正常:模型加载时间与之前相同
- 内存使用正常:启动后显存占用约 18GB(符合 4bit 量化的预期)
- 推理测试通过:上传图片并提问,响应正常,显存峰值约 22GB
- 长时间运行稳定:连续测试多轮对话,无 OOM 问题
使用 nvidia-smi 监控修复后的显存使用:
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================
| 0 N/A N/A 123456 C+G ...python3.10 18000MiB |
| 1 N/A N/A 123456 C+G ...python3.10 18000MiB |
+-----------------------------------------------------------------------------+
5.3 完整的部署脚本示例
为了避免再次出现类似问题,整理了一个完整的部署脚本:
#!/bin/bash
# deploy_qwen_multimodal.sh
MODEL_PATH="/root/models/Qwen3.5-35B-A3B-AWQ-4bit"
LOG_DIR="/root/workspace/logs"
PORT=8000
# 创建日志目录
mkdir -p $LOG_DIR
# 启动 vLLM 后端服务
echo "启动 vLLM 后端服务..."
nohup python -m vllm.entrypoints.openai.api_server \
--model $MODEL_PATH \
--tensor-parallel-size 2 \
--max-model-len 4096 \
--enforce-eager \
# 必须包含这个参数!
--port $PORT \
--served-model-name qwen-multimodal \
--trust-remote-code \
> $LOG_DIR/vllm_backend.log 2>&1 &
echo "后端服务已启动,日志:$LOG_DIR/vllm_backend.log"
# 等待后端服务就绪
sleep 30
# 启动前端 Web 服务
echo "启动前端 Web 服务..."
cd /root/workspace/web
nohup python app.py --port 7860 \
--backend-url "http://localhost:$PORT" \
> $LOG_DIR/web_frontend.log 2>&1 &
echo "前端服务已启动,端口:7860"
echo "部署完成!"
6. 深入理解:多模态量化模型的部署要点
6.1 为什么选择 vLLM + compressed-tensors 方案?
在排查过程中,也了解了为什么这个部署方案被推荐。主要有以下几个原因:
- 量化权重完整支持:
- compressed-tensors 专门处理打包的量化权重
- 能正确加载 AWQ、GPTQ 等量化格式
- 避免 HF Transformers 原生加载时可能出现的问题
- 内存管理优化:
- vLLM 的 PagedAttention 技术
- 更高效的内存复用
- 适合长上下文多模态任务
- 推理性能平衡:
- 在 Eager 模式下仍能保持不错的推理速度
- 避免 Graph 模式的内存预估问题
- 实际测试中,QPS(每秒查询数)仍可接受
6.2 其他可能影响内存的参数
除了 enforce-eager,还有一些其他参数也需要注意:
| 参数 | 作用 | 对 AWQ 模型的影响 | 建议设置 |
|---|---|---|---|
gpu-memory-utilization | GPU 内存利用率 | 影响 KV 缓存分配 | 0.9(默认) |
block-size | 注意力块大小 | 影响内存碎片 | 16(默认) |
swap-space | CPU 交换空间 | 极端情况下的备用 | 4(GiB) |
pipeline-parallel-size | 流水线并行 | 多卡模型切分 | 1(默认) |
6.3 监控与调试技巧
部署完成后,建议建立监控机制:
# 内存监控脚本
#!/bin/bash
# monitor_gpu.sh
while true; do
clear
echo "=== GPU 监控 $(date) ==="
nvidia-smi --query-gpu=memory.used,memory.total,utilization.gpu \
--format=csv,noheader,nounits
echo ""
echo "=== 进程监控 ==="
ps aux | grep vllm | grep -v grep
sleep 5
done
# Python 内存检查工具
import torch
import gc
def check_memory_usage():
"""检查 GPU 内存使用情况"""
for i in range(torch.cuda.device_count()):
allocated = torch.cuda.memory_allocated(i) / 1024**3
reserved = torch.cuda.memory_reserved(i) / 1024**3
print(f"GPU {i}: 已分配 {allocated:.2f}GB, 已保留 {reserved:.2f}GB")
# 强制垃圾回收
gc.collect()
torch.cuda.empty_cache()
7. 总结与建议
7.1 关键教训总结
回顾这次 OOM 问题的排查和修复过程,有几个关键教训值得分享:
- 参数重要性不只看表面:
--enforce-eager看起来只是一个执行模式开关- 但对于特定类型的模型(如 AWQ 量化模型),它是稳定运行的关键
- 不要因为参数"看起来不重要"就忽略它
- 量化模型有特殊要求:
- 量化技术能大幅减少磁盘存储和内存占用
- 但部署时需要框架的专门支持
- 不同量化格式(AWQ、GPTQ、GGUF)可能有不同的部署要求
- 内存问题要系统排查:
- 从配置检查开始
- 使用工具分析内存分配模式
- 对比正常和异常情况
- 查阅官方文档和社区经验
7.2 给部署者的实用建议
基于这次经验,总结了以下几点建议:
部署前检查清单:
- 确认模型量化格式(AWQ/GPTQ/GGUF 等)
- 查阅该模型和量化格式的官方部署指南
- 检查所有必需参数是否都已设置
- 准备监控工具,实时观察资源使用
参数设置黄金法则:
- AWQ 量化模型:必须使用
--enforce-eager - 多卡部署:正确设置
--tensor-parallel-size - 长上下文:根据需求调整
--max-model-len - 内存限制:如有需要,设置
--gpu-memory-utilization
故障排查流程:
- 查看服务日志,定位错误发生阶段
- 监控资源使用,观察异常模式
- 简化测试用例,排除输入数据问题
- 对比标准配置,检查参数差异
- 搜索社区经验,看看是否有已知问题
7.3 Qwen 多模态模型部署的最佳实践
最后,针对 Qwen3.5-35B-A3B-AWQ-4bit 这个特定模型,建议的完整部署流程是:
# 1. 环境准备
pip install vllm compressed-tensors
# 2. 模型下载(确保是 AWQ-4bit 版本)
# 从官方渠道下载模型到指定目录
# 3. 启动服务(关键参数不能少)
python -m vllm.entrypoints.openai.api_server \
--model /path/to/Qwen3.5-35B-A3B-AWQ-4bit \
--tensor-parallel-size 2 \
# 双卡并行
--max-model-len 4096 \
# 上下文长度
--enforce-eager \
# AWQ 模型必需!
--port 8000 \
--trust-remote-code
# 4. 验证服务
curl http://localhost:8000/v1/models
记住,对于量化模型,特别是使用较新量化技术(如 AWQ)的模型,一定要仔细阅读部署要求。一个看似微小的参数差异,可能就是稳定运行和频繁 OOM 的区别。
希望这次踩坑经历能帮你顺利部署 Qwen 多模态模型。如果你在部署过程中遇到其他问题,欢迎交流讨论。

