先把当时的情况摆出来。同一张 80GB 卡跑 Llama-3-8B,bf16 时 batch 上限能到 32,换成 GPTQ 4bit 权重后只能到 18,再多就报 CUDA out of memory,可 nvidia-smi 显示还剩 20GB。环境是 vLLM 0.6.3 的 gptq_marlin 后端,gpu_memory_utilization 给到 0.95 也一样。
排查方向其实有限,先把可能性排一排。marlin kernel 需要额外的 workspace 做反量化。少数情况下是4bit 省下的权重显存被 KV cache 和临时缓冲吃掉。
还有一种情况,max_num_seqs 没跟着调,调度器仍按旧的并发数分配块。另外,反量化后的激活是 bf16,并没有随权重一起变小。
动手时先看实际可用的 KV cache 块数
curl -s http://127.0.0.1:8000/metrics | grep -i cache
随后把并发序列数调到与显存匹配
python -m vllm.entrypoints.openai.api_server --model ./llama3-gptq --quantization gptq_marlin --max-num-seqs 16
给 workspace 留出余量再启动
python -c "print('gpu_memory_utilization 0.95 -> 0.90')"
末了用固定长度输入压测确认不再 OOM
curl -s http://127.0.0.1:8000/v1/completions -H 'Content-Type: application/json' -d '{"model":"llama3","prompt":"hi","max_tokens":64}'
中途换过一次思路,把范围缩到最小的那一层,反而快了。
别只看报错消失,验证要多做一步。并发 18 个请求连续跑 10 分钟无 OOM,吞吐比 bf16 高 1.6 倍,首字延迟没有明显上升。
量化省的是权重显存,KV cache 和 kernel workspace 一点没省,按权重压缩比去推算 batch 上限一定会估错。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
