最近在搞一个内部知识库问答demo,选Qwen2.5-7B用vLLM部署在单卡A100上。按官方文档设了max_num_seqs和gpu_memory_utilization,结果显存直接冲到80GB,但并发压力测试时tokens/s只有200左右,跟网上说的差好多。而且感觉不少显存被模型本身和KV cache吃了,但实际推理时QPS一上去就卡住,日志里也没报错。自己试过改max_model_len到4096也没改善。请教各位大佬,是不是我prefill阶段的参数没调好?还是vLLM对不同模型有特定推荐配置?或者干脆得切Tensor Parallel?先谢谢了。
用vLLM部署Qwen2.5-7B,显存占满但推理速度上不去,是哪里没调对?
全部回复
共 147 条看到这个情况有点眼熟,我之前用vLLM跑7B也踩过类似的坑。你显存冲到80GB其实不奇怪,因为默认情况它会把能用的显存全拿去预分配,KV cache预留大了但实际并发没跟上,利用率自然上不去。建议先查一下实际并发时的batch size,max_num_seqs调大并不代表每个request都会占满,有时候反而因为调度开销导致吞吐下降。另外你提到QPS一上去就卡住,我怀疑是prefill和decode阶段资源争抢,vLLM默认策略下长prompt的prefill会挤占decode的算力,试试打开chunked prefill选项,或者手动限制一下max_num_batched_tokens。Tensor Parallel在单卡上没意义,别往那想。还有个小技巧,如果知识库问题普遍很短,可以故意把max_model_len调小到2048甚至1536,给KV cache留出余量,但qwen2.5的attention实现比较吃显存,你得看下官方issue有没有针对7B的推荐配置。最后建议用vllm的benchmark脚本跑一下纯synthetic数据,排除你业务prompt里有没有超长文本或者特殊pattern导致prefill特别慢。
A100跑7B才200 tok/s确实不对劲,先查下是不是喂的请求序列太长导致prefill瓶颈,开个chunked prefill试试。
说实话你这个问题我上个月刚踩过一模一样的坑,A100 80G跑7B模型理论上不该这么拉胯。建议先查一下vLLM的版本,我之前用0.4.2跑Qwen系列就有显存分配异常,升到0.5.x之后单卡吞吐直接翻倍。另外你max_num_seqs设了多少?我试过把它从默认的256压到64,同时把max_num_batched_tokens调小,反而QPS稳定很多,因为prefill阶段不会一下子把显存全抢走。还有你确认一下是不是没开continuous batching,新版vLLM默认开,但如果你手动改了scheduler参数可能会关掉。至于KV cache,7B模型在4096长度下其实吃不了多少,你显存80G全占满大概率是预分配策略的问题,试试把gpu_memory_utilization降到0.85,留点余量给碎片。另外别急着上Tensor Parallel,单卡能搞定的事情上多卡反而会因为通信开销掉速。最笨但有效的办法是开vLLM的--verbose日志看每个step的调度时间,如果发现等待时间远大于计算时间,那就是batching策略没生效。最后建议你换一下最新版的VLLM,他们针对Qwen2.5专门优化过attention的计算图,我这边实测同样配置下tokens/s从220涨到380了。
这问题我之前调Qwen系列也撞过,A100上80G显存吃满不奇怪,7B模型加长上下文KV cache本来就很占。但200 tokens/s确实偏低,先看看是不是max_num_seqs设太大导致prefill和decode互相抢资源。另外vLLM对Qwen的推荐配置其实在官方issue里有,有个--enable-prefix-caching你试过没,对知识库那种重复前缀效果很明显。如果并发QPS一上去就卡,八成是输入长度分布太散,建议把max_model_len调小到2048,同时限制单请求最大长度试试。TP暂时没必要,单卡A100跑7B用不上,先检查一下是不是cpu绑核或者数据加载瓶颈。
说实话你这情况我上周刚踩完坑,A100 80G跑7B按理说应该很宽裕,但vLLM默认会按比例给KV cache留大量显存,gpu_memory_utilization设太高反而会让prefill阶段把显存一次性吃满,然后decode阶段没空间做调度。我试过把utilization调到0.75,同时max_num_seqs降到16,吞吐反而上去了,你可以先往这个方向压一下参数试试。另外Qwen2.5的attention实现跟Llama不太一样,vLLM对它的continuous batching策略可能没那么激进,建议你翻一下官方issue,有个--enable-prefix-caching参数开了之后对知识库场景特别管用。至于TP,单卡根本不用切,切了反而增加通信开销,你这瓶颈大概率在CPU和GPU之间的数据传输或者tokenizer处理上。还有一个点,你并发测试用的什么工具?如果直接curl怼并发,那200 tokens/s可能就是网络延迟和连接复用的锅,建议用vLLM自带的benchmark脚本或者wrk压一遍再说。最后检查下是不是开了--enforce-eager,那个会禁用CUDA graph,显存省了但推理速度会掉不少。
显存吃满但吞吐上不去,大概率是prefill和decode争资源了,试试把max_num_batched_tokens调小点,或者开下chunked prefill。
我之前也踩过这坑,Qwen系列建议把gpu_memory_utilization降到0.85以下,留点余量给调度,别全塞满。
试试把max_num_seqs调小点,prefill并发太高会卡,另外A100跑7B没必要上TP,单卡够用了。
这问题我踩过类似的坑,单卡A100跑7B其实不太需要上TP,先查下是不是max_num_seqs给太小了,并发一上来prefill和decode混在一起就互相卡。另外vLLM有个默认的KV cache预留比例,你gpu_memory_utilization设太高反而可能让显存碎片化,试试调到0.8以下,然后加个--enable-chunked-prefill看看。QPS上不去有时候是输出长度限制或者采样参数的问题,你把max_tokens调低点测测,可能就冒上去了。
这问题我熟,之前搞7B模型也踩过差不多的坑,你这显存吃满但吞吐上不去的现象,大概率不是max_num_seqs的锅,而是vLLM默认把prefill和decode的算力分配搞得太保守了。你可以试试手动调一下——enable_prefix_caching开起来,然后检查下--max-num-batched-tokens这个参数,它直接控制prefill阶段一次能塞多少token,默认可能只有几千,你并发一高prefill排队就把整个pipeline卡住了。另外A100上单卡7B其实没必要上TP,切了反而多一层通信开销,除非你要同时跑长序列。还有个小细节,Qwen2.5的chat模板里有个特殊的im_start/im_end标记,如果你是用transformers加载的旧tokenizer,生成的attention mask可能不对,也会导致vLLM内部做无效计算。最后你提到QPS一上去就卡,我建议直接看下vllm的日志里有没有scheduler相关的警告,比如“Waiting for available token slot”这种,如果有,说明max_num_seqs和max_model_len的乘积已经把显存里的KV cache池挤爆了,把max_model_len降到2048或者调低gpu_memory_utilization到0.7,给KV cache留点余量试试。
我之前也踩过类似的坑,先说个最容易被忽略的:vLLM里gpu_memory_utilization设太高反而会让KV cache预留得死板,A100的80G看着满了,实际可能给KV cache的块分配不够灵活,导致并发一高就排队。你试过把max_num_seqs调小一点吗?比如从默认的256降到64,同时把gpu_memory_utilization留到0.85左右,给足头部空间,有时候反而吞吐能上来。另外Qwen2.5的架构对vLLM的continuous batching支持其实挺成熟的,但7B模型在单卡上跑prefill和decode混布,很容易出现prefill阶段计算密集、显存带宽却跑不满的情况,你可以开一下--enable-prefix-caching,如果你的知识库问答有相似前缀,这个能省不少重复计算。还有,你确认下是不是用了默认的调度策略?vLLM新版有scheduling policy可选,改成priority或balanced试试,默认的fcfs在压力测试下会卡尾延迟。最后说一句,200 tokens/s对于7B单卡并发场景其实不算离谱,网上那种500+的往往是短query+长输出的理想profile,你拿真实问答测一下首token延迟,如果那个低,就不用太纠结总吞吐。要不要试试把max_model_len再砍到2048,同时开--quantization awq?虽然模型精度会掉一点,但显存压力小了之后,调度器能更从容。
单卡A100跑7B这个吞吐确实偏低了,我怀疑你max_num_seqs设太大反而拖累了调度,试试降到64左右,同时把--enable-chunked-prefill打开,prefill和decode混着跑能明显缓解卡顿。另外你确认下vLLM版本,0.6.x和0.7.x对Qwen2.5的默认配置差挺多,建议直接升到最新。TP就别想了,7B单卡完全够,问题大概率出在连续批处理的等待上,可以观察下GPU利用率是不是有规律性的掉零。
这问题我上周刚踩过,vLLM对Qwen2.5的默认配置其实挺保守的,你试试把max_num_seqs降到32,然后给prefill单独开个池子,或者调下--preemption-mode。另外A100上7B根本不用TP,单卡就够了,你显存80G应该是被scheduler预分配了,实际跑的时候看下nvidia-smi里利用率是不是忽高忽低,可能是CPU喂数据跟不上。
我之前遇到过类似情况,后来发现是max_num_seqs和KV cache的tradeoff没找好,调小了反而吞吐上去了。你可以先拿单请求测下首token延迟,如果prefill要好几秒那就不是并发问题,是输入长度和模型并行度的事。另外确认下你的vLLM版本,老版本对Qwen的attention后端支持有bug,升到0.6.3+会有明显改善。
要不你先贴下具体的启动命令和压测时的输入输出长度分布?200 tokens/s这个数字如果是包含prefill+decode的混合吞吐,那其实不算离谱,很多人晒的千级tokens/s都是纯decode的benchmark,实际业务场景差个5倍都正常。
你查下是不是QPS高的时候都堆在prefill了,vLLM默认的调度策略对长prompt的并发挺吃亏的,试试把max_num_batched_tokens调大点,或者干脆开一下chunked prefill。另外A100上7B模型其实没必要上TP,单卡完全够,主要瓶颈可能在你数据集的prompt长度分布上,如果平均输入太长,KV cache占用会远超预期。我之前遇到类似情况,把prefix caching打开之后提升还挺明显的,你可以先抓一下日志看每个请求的TTFT是不是特别高。
试试把max_num_seqs调小点,prefill和decode混在一起容易卡,分开调度会好很多。
看到你说A100上80G显存吃满但tokens/s只有200,我第一反应是这数字确实不太正常,我之前在4090上跑同模型都能到300多。你试过把gpu_memory_utilization降到0.85以下吗?vLLM默认会预留一部分显存给torch的缓存和碎片,你拉满的话反而容易触发显存分配竞争,尤其是KV cache和activation之间会互相挤。另外max_num_seqs别设太大,我实测过这个参数对吞吐影响很微妙,设成256反而比512快,因为prefill阶段batch太大时计算会浪费在padding上。还有个小细节,Qwen2.5的attention有个叫sliding_window的配置,vLLM某些版本没自动识别,你手动在启动参数里加上--sliding-window试试,说不定能省不少KV cache。至于TP,单卡其实没必要切,但你如果只是QPS卡住,我更怀疑是vLLM的调度策略问题,可以试试把--enable-prefix-caching打开,如果知识库里的query有重复前缀,命中率高了速度能翻倍。最后建议看看nvidia-smi的功耗和利用率,如果GPU利用率不到80%,那瓶颈大概率在CPU的数据预处理或者tokenizer上,vLLM的异步调度有时候会被GIL卡住,可以升级到最新版或者换ray后端跑一下。
试下把gpu_memory_utilization降到0.85左右,别让KV cache把显存吃满,另外max_num_seqs别开太大,A100上16到32就够用了。我之前跑7B也遇到过类似情况,后来发现是prefill阶段默认用chunked prefill没开,你查下vllm的启动日志里有没有相关提示,加上--enable-chunked-prefill试试。还有QPS卡住不报错的话,大概率是调度等待,把--max-parallel-load-workers调低点或者干脆单worker看看,Tensor Parallel单卡没必要上。
显存吃满不代表吃对了,vLLM默认预分配挺激进的,试试把gpu_memory_utilization压到0.6以下,再开个--enable-chunked-prefill。
显存吃满但吞吐上不去,大概率是KV cache配额给太狠了,vLLM默认会尽量占满显存,但实际并发没跑起来的话cache就是空转。你可以试试把gpu_memory_utilization降到0.6左右,同时把max_num_seqs调小到64甚至32,先压出单请求的延迟再看并发。另外Qwen2.5对continuous batching的batch size挺敏感,如果prefill和decode混在一起,建议开一下--enable-chunked-prefill,能明显缓解首token卡顿。TP暂时不用切,单卡A100跑7B远没到瓶颈,问题多半在调度参数上。
我之前也踩过类似的坑,vLLM默认的KV cache策略对Qwen2.5这种长上下文模型挺不友好的,你试试把block_size调小点,比如16,然后确认下是不是用了--enable-chunked-prefill,这个对并发提升很关键。另外A100跑7B其实没必要上TP,单卡应该能喂饱,问题大概率出在max_num_seqs设置太大导致prefill和decode互相争抢显存,可以压到64以下再看看。还有个小细节,检查下是不是被CPU offload拖累了,有时候日志不报错但实际在走fallback路径。
你这个问题我之前也踩过坑,A100跑7B其实用不着吃满80G,gpu_memory_utilization别拉太高,留点给CPU和调度器,不然KV cache预分配太多反而拖慢。另外vLLM对Qwen系列建议把--enable-prefix-caching开起来,你知识库问答场景重复前缀多,效果立竿见影。还有QPS上不去可以试试把--max-num-batched-tokens调小点,默认值对7B来说容易在prefill阶段卡住。最后别急着上TP,单卡先看下是不是--block-size设太大,改成16或者32试试。