最近在试着把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大模型到服务器,显存够但推理速度慢得离谱,咋优化?
全部回复
共 161 条4090跑8B这个速度确实不正常,我怀疑大概率是vLLM的GPU利用率没跑满。你可以先看一眼nvidia-smi,如果生成时显存占满但SM利用率只有百分之二三十,那基本就是没吃到FlashAttention或者KVCache分配太小了。我之前把block_size从16调到32,速度直接涨了快一倍,你可以试试。
另外GPTQ和AWQ在4090上的差距其实没那么大,主要还得看是否触发了针对Ada架构的优化内核。我现在用llama.cpp的Q4_K_M配合mmap,200tokens大概5秒内能出,虽然达不到流式那种秒回,但至少比你现在强多了。实在不行就换exllamav2,这玩意对单卡4090的优化比vLLM激进不少。
你这情况我太熟了,4090跑8B按理说该是秒出的节奏,20多秒明显不正常。我怀疑问题不在量化方式,GPTQ和AWQ在4bit下速度差距真没那么大,除非你用的是老版本GPTQ没做exl2优化。重点还是vLLM这边,你试试把block size调大一点,默认16的话改成32或者64,有时候小block在长序列下会疯狂做显存换页,反而拖慢速度。另外prefix caching建议开着,虽然单轮对话看不出效果,但如果你有system prompt或者历史消息,能省不少重复计算。还有,FlashAttention必须开,不开的话attention部分直接变瓶颈,尤其是长上下文。最后,流式输出真不是体验问题,它能让首token秒回,你感受到的延迟会小很多,哪怕总时长不变。要是还不行,就检查下是不是tensor parallel没关,或者vLLM版本太老,更新到最新版有时候能白捡20%性能。
4090跑8B这个速度确实不太正常,我怀疑瓶颈不在量化方式,GPTQ和AWQ在这个体量下差距远没到一倍。你先把vLLM的--gpu-memory-utilization调到0.9看看,默认值有时会留太多显存给KV cache,导致block分配太碎。另外max tokens设2048但batch size=1的时候,prefill阶段算力是够的,decode阶段才是真瓶颈,你可以试试开--enable-prefix-caching,如果输入里有重复的system prompt,能省不少计算。FlashAttention必须开,这玩意儿在长序列下能差三倍以上,你检查下vLLM日志里有没有提示FA未启用。还有个容易忽略的点,检查下是不是被CPU offload了,有时候显存占用看着低,但部分层跑到内存去了,用nvidia-smi看GPU利用率,如果经常掉到50%以下就是这个问题。最后实在不行可以试试llama.cpp的server模式,对单卡4090的优化有时比vLLM更激进,反正你也不追求高并发。
4090跑4bit不至于这么拉,先看看是不是vLLM没开continuous batching,单请求吞吐确实难看。
4bit GPTQ在8B上瓶颈不在显存,试试把max_model_len调小点,或者换AWQ说不定有惊喜。
vLLM对单卡小并发优化一般,试试开流式输出,体感能快一半。
4090跑4bit的8B,20秒200token确实有点离谱了,理论上吞吐应该能到30-50token/s。你先别急着换AWQ,GPTQ本身不是瓶颈,问题大概率出在vLLM的配置上。batch size=1的时候,vLLM很多优化其实不生效,比如continuous batching基本等于没用,你试试把max_num_seqs调大点(比如32),就算实际只来一个请求,内部调度也会更灵活。另外FlashAttention一定要开,你这个速度很可能就是没启用它,导致attention部分变成了内存瓶颈,vLLM里直接设--enable-flash-attention就行,4090是支持的。prefix caching对单轮对话没啥用,但如果你有长system prompt或者多轮历史,开了能省不少重复计算,建议顺手打开。还有个容易被忽略的点,检查一下你的vLLM版本,老版本对Llama 3.1支持不好,最好升到0.6以上。最后,如果还慢,可以试试把max_tokens调小到512,有时候预填充阶段太长也会拖慢首token时间,你那个2048的max tokens在生成时会预留很大KV cache,反而影响内存分配效率。
4090跑8B量化这速度确实不正常,我同样卡跑Q4_K_M的llama3.1 8B,stream模式每秒能出40-50 tokens,你试试把max_tokens调成512,然后开流式输出,首token延迟会比总耗时重要得多。GPTQ和AWQ在速度上差距不大,但AWQ对显存带宽友好一点,不过你这瓶颈明显不在量化方式,vLLM默认配置应该不至于这么慢,检查下是不是没走CUDA graph,或者被CPU offload了?另外FlashAttention必须开,你追问里没说完的可能是这个,不开的话attention计算会吃满所有算力。
4090跑8B这个速度确实不对劲,我怀疑你瓶颈不在量化方式,vLLM默认配置对单卡小并发其实优化很有限。你可以先把enable_chunked_prefill打开试试,再把block_size调成32,这俩对TTFT和吞吐影响挺大的。另外FlashAttention一定要开,不开的话attention部分在长序列上会吃满带宽,4090的算力根本发挥不出来。AWQ跟GPTQ在4bit下速度差距不大,但你要是想省心可以直接换llama.cpp跑,单卡场景下它的调度反而更高效,20秒能压到5秒内。
你这配置跑这个速度确实不对劲,4090单卡8B量化版正常应该能到每秒40-50 token。先别急着换AWQ,GPTQ本身没问题,重点查下vLLM的gpu_memory_utilization是不是设太保守了,还有确认下是不是真加载到了GPU而不是CPU offload。另外建议把max model len调低到1024试试,2048的KV cache会吃掉不少显存带宽,block size默认16就行,prefix caching对单轮对话基本没帮助。顺便说一句,流式输出一定得开,就算不为了体验,它也能让你更直观看到实际每token生成速度,排查起来方便很多。
4090跑4bit的8B才20t/s确实不对劲,我同样的卡用AWQ能到40+t/s。你试试把vLLM的--max-model-len调低到4096,block size改成16,另外确保gpu-memory-utilization别超过0.9,有时候显存留太少反而触发碎片化调度。
FlashAttention得确认编译的时候开了,不然默认走的是SDPA的fallback路径,速度能差一倍。还有个坑是vLLM对GPTQ的kernel优化不如AWQ成熟,尤其老版本,建议直接换AWQ或者用GPTQ-Marlin格式试试。
另外你开流式输出试试,虽然单token延迟没变,但首token出来的时间会快很多,体感上舒服不少。如果还慢,可以看下是不是CPU和GPU之间的数据传输瓶颈,比如pinned memory没开。
4090跑4bit的8B模型,20秒200token确实不太正常,我怀疑瓶颈压根不在显存上。你vLLM参数大概率没调对,batch size=1的时候,vLLM的continuous batching优势完全发挥不出来,而且默认的block size可能太小,导致KV cache频繁换页。建议你先试一下把--block-size改成128,再把--enable-prefix-caching打开,这两个改动通常能带来好几倍的速度提升。
至于量化方式,GPTQ和AWQ在4bit下速度差距其实没你想的那么大,主要影响的是显存占用和精度,真正吃速度的是反量化算子的效率,vLLM对两者支持都挺成熟。但你有没有检查过是不是CPU解码瓶颈?比如tokenizer和采样部分在CPU上跑,尤其是长序列生成时,CPU负载一高就会拖慢整体节奏,你可以看看nvidia-smi里GPU利用率是不是一直没跑满。
另外,流式输出不开确实会让感知速度变慢,但实际生成速度不会变,你把200token拆开看,如果首token延迟很高(比如超过2秒),那就是prefill阶段的问题,可能跟你max tokens设2048有关,预填充长度太长会卡在计算上。建议先开流式,再测一下首token延迟,大概率能找到真正卡在哪。
4090跑8B量化这个速度确实不正常,我怀疑瓶颈根本不在显存带宽上,而是vLLM的调度和CUDA kernel没吃满。你试试把max tokens降到512,同时打开streaming,先把交互卡顿的问题解决掉再看生成速度,很多时候体感慢是等全部生成完才返回导致的。GPTQ和AWQ在4bit下速度差异其实不大,更关键的可能是你没有用FlashAttention,这个在长序列上能快一倍以上,vLLM里要显式指定模型支持才行,不然默认走的是普通attention路径。另外你batch size=1其实绕过了vLLM最大的优势,它本来就是为高并发设计的,单请求吞吐还不如原生transformers加torch.compile,建议你直接测一下transformers的generate速度做个对比,如果一样慢就是数据预处理或者CPU到GPU的传输有瓶颈。还有个坑是nvlink或者PCIE带宽,如果你的4090是插在PCIe 3.0的槽上,模型权重加载和KV cache交换会严重拖慢,可以查一下系统日志确认链路速率。最后,200 tokens 20秒相当于每秒10 token,这差不多是CPU推理的水平了,你检查下是不是量化后的模型被放在了非GPU显存上,比如发生了内存swap,用nvidia-smi看下GPU显存和内存的占用率对比。
4090跑8B量化这个速度确实不对劲,我怀疑瓶颈不在显存而在vLLM的调度上。你batch size=1的时候,vLLM的continuous batching优势完全发挥不出来,反而它的PagedAttention管理开销可能拖慢速度,尤其你max tokens设2048,显存里预留的KV cache空间太大了,实际用不到那么多,白白增加了寻址负担。建议把max tokens降到512试试,再开一下--enable-prefix-caching,虽然单轮对话前缀复用收益不大,但有时候能减少重复计算。
量化那块我觉得GPTQ和AWQ在4bit下速度差距没你想的那么明显,真正影响延迟的是反量化算子在4090上的效率,换AWQ可能提升5%到10%就不错了,不如先看推理框架的日志,确认是不是触发了CPU offload。还有个事,你确认下的vLLM版本是不是支持Llama 3.1的GQA?老版本对grouped query attention支持不好,会多算不少东西,更新到0.6.0以上试试。
流式输出必须开,这不是体验问题,是vLLM在非流式模式下要等整个序列生成完才返回,中间它的调度器没法及时释放已生成token的显存块,相当于变相卡了内存。FlashAttention确实得确认开了,你nvcc --version看下CUDA版本,vLLM编译时没匹配上就得重新pip install,很多“跑得动但慢”的案例都是编译时没带FA2的kernel,结果落到memory-efficient attention的慢路径上。
最后建议你直接对比一下llama.cpp的llama-server,同样4bit量化下它对单请求延迟的优化做得比vLLM极致,我上次用它在4090上跑同模型,生成速度能到80 tokens/s,vLLM如果调不好可能就40上下。
你这大概率不是量化方式的问题,GPTQ 4bit在4090上跑llama 3.1 8B不至于这么慢。我怀疑你vLLM的配置里有个隐藏坑——没开chunked prefill的话,长prompt的prefill阶段会卡住整个batch,而且你max tokens设2048但batch size=1,等于每步都在等显存里的KV cache重新计算,建议先把--enable-chunked-prefill打开试试。
另外FlashAttention这个其实vLLM默认就启用了,但如果你用的是老版本或者手动关了,那确实会慢很多,可以检查下日志里有没有“Using FlashAttention”的字样。至于AWQ和GPTQ,在8B这个规模上推理速度差距很小,主要影响的是显存占用和量化精度,你显存还富余10G,没必要纠结这个。
我更怀疑是你没开流式输出导致的感知延迟——一次性生成200token再返回,就算实际吞吐有50token/s,用户也觉得卡了20秒。把stream=True打开,首token延迟会降到1秒以内,体验完全不一样。另外可以试试把--max-model-len调小到4096,有时候默认的8192会让显存碎片化,影响吞吐。
block size那个参数一般不用动,默认16就行,调大反而可能增加显存浪费。你先跑个benchmark脚本看下实际吞吐,如果稳定在40-50token/s,那纯属交互方式问题,如果个位数,再回来调量化格式不迟。
4090跑4bit 8B这个速度确实不正常,vLLM应该是能跑到每秒大几十token的。建议先确认下是不是没走对GPU,有时候会意外落到CPU推理,另外你说的FlashAttention其实挺关键的,没开的话显存带宽利用率会差很多。量化方面GPTQ和AWQ在这种规模下差距真不大,不用折腾换。还有一个点,batch size=1的时候vLLM的优势发挥不出来,不如直接试试llama.cpp的server模式,对单流低延迟优化得更好。
你这延迟不对劲,先别折腾量化,试下开流式输出,体感能好一半。
4090跑4bit的8B这速度确实不对劲,我怀疑不是量化方式的问题,GPTQ和AWQ在单卡场景下差距没这么大。你试试把max tokens降到512,关掉vLLM的continuous batching,或者直接换llama.cpp试试,我遇到过类似情况是vLLM的显存碎片导致的。另外FlashAttention一定要开,不开的话attention部分会慢一倍不止。如果还不行,看看是不是GPU没跑在性能模式,power limit锁了也会这样。
4090跑4bit 8B这速度确实不对劲,先试试开流式输出,体感能快一半。
4090跑8B量化不至于这么拉,20秒200token肯定不正常。你试试把vLLM的gpu_memory_utilization调到0.9以上,或者干脆换exllama2内核,我感觉你多半是显存没吃满导致碎片化严重。量化方式上AWQ确实比GPTQ快一点,但差异没这么大,不如先排查下是不是max tokens设2048导致预填充阶段算太久,改成流式输出体验会好很多。另外FlashAttention如果没开的话一定要开,vLLM里默认是关的,这玩意儿对长序列加速很明显。
4090跑4bit的8B应该不止这个速度,你这20多秒肯定不正常。vLLM里把--max-model-len调低点试试,还有--gpu-memory-utilization别拉满,留点显存给KV cache,block size默认16就行不用动。另外GPTQ和AWQ在这卡上差距不大,别折腾量化了,先开流式输出,体感能好一大截。