最近在尝试用vLLM部署一个微调过的Qwen2.5-7B模型,单卡A100,开了tensor parallel=1,max_num_seqs设到了256。压测的时候发现QPS只能到10左右,GPU利用率一直在30%晃荡,显存倒是跑满了。我看别人都说7B能跑到30-50 QPS的,是不是我参数设置有问题?还是vLLM版本太旧?或者是不是我的prompt太长(平均1.5k tokens)导致的?有没有大佬能指点一下,该从哪里排查?感谢!
用vLLM部署7B模型,QPS上不去,GPU利用率才30%怎么回事?
全部回复
共 134 条prompt长确实吃显存带宽,你试试把max_num_seqs调低到64,同时开个continuous batching看看。
prompt长度影响很大,1.5k tokens吞吐肯定受影响,建议先测下短prompt的基线QPS再对比。
说实话你这情况挺典型的,1.5k的prompt长度对prefill阶段压力很大,QPS自然上不去。建议先看看是不是卡在prefill上,试试把max_num_seqs调低到64或32,同时把--enable-chunked-prefill打开,能显著提升吞吐。另外你确认下vLLM版本,0.6.x和0.7.x在调度策略上差别挺大,旧版对长序列支持确实不行。还有个小技巧,如果业务允许,把prompt做一下缓存或截断,效果会立竿见影。
显存跑满但算力闲置,这个特征很像prefill和decode阶段互相卡脖子。1.5k的prompt长度对7B来说计算量其实不小,你max_num_seqs拉到256反而可能让显存被prefill的中间态占满,decode阶段的batch反而起不来。建议先把max_num_seqs降到64左右试试,同时看看vLLM的server日志里有没有scheduler警告。另外QPS 10这个数字如果是包含长prompt的端到端延迟,那其实不算太离谱,别人报的30-50大概率是短输入(比如几百token)的测试条件。可以做个对比实验,把输入截断到512token压测,看QPS能到多少,这样能快速定位是不是prompt长度主导的问题。还有就是vLLM版本这坑我踩过,0.4.x和0.6.x的调度策略差异巨大,你最好升级到最新版再测。如果还不行,检查一下是不是微调模型导致KV cache的padding开销变大,可以开--enable-chunked-prefill试试。
显存跑满但利用率上不去,大概率是kv cache把batch卡死了,你max_num_seqs=256但实际并发可能远到不了那么多,可以看下日志里的实际running seqs数。另外1.5k prompt确实偏长,prefill阶段会占大量显存和算力,试试把prompt截断到512或者用chunked prefill选项,vLLM新版本这个优化挺明显的。还有你压测用的数据集和请求并发方式也得看看,是不是等待时间太长导致流水线空转。
prompt长度这个因素确实影响很大,1.5k tokens的输入会让prefill阶段占掉大量时间,而且显存跑满但利用率低很可能是卡在显存带宽上了。你可以试试把max_num_seqs调低到64或128,同时开一下vLLM的chunked prefill特性,应该能改善不少。另外检查下是不是PagedAttention的block大小没调对,默认16可能不太适合你的场景。版本太旧的话也建议升到最新,之前有个版本确实有调度问题。
你这个情况我遇到过类似的,问题大概率不在参数上,而是单卡A100跑7B本来就有点瓶颈,尤其是长prompt场景。建议先用静态输入长度压测对比下,比如固定128 tokens,看看QPS能到多少,如果还是上不去那就得查下是不是模型编译或CUDA版本的问题了。另外你压测工具本身会不会有瓶颈?换wrk或者ghz试试看。
显存跑满但GPU利用率低,典型的显存带宽瓶颈,长prompt意味着每生成一个token都要处理1.5k的KV cache,带宽全耗在读缓存上了。试试把max_num_seqs降到32,减少并发时KV cache的争抢,再量化成INT8或AWQ,带宽压力会小很多。我之前用同样配置跑8B模型,量化后QPS从12涨到了25,你可以参考
1.5k的prompt确实是关键,prefill阶段算力消耗大但并发又上不去,GPU利用率看着低很正常。你试试把max_num_seqs降到64甚至32,同时开下continuous batching的日志看看实际排队的sequence数,大概率是显存被长prompt占满导致等待。另外vLLM版本如果低于0.4.2的话建议升一下,老版本对长上下文的调度优化差挺多。还有压测别用单一固定长度prompt,混合长短请求测出来的数据才接近真实场景。
看到这个情况第一反应是prompt长度确实是个大坑,1.5k tokens意味着prefill阶段计算量占比很高,而vLLM的continuous batching对长prompt的调度效率会明显下降,QPS上不去很正常。你试试把max_num_seqs调低到64或者32看看,有时候256反而会造成显存碎片化,让batch里的请求长度差距太大,GPU一直在等最长的那个结束。另外确认下你的vLLM版本,0.4以上的话有chunked prefill功能,开了能把长prompt切成小块和decode混跑,对这类场景提升挺明显的。还有个思路是看看压测工具本身是不是瓶颈,比如并发请求数是不是够大,如果单线程发请求那GPU肯定饿着。最后建议用nvidia-smi dmon看下SM占用率和显存读写带宽,如果SM利用率也低但显存带宽跑满,那就是prefill计算密集但并行度不够,需要调整调度策略而不是单纯堆并发。我上次调8B模型也遇到过类似情况,最后发现是max_seq_len设太大导致KV cache预留过多,实际用到的少,白占显存。
你这prompt长度1.5k确实很拖后腿,试试把max_num_seqs调低到64或128,QPS能明显上来。
说实话你这个现象我太熟了,之前我用vLLM跑Yi-34B的时候也这样,显存吃满但算力上不去,最后查出来是max_num_seqs和block_size的锅。你设256其实有点太大了,尤其是prompt平均1.5k tokens的情况下,每个sequence占的KV cache空间会非常夸张,显存全被缓存占掉,但实际并行计算的batch没多少,GPU自然闲得慌。我建议你把max_num_seqs降到64或者128试试,同时看看--gpu-memory-utilization是不是默认值,有时候留个0.9给KV cache反而会让调度更灵活。另外你用的vLLM版本是啥?0.6.x和0.7.x的调度策略差挺多的,特别是对长prompt的处理,老版本很容易出现这种“假满载”的情况。还有个思路是直接看vLLM的日志,里面有个SchedulerStats会打印每个step的running/waiting/swapped序列数,如果swapped一直很高那就是显存碎片化严重,这时候可以开--enable-prefix-caching,或者把--max-model-len稍微调短一点,比如从32k砍到16k,很多场景下QPS能直接翻倍。你那边压测的时候并发数是怎么控制的?如果并发线程本身不够多,也会卡在等待上,跟vLLM关系不大。
看到你说显存跑满但GPU利用率只有30%,我第一反应是prefill和decode阶段混在一起导致的。1.5k tokens的prompt其实不算短,但vLLM对长prompt的continuous batching策略有时候反而会卡在显存带宽上,尤其你max_num_seqs拉到256,显存全被KV cache占了,计算单元反而在等数据搬运。建议你先试试把max_num_seqs降到64或者32,同时打开--enable-chunked-prefill,看看QPS有没有变化。另外你用的vLLM版本是多少?0.6.x和0.7.x的调度逻辑差别挺大的,旧版本对长序列的支持确实差不少。还有个容易忽略的点,你压测的时候并发请求数是多少?如果请求本身发送速率不够,GPU当然会闲着。最后可以看一眼nvidia-smi的功耗和显存带宽利用率,如果功耗也低,大概率是数据加载或调度开销卡脖子了,这时候可以试试把prompt填充到固定长度再测,排除掉动态形状的影响。
1.5k的prompt确实影响很大,prefill阶段会吃掉不少算力,你可以试试把max_num_seqs调低到64或者32,让batch小一点,看看GPU利用率会不会上来。另外vLLM版本太旧也可能有性能问题,建议升到最新版再跑一次,特别是paged attention的优化差别挺大的。
看到你说显存跑满但GPU利用率才30%,我第一反应是卡在prefill阶段了,1.5k的prompt长度对7B来说计算量其实不小,而且vLLM默认的chunked prefill策略可能没吃透这个场景。你可以先试试把max_num_seqs调低到64或者128看看,有时候并发太高反而导致频繁的显存换入换出,GPU一直在等数据搬运,算力自然上不去。另外检查下是不是开了--enable-prefix-caching,如果压测的请求里有重复的system prompt,这个开关能省大量重复计算,QPS可能直接翻倍。还有个小细节,vLLM版本差距挺大的,0.4.x和0.6.x的调度逻辑完全是两码事,建议直接升到最新版再测,老版本对长序列的支持很差。如果还不行,可以看看nvidia-smi里的power和温度,排除降频问题,但我觉得大概率不是这个。最后问一句,你压测用的数据集是固定prompt还是变长的?如果全是1.5k的固定长度,那瓶颈可能就在prefill的batch大小上,试试用--gpu-memory-utilization调低到0.85给KV cache留点余量,说不定有惊喜。
prompt长度影响很大,1.5k tokens的prefill会吃掉不少算力,试试把max_num_seqs调低到64或者128看看。
1.5k的prompt确实是个大问题,prefill阶段算力消耗远高于decode,你试试把平均长度降到500左右再压测,QPS应该能翻倍。另外max_num_seqs=256太大了,显存全被prefill占住,decode并发上不去,建议调成64甚至32看看。还有确认下vLLM版本,0.4以上对长序列的continuous batching优化差距挺明显的。
1.5k的prompt长度确实是关键,prefill阶段算力开销大但并发又上不去,导致GPU一直喂不饱。你试试把max_num_seqs调低到64,同时开个continuous batching的日志看下实际batch size,大概率是排队延迟拖垮了QPS。另外vLLM版本太旧的话对长序列的优化差很多,升到0.6以上会有明显改善。
显存跑满但利用率只有30%,大概率是prefill和decode混在一起互相挤占资源了,1.5k的prompt确实偏长,prefill阶段算力需求大但GPU并行度上不去。你可以试试把max_num_seqs调低到64或32,同时开一下--enable-chunked-prefill,让prefill和decode分开调度。另外确认下vLLM版本,0.4以上对长prompt优化差挺多的,建议升到0.6+。如果还不行,看看是不是微调时padding或attention mask有问题,某些实现会让计算量虚高。
你这情况明显是显存跑满但算力闲着,大概率卡在显存带宽或者KV cache分配上。试试把max_num_seqs调低到64,同时开下--enable-chunked-prefill,长prompt场景下效果很明显。另外确认下vLLM版本,0.4.2之前对长序列支持很拉胯,更新到0.5+可能直接翻倍。还有个小技巧,如果微调时padding到固定长度了,推理时记得关掉pad token,这也会吃掉不少显存和算力。
prompt长度确实是个大坑,1.5k tokens的话prefill占比太高了,QPS上不去很正常。你试试把max_num_seqs调低到64或者128,同时看看是不是被max_model_len卡住了,显存跑满但利用率低八成是等待batch填满。另外确认一下vLLM版本,0.4以上的话可以开--enable-chunked-prefill试试,能把prefill和decode混排,我这边之前7B从8QPS提到了20左右。
prompt长度确实是关键因素,1.5k tokens意味着prefill阶段占了很大比重,而vLLM的continuous batching在这种场景下容易成为瓶颈。你可以试试把max_num_seqs调低到64左右,同时开一下--enable-chunked-prefill,让prefill和decode交错执行,对吞吐提升挺明显的。另外确认下你的vLLM版本是不是0.6以上的,老版本在长上下文下调度策略很吃亏。还有个思路是压测时用不同长度的prompt混合测,看看是不是均匀分布下QPS能上来。
prompt长确实会影响,1.5k tokens的输入在prefill阶段会吃掉大量显存带宽,但你这GPU利用率才30%明显不对劲,大概率是vLLM版本太老导致continuous batching没生效,先升到0.6.x试试。另外max_num_seqs=256在长prompt场景下可能反而让显存碎片化严重,建议调回128同时把block_size改成16看看,我上次就是这俩参数调完QPS直接翻倍。