最近在折腾本地部署,用vLLM跑一个微调过的7B模型(Qwen2.5),显存占用大概14GB,但吞吐量一直上不去。我试过调max_model_len和gpu_memory_utilization,也开了flash_attn,但QPS只有20左右,比官方说的差好多。我看网上有人用同样的卡跑13B都能到50+,不知道是哪里配置有问题?还是说我的模型量化没做好?另外,我是用docker部署的,会不会有额外的性能损耗?求大佬指点一下排查方向,谢谢!
用vLLM部署7B模型,单卡A100推理速度只有20tokens/s正常吗?
全部回复
共 28 条同问,最近也卡在这个问题上了。我也是Qwen2.5 7B,不过用的不是A100是4090,吞吐量比你高点有限,大概30出头,但看别人跑同样的模型能到50+,心里确实不平衡。
我这边排查了一圈,有几个点你可以试试看。首先docker确实可能有影响,我对比过裸机和docker,同样配置下docker大概会损失5%-10%的性能,主要是网络和GPU驱动间的overhead,不过影响不至于差这么多。
然后你提到量化,这很关键。7B模型如果没量化,A100跑20确实偏低但也不是完全离谱。你可以检查下模型是不是真的加载了量化版本,比如用AWQ或者GPTQ。我试过用bitsandbytes的4bit,吞吐能翻倍,不过精度会有点损失。vLLM对量化支持得挺好,可以看看是不是加载时忘了指定quantization参数。
另外max_model_len也别调太小,我之前设成2048反而比4096慢,后来发现是因为频繁触发prefill。你试试设成4096或者8192,有时候反而更顺。还有gpu_memory_utilization别超过0.9,留点显存给kv cache,不然容易OOM然后降速。
调度策略也值得看看,vLLM默认用round-robin,你试试换成prefill-aware或者把max_num_batched_tokens设大点。不过这个得结合你的实际请求长度来调,建议用wrk或者locust压测一下长尾场景。
最后,确认下flash_attn是不是真的生效了,可以看日志里有没有类似“Using FlashAttention”的提示,有时候版本不匹配会静默降级到普通attention,那个速度差很多。
以上都是我踩坑踩出来的,不一定全对,但方向应该没问题。你要是找到其他原因也告诉我一声,一起进步。
20 tokens/s对于7B模型在A100上确实偏低了,但也不至于离谱到完全不能接受——得看你具体怎么跑的。vLLM的吞吐瓶颈很多时候不在模型本身,而在prefill和decode阶段的调度策略。
首先,QPS 20这个数据如果是包含prefill时间的端到端吞吐,那大概率是batch size没喂上去。vLLM默认是continuous batching没错,但如果你实际请求的并发数不够高(比如单线程压测),那它根本触发不了batching优化,等于退化成串行推理。你试试用vllm.entrypoints.openai.api_server启动后用benchmarks/benchmark_serving.py多路并发压一下,看峰值QPS能不能拉到50+。
其次,Qwen2.5的7B原生支持GQA,但如果你微调时改动了attention结构(比如用了LoRA),vLLM的PagedAttention可能没完全对齐,导致显存碎片化严重。你检查下/tmp/vllm/vllm_engine_*.log里有没有kv_cache size的warning,如果cache利用率低于70%,那gpu_memory_utilization设再高也没用。
docker性能损耗这块,我建议直接nvidia-smi dmon跑一下看GPU利用率。如果GPU-Util卡在30%以下,那大概率是CPU喂数据的速度跟不上——检查下vllm的max_num_batched_tokens是不是设得太保守,或者你用了--enable-prefix-caching但请求无前缀复用,白占调度开销。
最后,13B跑到50+的那个案例,我怀疑要么是对方用了FP8或INT4量化(A100不支持原生FP8,得靠triton手写kernel),要么就是用了更高的并发+更短的输入输出。你确认一下自己测试时的input/output长度,如果平均生成512 tokens,那20 t/s其实不算差。建议先拿官方vLLM benchmark的默认参数跑个baseline再排查。
同问,最近也在折腾vLLM部署,不过是8B的模型,A100 40G,跑下来也差不多20多tokens/s,一直怀疑是不是自己哪里没调对。看到你说13B能跑到50+,我也有点懵……不过仔细想想,会不会跟量化关系挺大的?我试过FP16和INT4,INT4确实能快一截,但也没到翻倍的程度。你有试过AWQ或者GPTQ量化吗?我看官方文档说vLLM对这两种量化支持得比较好,吞吐能提升不少。
另外docker那个点我也有同样的困惑。之前看过一些讨论,说docker的网络模式和共享内存设置会影响性能,尤其是--shm-size,如果设太小,模型加载和推理时可能会卡在内存分配上。你docker跑的时候有没有加--ipc=host或者调大shm-size?我试过从默认64M改成8G,体感上吞吐确实稳了一点,但不确定是不是心理作用。
还有就是你max_model_len设了多少?如果设太大,虽然能加载长序列,但会浪费显存,导致batch size上不去,vLLM的continuous batching效果就出不来。我自己的经验是尽量压到实际需要的长度,比如4096或8192,同时gpu_memory_utilization留个0.9左右,别太满。另外flash_attn版本也很关键,旧版本可能兼容性有问题,建议确认下vLLM和flash_attn的版本对不对得上。
最后问下,你那个模型是微调过的,会不会是模型架构上有什么改动,导致vLLM的优化用不上?比如自定义了attention或者加了额外的层?我之前试过一个加了lora的模型,吞吐就比原版低了不少。希望你能排查出来,回头也分享下经验!
docker确实会有网络和内核开销,建议裸机对比一下,另外检查下vLLM版本和CUDA版本是否匹配。
20的tokens/s对7B来说确实偏低了,我猜主要瓶颈可能在docker的网络和内存映射上,可以试试直接宿主机跑一下排除这个干扰。另外你说的13B能到50+,那个大概率是用了FP8或者INT4量化,你的模型如果还是BF16/FP16,单卡A100跑7B这个速度其实也算正常范围。建议先检查下vLLM的日志里有没有显存碎片化提示,或者试试把max_model_len设小一点,比如2048,看单batch延迟有没有改善。
说实话20 tokens/s对于7B模型在A100上确实偏低了,我怀疑问题可能出在几个地方。你提到开了flash_attn,但vLLM的版本和CUDA环境有没有对齐?有时候老版本vLLM搭配新驱动反而会触发bug。另外Qwen2.5的7B本身用fp16推理的话,单卡A100理论吞吐应该能到80-100 tokens/s左右,建议先检查一下是不是模型文件本身有损坏或者微调时混入了奇怪的算子。docker倒不一定有太大性能损耗,除非你绑定的CPU核心数或者内存限制太紧,导致数据预处理卡IO。还有个小细节,如果用了vLLM的continuous batching但没调好max_num_seqs,默认值可能太低,你可以试试把这个参数提到256以上。最后建议用nvidia-smi确认一下显卡是不是跑在PCIe 3.0或者被降频了,A100被限速的情况还挺常见的。
20的tokens/s对于7B确实偏低了,我猜可能是docker的显存分配和vLLM的page管理有冲突,建议试试不用docker直接跑一次对比下。另外你那个gpu_memory_utilization调了多少?如果设得太高反而会让vLLM频繁做显存交换,可以降到0.85左右看看。还有Qwen2.5的7B本身对prefill阶段比较敏感,max_model_len设得太大会拖慢首token延迟,可以先用1024测试一下基准性能。
试试把batch size调到32以上再测,单条推理vLLM的优势发挥不出来。
检查下vLLM版本和CUDA环境,旧版对Qwen2.5支持不好,建议升到0.6.0以上试试。
20的QPS对于7B模型来说确实偏低,我怀疑不是vLLM本身的问题,而是docker的网卡或内存带宽被限制了,可以试试裸机跑一下对比。另外你确认下是不是用了flash_attn的官方版本,有的魔改版反而会降速,而且Qwen2.5对batch size比较敏感,单条请求跑满显存反而效率低。如果模型没量化,可以试试AWQ或GPTQ,A100上4-bit推理能快不少,不过要记得同步调整下采样参数。
20的qps对于7B确实偏低了,我估计问题大概率出在docker的网络和内核参数上,vLLM对容器环境挺敏感的,建议先裸机跑一下排除环境干扰。另外你微调过的模型会不会是fp16没对齐?可以检查下模型加载时的精度设置,有时候混了int4就会拖慢。还有你max_model_len调到多少了?设太大对短序列推理会有负优化,试试调成2048看看有没有改善。
20的QPS确实偏低了,检查下vLLM版本和CUDA版本是否匹配,另外docker的网络模式可能有影响。
20的tokens/s确实偏低了,我怀疑问题出在docker的网络或显存隔离上,可以试试直接在宿主机跑一下排除这个干扰。另外Qwen2.5对vLLM的版本有要求,你确认一下是不是最新版,老版本对某些架构支持不好。还有你调gpu_memory_utilization的时候有没有留够kv cache的空间?我之前就是把这个值设太高反而把吞吐卡住了,降到0.85左右反而能跑到40+。
20的qps对7B来说确实偏低,但A100单卡跑这个规模理论上限也就40-50左右,官方数据通常是用最佳batch和连续请求压出来的。你试试把max_num_seqs调到256以上,或者确认下是不是docker里CPU内存分配不够导致GPU利用率上不去,我之前遇到过容器内存锁页导致性能腰斩的情况。另外如果模型没量化成FP16或INT8,显存占用14GB可能说明精度还是FP32,这也是个容易忽略的点。
20 tokens/s确实不太正常,我怀疑瓶颈可能在数据加载或预处理上,vLLM对输入长度和batch size挺敏感的,试试把max_num_seqs调大点,比如64或128。另外docker网络模式用host模式能减少一些开销,我踩过这个坑。量化的话,如果没做AWQ或GPTQ,可以试试转成4bit,显存占用降下来后吞吐会有明显提升。
20确实有点低了,我之前用vLLM跑同尺寸模型单卡A100基本在40-50左右。你检查下是不是max_model_len设得太小导致频繁重新计算,或者gpu_memory_utilization设得太保守没充分利用显存?另外docker网络和共享内存配置也可能有影响,建议换个原生环境对比下排除干扰。
20 tokens/s确实偏低了,我拿同款卡跑7B一般能到40-50,建议先检查下vLLM的调度参数,比如把block_size设成16或者32试试。docker确实会有一些网络和显存管理上的开销,但通常不会差这么多,更可能是模型没量化到位,或者max_model_len设得太保守了。另外确认下是不是开了多卡通信但实际只用单卡在跑,有时候环境变量没配好会吞性能。
20 tokens/s对7B模型来说确实偏低,但也没到离谱的程度——vLLM官方benchmark通常是在理想批处理场景下测的,单条请求加小batch size很容易被调度开销拖慢。你先确认下实际并发数,如果只跑单条流式输出,这个速度其实算正常范围。倒是你提到13B能跑到50+,我怀疑是对方用了更大的batch size或者做了AWQ/GPTQ量化,7B模型显存余量大但没充分利用也会导致吞吐上不去。docker性能损耗一般很小,除非你网络模式或共享内存没配好,可以试试挂--ipc=host参数。另外建议检查下vLLM版本,老版本对Qwen2.5的支持有bug,升级到0.6.0以上可能会有改善。还有个小细节:gpu_memory_utilization别设太高,留点余量给kv cache的碎片化,0.85到0.9之间比较稳妥。如果还不行,试试把max_num_seqs调到64以上,让vLLM的连续批处理机制真正跑起来。
先检查下是不是vLLM版本太旧,新版本对Qwen优化好很多,另外docker确实会有网络和内存开销。
20 tokens/s对于7B模型在A100上确实偏低了,我自己的经验是同样用vLLM部署Qwen2.5-7B,单卡A100-80G不开量化也能跑到35-40左右,峰值甚至能到50+。你的显存占用14GB其实有点奇怪,正常7B模型在vLLM里就算开了gpu_memory_utilization=0.9,加上KV cache应该也到不了这么高,是不是max_model_len设得太大了?比如设成8192或者更高,那对长序列吞吐影响很明显。另外建议检查一下vLLM版本,我之前用0.4.0的时候也有类似瓶颈,升级到0.6.0之后调度优化了不少。docker的性能损耗理论上很小,但如果你挂载了额外的存储或者网络配置有问题,也可能导致IO延迟,可以试试直接跑原生环境对比一下。还有一点,如果你用了AWQ或者GPTQ量化,QPS反而可能下降,因为7B模型本身显存压力不大,量化反而增加了decode时的计算开销。最后,网上那些13B跑50+的说法最好确认下是不是用了多卡张量并行,或者batch size开得很大,单卡单请求很难到这个水平。