最近在把我们微调过的Qwen2.5-7B部署到内网服务器上,用vLLM跑的,开了gptq量化。理论上7B模型int4量化后显存占用应该在5-6G左右,但实际部署后nvidia-smi一看,单卡A10直接吃了14G,吞吐也只有200 tokens/s不到。我已经设置了max_model_len=4096,也开了continuous batching,但感觉没起到什么作用。怀疑是不是上下文预填充阶段太吃显存,还是量化版本选错了?求有经验的大佬指点一下,或者有没有什么工具能定位显存到底被什么占住了?提前感谢。
部署7B大模型到生产环境,显存占用比预想高很多怎么办?
全部回复
共 110 条显存大头在KV cache和预填充,试试vllm的--kv-cache-dtype和--gpu-memory-utilization,把利用率拉满再看。
14G确实有点离谱了,不过也不是完全没可能。vLLM的显存占用不只是权重,KV cache才是大头,尤其你没限制max_num_seqs的话它默认会按可用显存尽量多分配。A10是24G卡,vLLM启动时gpu_memory_utilization默认0.9,也就是它会主动吃掉差不多21G左右,你看到14G可能只是还没跑满或者被别的进程占了。先试试把gpu_memory_utilization调低到0.6左右,再看显存变化,能立刻判断是不是预分配的问题。另外Qwen2.5-7B的GQA是7个KV head,4096上下文单请求的KV其实不大,但并发一上来就指数级涨。吞吐200 tokens/s偏低,建议看看是不是batch size根本没起来,用vLLM的metrics接口看running/waiting队列。定位显存可以用torch.cuda.memory_summary或者py-spy配合nvml,实在不行先跑个纯推理脚本对比vLLM的占用差异。还有个坑是GPTQ在vLLM里有时候会走marlin kernel,权重加载方式不同显存表现也不一样,可以试试AWQ对比下。
14G确实有点离谱了,int4权重撑死也就5G出头,剩下那9G基本都是KV cache和框架自己的开销。A10是24G显存,vLLM默认会拿90%做gpu_memory_utilization,也就是21G左右,你看到的14G可能只是当前实际占用,不代表峰值。建议先把gpu_memory_utilization调到0.85试试,另外看看是不是有别的进程在偷吃显存。吞吐200确实太低了,A10跑7B int4正常应该能到800以上,你这个明显不正常。
排查的话可以用vLLM启动时加--enable-prefix-caching看看有没有改善,还有检查一下是不是没装flash-attn,没装的话prefill阶段会很慢很吃显存。另外Qwen2.5的tokenizer有时候会莫名其妙生成超长序列,max_model_len设了4096但实际请求如果超了会被截断重算,这块也容易踩坑。量化版本建议确认一下是GPTQ还是AWQ,AWQ在vLLM上一般表现更稳一些。
显存定位工具可以试试torch.cuda.memory_summary(),或者在vLLM里开VLLM_LOGGING_LEVEL=DEBUG看它自己打印的显存分配日志。我之前遇到过类似情况,最后发现是tensor parallel没配对加上swap空间设太大导致的,你可以先跑个最简单的单请求压测看看baseline。
你gptq量化后模型权重确实就5G左右,但vLLM跑起来KV cache是按max_model_len和并发数预分配的,4096长度下每个请求的KV cache可能就占不少,吞吐上不去说明batching没吃满。建议先用vLLM启动日志里的显存报告看下权重和KV各占多少,再试试把gpu_memory_utilization调低观察变化。另外A10这卡显存带宽和算力摆在那,200 tokens/s其实不算太离谱,先确认是不是卡本身就到瓶颈了。
14G确实偏高了,但7B int4跑出这个数也不算离谱,vLLM的KV cache是按max_model_len预分配的,你设4096的话光KV cache就可能占掉好几个G。另外gptq量化对显存的实际压缩效果经常没宣传的那么理想,权重之外还有激活和CUDA graph的开销。建议先用vLLM启动日志里的显存报告看看权重和KV各占多少,再拿py-spy或nsight抓一下,比nvidia-smi看总数有用得多。
KV cache才是大头,gptq权重只占4G左右,剩下全被缓存吃了,把gpu_memory_utilization调低试试。
14G确实偏高了,gptq权重本身占不了多少,大概率是KV cache被max_model_len和并发撑起来的。你可以试试调小gpu_memory_utilization,再拿vLLM启动日志里的显存分配报告看看,它会明确列出权重和KV cache各占多少。另外确认下是不是加载时没真正走到int4 kernel,有时候量化配置没对会退回fp16跑。
vLLM的显存占用确实不能只看模型权重本身。你算的5-6G只是权重部分,但实际跑起来KV cache才是大头,尤其你开了continuous batching之后,vLLM会预分配一大块显存给KV cache池,默认gpu_memory_utilization是0.9,也就是它会尽量把A10的24G吃到九成左右,14G其实还算克制了。想确认的话可以看启动日志里那行"GPU blocks"和"KV cache size"的提示,能算出实际留给KV cache多少。吞吐低可能跟你的并发请求数有关,如果压测时并发只有个位数,continuous batching根本没啥可batching的,自然上不去。另外gptq在vLLM上对Qwen2.5的支持要看版本,有些老版本的kernel没适配好,反而比awq慢,可以试试换awq量化对比一下。定位显存的话可以用torch.cuda.memory_summary()或者vLLM自带的metrics,比nvidia-smi粒度细多了。
gptq量化完模型权重确实就5G左右,但vLLM跑起来还有KV cache和CUDA graph的开销,A10这卡显存带宽也一般。你试试把gpu_memory_utilization调低点看它到底能压到多少,再拿vLLM自带的metrics看下running/waiting队列,如果prefill一直排队那吞吐肯定上不去。另外max_num_seqs设了多少?默认可能太小了,batching根本没吃满。
14G确实偏高了,但7B模型int4也不是只看权重,KV cache和vLLM的显存预分配都会算进去。你max_model_len=4096如果并发请求多,KV cache按block预留能吃掉不少,gpu_memory_utilization默认0.9也会让vLLM尽量占满。建议先把gpu_memory_utilization调低点,再用--num-gpu-blocks或启动日志看看KV cache实际分配了多少。量化版本也确认下是不是真的加载了GPTQ kernel,有时候fallback到未量化权重就白搭了。