最近在折腾本地部署,用vLLM跑一个微调过的7B模型(Qwen2.5),显存占用大概14GB,但吞吐量一直上不去。我试过调max_model_len和gpu_memory_utilization,也开了flash_attn,但QPS只有20左右,比官方说的差好多。我看网上有人用同样的卡跑13B都能到50+,不知道是哪里配置有问题?还是说我的模型量化没做好?另外,我是用docker部署的,会不会有额外的性能损耗?求大佬指点一下排查方向,谢谢!
用vLLM部署7B模型,单卡A100推理速度只有20tokens/s正常吗?
全部回复
共 169 条说实话20 tokens/s对于7B模型在A100上确实偏低了,我怀疑问题可能出在docker的网络和内存映射上,容器化部署有时候会因为共享内存或cuda驱动版本不一致带来额外开销,建议你试试直接在宿主机上跑一遍,或者检查下容器里nvidia-smi的输出是否真的绑定了A100。另外你提到量化没做好,这个很关键,vLLM对GPTQ或AWQ的支持比较成熟,如果你用的是原生fp16,显存占用14GB说明模型本身就已经满载了,试试4bit量化,应该能大幅提升并发能力。还有一个常见陷阱是max_model_len设得太大,比如2048以上,这会显著降低batch size,建议先调成512测试,同时把gpu_memory_utilization提到0.95,看看单次batch的生成速度能否翻倍。至于别人13B跑到50+,很可能是他们用了连续批处理且开了更大的batch size,或者模型本身没有微调过导致显存占用更小,你可以用vLLM的--enable-prefix-caching参数试下,对重复prompt加速明显。对了,确认下你的CUDA版本和vLLM版本是否匹配,我之前踩过坑,v0.4.2之后的版本对flash_attn的依赖改过,升级到最新版或者回退到稳定版可能直接解决问题。
20的QPS其实也不算特别离谱,7B模型在A100上吃满带宽的话,理论上限也就40-50左右,你docker跑肯定有损耗,建议直接在宿主机试试。另外检查下vLLM的调度参数,比如block_size改成16或者32,还有确认下flash_attn是不是真的生效了,有些docker镜像里cuda版本不对会导致它回退到普通attention。模型量化这块可以试试FP8或者AWQ,但7B本身参数不大,量化提升未必明显,先排查环境问题吧。
Docker确实会有一些网络和内存开销,但你这速度差太多了,检查下是不是显存碎片化严重或者没开continuous batching。
你这20tokens/s确实偏低了,我A100跑7B一般能到40左右。建议先确认下模型是不是原生fp16加载的,量化没做好反而会慢;另外docker网络模式用host试试,桥接模式确实有损耗。还有vLLM版本别太新,0.4.2之后有些改动反而对7B不太友好。
这速度确实不太正常,我自己的经验是7B模型在A100上vLLM跑起来至少得50-60 tokens/s才算合格。你提到的20 tokens/s感觉像是batch size没跑起来,vLLM默认是动态batching的,但如果你把max_num_seqs设得太小或者请求并发不够,它可能压根就没触发批量推理,单个请求跑就会很慢。另外Qwen2.5本身对vLLM的兼容性其实挺好的,但微调过的模型有时候会导致vLLM的缓存策略失效,尤其是如果你用了自定义的attention mask或者改了tokenizer的pad设置,建议检查一下模型文件里config.json的sliding_window参数有没有被意外修改。Docker的性能损耗其实可以忽略不计,除非你用了奇怪的网络模式或者挂载了慢速存储,我反而建议你直接跑一个原生环境做对比测试,排除掉容器层的影响。还有个小细节,gpu_memory_utilization别拉太高,留个1-2GB给CUDA kernel调度,不然显存碎片化也会拖慢速度。对了,你确认一下vLLM版本是不是0.6.0以上,老版本对Qwen2.5支持确实有性能问题。
你这情况我遇到过类似的,20t/s对于7B模型在A100上确实偏低了,尤其vLLM本身优化得不错。先确认一下是不是docker的共享内存限制问题,有时候默认的shm-size太小会导致页缓存效率下降,加上--shm-size=8g试试。另外你提到Qwen2.5,这个模型系列有分组查询注意力,vLLM对它的支持可能不如Llama那么成熟,可以试试把--enable-prefix-caching关掉,或者切换一下调度策略比如--use-v2-block-manager。还有,你说的量化,如果用的是FP16那应该不是瓶颈,但如果是GPTQ或AWQ,得确认下vLLM版本是否完全兼容,之前有段时间Quantized模型在vLLM上吞吐反而下降。最后,A100的带宽利用率对batch size很敏感,你可以把max_num_seqs从默认的256调大到512甚至1024,把吞吐压上去。如果还不行,建议用nvidia-smi dmon盯着看下GPU利用率是不是跑满了,有时候CPU数据预处理会拖后腿。
试试把docker的共享内存调大点,另外确认下vLLM版本是不是最新,有些老版本对Qwen支持确实拉胯。
20 tokens/s确实偏低了,我猜可能是batch size没拉起来?vLLM吃动态batching,你试试把max_num_seqs调到256甚至更高,同时确认下是否真的开启了continuous batching。另外docker网络模式如果用bridge会有额外拷贝开销,建议改成host模式跑一下对比。量化的话检查下是否真的加载了fp16,有时候自动转bf16反而拖慢速度。
这速度确实不太正常,我怀疑瓶颈不在vLLM本身而在数据预处理或模型配置上。你试试把--max-num-seqs调低点,比如32,有时候并发太高反而会拖慢单请求延迟。另外Qwen2.5的7B本身对A100来说应该很轻松,20t/s更像是被CPU喂数据卡住了,检查下dataloader是不是单进程。docker的话确实会有轻微损耗,但一般不到5%,不太可能是主因。你量化是用的AWQ还是GPTQ?如果只是FP16跑,那更得排查下是不是微调时把模型结构改坏了。
先确认下是不是被CPU瓶颈卡住了,docker部署本身损耗很小,但如果你没开--num-cpu-threads或者容器里CPU配额受限,prefill阶段会很拖后腿。另外20 tokens/s如果是单并发,那确实偏慢,试试压测时把并发拉到8-16,vLLM的continuous batching优势要在多并发下才明显。还有个小坑,Qwen2.5的GQA参数如果没在配置里正确加载,attention计算会退化,你可以看下日志里有没有警告。最后建议直接对比HuggingFace原版模型跑同样的prompt,排除微调后权重异常的影响。
20的QPS对7B确实偏低,先查下是不是没开continuous batching,另外docker网络模式用host试试。
20 tokens/s确实不太对劲,我拿A100跑Qwen2.5-7B(FP16)用vLLM默认参数都能到40-50,你试试把max_model_len设成4096看看,有时候上下文窗口开太大(比如32K)会显著拖慢prefill。另外docker本身损耗可以忽略,但如果你没加--ipc=host或者--shm-size给够,页缓存和显存换入换出会有怪问题,我踩过这个坑。量化这块如果是GPTQ或者AWQ,记得确认vLLM加载的是量化后的模型目录,不是原模型套个quantize参数,不然等于白搞。还有个容易被忽略的点——你微调时的padding和vocab_size如果跟基座不一致,vLLM的prefill阶段会有额外重算,建议用--revision或者直接重新导出下模型架构。最后,看看你的并发数是不是设太低,vLLM单请求吞吐本来就一般,把--max-num-seqs调到128以上,配合continuous batching效果会明显改善。如果还不行,用nvidia-smi盯一下GPU利用率,如果不到70%大概率是CPU预处理或者tokenizer成了瓶颈,可以升级到vLLM最新版试试,他们最近优化了Qwen系的前处理。
20的吞吐确实有点低了,不过先别急着怀疑量化,你check一下vLLM版本和CUDA版本匹配不,我之前因为pytorch和vLLM版本对不上掉到过10几。另外docker本身损耗很小,但注意容器里别限制CPU或内存,还有QPS得看并发数,单请求测和压测差很多。你试试把max_num_seqs调高到128,再把gpu_memory_utilization拉到0.95,A100跑7B应该能轻松50+的。
20的吞吐确实偏低了,我拿A100跑7B一般能到40-60,你试试把--max-num-seqs调大点,比如64或128,有时候显存没占满但队列太浅也会卡吞吐。另外你确认下微调的时候是不是用了padding,vLLM对非连续推理很敏感,模型里如果有动态padding会拖慢不少。docker的话网络和共享内存要开--ipc=host,否则数据拷贝会有额外开销,但影响通常没这么大。还有就是你量化了吗?如果只是FP16,建议先跑个官方未微调的Qwen2.5-7B对比下,排除模型本身的问题。
20 tokens/s对于7B模型来说确实偏低了,但先别急着甩锅给vLLM,我怀疑你docker的共享内存没给够。vLLM的paged attention在容器里如果/dev/shm太小,会疯狂触发swap到磁盘,这个瓶颈比量化影响大多了,你可以先docker run加个--shm-size=8g试试,我遇到过类似情况,改完直接翻倍。另外你说开了flash_attn,但确认下是不是真的生效了——A100上如果CUDA版本和flash-attn编译版本不匹配,它会静默回退到普通attention,日志里会有warning,你检查下启动输出。还有个小细节,Qwen2.5的7B本身激活参数不多,如果max_model_len调得很大(比如32k),prefill阶段计算量会显著拉低吞吐,你试试固定成4k或8k看QPS变化。至于量化,如果显存占用才14GB,说明权重还是FP16,你要是能接受一点精度损失,用AWQ或GPTQ量化到4bit,显存能压到7GB左右,同时因为内存带宽瓶颈变小,速度可能提到40+。最后,你网上看到13B跑50+的人,大概率是用了多卡张量并行或者batch size拉得很大,单卡A100跑13B FP16理论极限也就30多,别被那些benchmark误导了。建议先排查共享内存,再逐项调batch size(试着设到32或64),vLLM的吞吐跟并发数强相关,单请求测速没有参考意义。
docker跑vllm性能损耗很小,先看下是不是输入输出长度太长,20 tok/s对7B来说确实偏低了。
Docker网络和共享内存确实会吃点性能,但20也太低了,先查下是不是张量并行没开或者CPU绑核有问题。
20的吞吐确实偏低了,我怀疑瓶颈不在vLLM本身,而是微调后的权重和tokenizer没对齐,试试重新合并LoRA再加--enable-lora看看。另外docker的话网络和共享内存容易踩坑,记得加--shm-size=8g,不然数据搬运会有损耗。你显存才占14G,A100 40G的话可以试着把gpu_memory_utilization提到0.9,给KV cache留更多空间。量化方面如果用的是AWQ,注意下calibration数据集和你的业务分布差异大不大,这个影响挺明显的。
20 tokens/s对于7B模型来说确实偏低了,我怀疑瓶颈不在vLLM本身,而是你的微调模型里可能带了自定义算子或者动态shape,这会让vLLM的continuous batching失效。我之前遇到过类似情况,后来发现是模型里有个自定义attention mask导致无法走预编译的CUDA kernel,换成静态mask后吞吐直接翻了3倍。
另外你说docker部署,这个影响其实很小,除非你绑定了CPU核数或者内存限制导致显存和CPU之间拷贝变慢。可以试试在容器外直接跑一次对比,如果速度一样那就排除docker因素。更值得检查的是你用的vLLM版本,0.4.2和0.5.x之间优化差距巨大,尤其是对Qwen2.5的支持,建议升到最新版再测。
还有个容易忽略的点——你确认开了前缀缓存吗?如果微调数据里有很多重复的system prompt,不开prefix caching会浪费大量计算。至于量化,如果用的是FP16原生推理,20t/s确实不正常,但如果是AWQ或GPTQ,那这个速度反而合理,因为量化模型在A100上有时反而因为反量化开销变慢。
我建议你先用官方未微调的Qwen2.5-7B跑个基准,如果还是20,那就是环境问题(比如PCIe带宽受限或者GPU降频),如果官方模型能到50+,那问题就出在你的微调产物上。最后可以看看nvidia-smi里的GPU利用率,如果一直低于80%,那大概率是CPU预处理卡住了,试试增加--max-num-seqs到256看看。
20 tokens/s对7B来说确实偏低了,我猜你八成是没把vLLM的continuous batching吃满,单请求跑的话延迟好看但吞吐上不去。建议先用benchmark工具压并发,比如开8-16个并发请求看看QPS变化,如果线性增长那就不是模型或量化的问题。docker基本没损耗,除非你网卡或共享内存没配好,但推理是纯算力活,别在这上面花时间。另外你显存才占14GB,A100有40GB,剩下空间全给KV cache了,但max_model_len如果设太小会限制batch大小,试试把max_num_seqs调高到256。最后确认下你用的vLLM版本,老版本对Qwen2.5支持有bug,升级到0.6.3+再测一次。