最近在试着把Llama 3.1 8B量化版(4bit)部署到我自己的单卡RTX 4090(24G显存)上,显存占用大概14G左右,按理说应该能跑得动。但实际用的时候,生成一个200tokens的回复,要等20多秒,实时交互体验太差了。
我用的框架是vLLM,batch size设成1,max tokens设了2048,没有开流式输出。有没有大佬指点一下:
1. 是不是量化方式不对?我用的GPTQ 4bit,换成AWQ会不会快一点?
2. 或者是不是vLLM参数没调对?比如要开prefix caching或者调大block size?
3. 有人说FlashAttention必须配A100才有效,4090用了白搭?
求真实踩坑经验,不想折腾完发现是硬件天花板。
部署7B大模型到服务器,显存够但推理速度慢得离谱,咋优化?
全部回复
共 11 条我最近也在搞类似配置,4090跑7B量化模型理论上不该这么慢。vLLM里开一下prefix caching和调大block size确实能改善不少,另外流式输出建议打开,首token延迟能降很多。GPTQ和AWQ在推理速度上差别不大,主要还是看vLLM的调度参数有没有设对。
4090跑8B量化模型20秒才出200token确实太慢了,vLLM默认配置对单卡4090不一定最优。建议先开流式输出,不然完整生成完才显示体验肯定差。另外GPTQ 4bit和AWQ差距不大,但你可以试试把block size从默认128调到32,显存占用会降一点,速度可能反而上来。FlashAttention必须开,这玩意儿对长序列推理提速很明显。
4090跑4bit的8B模型,20秒200token确实不正常,这速度连CPU推理都赶上了。我盲猜问题大概率出在vLLM的配置和量化格式的配合上。
先说量化,GPTQ 4bit本身没问题,但vLLM对GPTQ的支持其实没对AWQ优化得那么彻底。AWQ在vLLM里有专门的kernel优化,特别是针对4090这种Ada架构,显存带宽利用率能拉高不少。你可以换个AWQ量化版本试试,同样4bit下推理速度通常能快30%到50%,而且精度损失几乎一样。另外检查下你是不是用了group size 128的GPTQ,如果group size设成32或者64,虽然模型精度略高但推理效率会下降,vLLM对这种细粒度量化支持不太行。
vLLM参数这块,你max tokens设2048但没开流式输出是个大坑。vLLM默认是等整个序列生成完才返回,200token的预填充(prefill)阶段计算量其实很大,尤其在4090这种显存带宽相对有限的卡上。你把stream=True打开,首token延迟能降到1秒以内,后续逐token生成虽然还是慢点,但用户体验会好很多。prefix caching对你的场景可能帮助不大,那是给多轮对话或者固定前缀用的,单次生成开了反而增加调度开销。block size建议从16改成32,减少显存碎片的同时也能提升吞吐。
FlashAttention这个你应该已经默认开了,vLLM现在强制要求。但注意检查下你的vLLM版本,老版本的FlashAttention在4bit量化模型上有bug,会导致推理变慢。建议升级到0.6.0以上,配合最新的FlashAttention-2,推理速度能再提一截。
最后说个很多人忽略的点:4090的PCIe带宽。如果你是插在PCIe 3.0的槽上,模型加载和kv cache的传输瓶颈会非常明显。用nvidia-smi确认下总线带宽,如果是Gen3的话考虑换到Gen4槽,或者用tensor_parallel=1强行锁单卡,减少跨卡通信。
实在不行就上ExLlamaV2吧,专门为4090这种消费级卡优化的,同样4bit量化,首token延迟能压到几百毫秒。vLLM强项是多卡并发和长上下文,单卡单batch场景下ExLlamaV2其实更暴力。你试过这几个方向再回来说下效果。
FlashAttention没开完吧?vLLM默认的block_size是16,你调到32或者64试试,对长序列吞吐提升很明显。另外GPTQ 4bit在4090上确实不如AWQ友好,AWQ对cuda kernel优化更彻底,延迟能降30%左右。还有个事,单batch跑vLLM发挥不出优势,这框架本来就是为高并发设计的,单请求建议换llama.cpp或者ExLlamaV2,流式输出也得开,不然首token延迟全浪费在等完整生成了。
GPTQ和AWQ在4090上差距不大,你这速度瓶颈大概率不是量化方式的问题。vLLM单batch不流式输出时,prefill阶段计算量太大,建议试试把max tokens调低到512,同时开流式输出,首token延迟能压到1-2秒。另外检查下vLLM版本,老版本对4bit支持有bug,升级到0.6.0以上会有改善。
4090跑8B量化版20秒才200token确实离谱,我怀疑不是量化方式的问题,GPTQ和AWQ单token延迟差距没那么大。vLLM那个prefix caching对单轮对话基本没卵用,先看看是不是没开continuous batching或者block size设太小了,默认16可以改32试试。另外FlashAttention必须开,不开的话attention计算能吃掉大半时间。
看到这个延迟我也挺有共鸣的,4090跑4bit 8B按理说应该能压到个位数秒才对,20多秒确实离谱。我猜几个可能的原因:
-
量化方式上,GPTQ和AWQ在速度上差距其实不大,主要影响的是显存和精度。你这种情况我更怀疑是vLLM的调度问题。4090的24G显存虽然够,但vLLM默认的KV cache分配策略有时候会留太多空间给cache,导致实际推理时计算单元没跑满。可以试试手动调低gpu_memory_utilization到0.8左右,强制vLLM多留点算力给decode阶段。
-
你提到没开流式输出,这个很关键。vLLM不开streaming的话,整个生成是等全部tokens算完才一起返回,200tokens的TTFT(首token延迟)可能只有几百毫秒,但后续计算一直在排队。开流式输出后,第一个token出来就能开始显示,后续逐token推送,用户感知上会快很多。虽然总时间不变,但交互体验差距巨大。
-
FlashAttention对长文本场景提速明显,但你这200tokens其实不算长。不过vLLM默认就内置了FlashAttention,如果版本较旧,可以确认下是否正确启用了(启动日志里会有提示)。另外,试试把block_size从默认的16调到32或64,能减少显存碎片和调度次数。
-
最后检查下CPU和内存带宽:vLLM在decode阶段会频繁做KV cache的访存操作,如果CPU内存频率低或者被其他进程抢带宽,也会拖慢。可以先用nvidia-smi看下GPU利用率,如果一直没跑满,那就大概率是IO瓶颈。
先试流式输出和调低gpu_memory_utilization,这两个改动成本最低,效果通常最明显。
4090跑4bit 8B,20秒200token确实不正常,大概率不是量化方式的问题,GPTQ和AWQ在这种规模上延迟差距没那么大。你vLLM的block size默认是16吧,试试调到32或64,能减少显存碎片和调度开销。另外max tokens设2048但每个请求只生200,建议把prefix caching打开,尤其是prompt固定时能复用KV cache。FlashAttention必须开,不开的话长序列注意力计算会拖垮延迟,vLLM里默认就依赖它,确认下你安装的版本是不是编译了FlashAttn支持。
同感,4090跑4bit应该不至于这么慢,20秒生成200token确实离谱。我之前试过GPTQ和AWQ,感觉AWQ在低比特下速度会好一点,你可以先换个量化方式试试。另外vLLM那个block_size默认是16,你试试调到32或者64,再开一下prefix caching,对长文本生成帮助挺大的。FlashAttention记得也要开,不开的话注意力计算会慢不少。
显存14G跑8B量化版其实4090绰绰有余了,你这20多秒肯定不正常。vLLM默认的调度策略对单batch场景不友好,试下把--num-scheduler-steps改成4到8,或者直接上TGI框架,实测单请求延迟能砍半。FlashAttention在4090上必须开,不开的话注意力计算会成瓶颈。
建议开流式输出,vLLM默认调度策略对小batch不友好,调大block size到32试试。