最近在搞一个内部知识库问答的demo,用的Qwen2-7B,用LoRA微调后想部署成API服务给测试组用。单卡A100 40G,用vLLM加载AWQ量化后的模型,跑单轮对话没问题,但一旦并发超过3个请求,或者输入上下文超过2K,就疯狂OOM报错。试过GPTQ和FP16,反而更吃显存。看网上说7B模型4bit量化后只需要8G显存,但我实测光权重就占了11G,KV cache一开再乘个4并发直接爆。想问下是我量化参数没设对(比如group_size、sym这些),还是说7B模型做服务端部署本来就得预留20G以上?另外,有没有办法在vLLM里动态调整KV cache的显存上限?求有实战经验的老哥指点一下,孩子已经被OOM折磨两天了。
部署7B模型微调API总OOM,是量化方案不对还是显存规划有问题?
全部回复
共 50 条8G显存那个说法太理想了,实际跑服务还得算上CUDA context和调度开销。你试试在vLLM里设--kv-cache-dtype=fp8_e5m2,能省不少,再配合--max-num-seqs把并发限制调小点,先跑通再往上加。另外group_size=128和sym=True对内存影响不大,主要是激活值和中间buffer在吃显存。
我上次用7B也踩过这坑,最后把max-model-len压到2048,并发砍到2才稳住。你那个2K上下文爆掉,八成是prefill阶段临时张量没释放干净,可以在vLLM里开--enable-prefix-caching试试,对重复问句的缓存效果挺明显的。
最好还是先盯一下nvidia-smi看是哪个阶段峰值涨上去的,别光盯着权重占用。
说实话你这个问题我太有共鸣了,之前用7B模型做服务端也踩过一模一样的坑。你看到的“4bit只要8G显存”那是纯权重不跑推理的理想值,实测光是激活值、临时buffer和CUDA context就能吃掉好几个G,再加上你开了并发和长上下文,OOM太正常了。我后来排查发现,vLLM默认的KV cache预留比例是90%,虽然看着很激进,但实际分配是按最大序列长度乘并发数来算的,你设个max-num-seqs=3再把max-model-len缩到2048,可能比调量化参数管用得多。group_size和sym对显存影响其实很小,主要影响精度,AWQ你至少把group_size设128,sym开true,不然量化损失会大。另外你试试vLLM的--kv-cache-dtype fp8,A100支持的话能省不少,但得看你的CUDA版本。要是还爆,干脆给每个请求单独一个进程池,用FastAPI挂多worker,虽然慢点但稳定,内部demo够用了。
7B模型AWQ光权重11G其实挺正常的,8G那是纯理论值没算上额外开销和CUDA context。你试试在vLLM启动参数里设--max-num-seqs 2或者调低--gpu-memory-utilization到0.7,能缓解不少。另外KV cache确实得按最大并发预留,动态调整目前只能靠这个百分比参数,没法单请求动态分配。你要是非得上4并发,建议换8B以下或者直接上量化到2bit试试,不过质量会掉。
说实话你这个问题我上周刚踩过,7B量化后8G显存是纯权重+单请求的理想值,实际部署光CUDA context和激活就得吃掉5-6G,4并发直接超20G很正常。建议先试下vLLM的--kv-cache-dtype fp8,能省不少,再把--max-num-seqs调小到2,配合--gpu-memory-utilization 0.85,至少能稳一点。另外group_size设128比64更省显存,sym开不开对vLLM影响不大,但AWQ的packing方式确实比GPTQ稳。你不如直接上量化+分块KV cache,或者干脆换Qwen2-7B-Instruct的AWQ官方权重,社区调好的参数比自己瞎折腾强。
同款配置踩过坑,A100 40G跑7B AWQ本来就不是8G能解决的,网上那个数字是纯权重不跑推理的实验室数据,你实测11G才是真实情况。group_size和sym对显存影响其实不大,主要差别在推理速度,真正吃显存的是激活值和KV cache,4并发加2K上下文这俩加起来轻松破15G。建议先查一下vLLM的gpu_memory_utilization参数,默认0.9太激进了,直接设成0.7给KV cache留点余量,OOM会明显减少。另外可以试试把max_num_seqs调小到2,配合连续批处理,感觉你现在的瓶颈是显存碎片化而不是总容量不够。动态调整KV cache上限vLLM有--kv-cache-dtype和--max-num-batched-tokens参数,但得先确认你用的版本支持,我试过0.4.2版本里改这两个值能缓解,但并发高了还是会抖。最后建议如果测试组不是必须实时响应,干脆部署时限制最大并发数,或者把输入截断到1.5K,比折腾量化实在多了。
说实话你这个情况我踩过一模一样的坑,7B量化后光权重确实不止8G,还得算上激活值和临时buffer,网上那些数字都是纯理论值。我后来发现group_size设128比32省显存但掉点精度,sym开不开倒影响不大,你可以先试group_size=128+AWQ。vLLM里可以设--kv-cache-dtype和--max-num-seqs来限制并发,但更关键的是把--gpu-memory-utilization调到0.85,给前向计算留点余量。另外建议你查下是不是max-model-len设太高了,默认可能吃掉大量KV cache预算,砍到2048试试,反正demo阶段长上下文需求不多。
8G那是纯权重的理论值,实际部署KV cache和并发都得算进去,你这配置至少得留16G给推理。
vLLM里设gpu_memory_utilization到0.85,再调下max_num_seqs,能把并发OOM缓解不少。
你这情况太典型了,7B量化后权重8G是理论值,实际得算上act order和KV cache,vLLM默认会预留显存池,并发一上来直接炸很正常。我试过把gpu_memory_utilization调到0.85,再配合--max-num-seqs限制并发,能缓解不少,但上下文一长还是得砍max-model-len。建议你直接看下vLLM的--kv-cache-dtype,换成fp8能省一小块,但别指望质变,7B服务端部署预留20G真不夸张。
说实话你这情况我太熟了,之前用7B模型做rag服务也踩过一模一样的坑,光看权重占用确实容易误判,但实际跑起来才知道kv cache才是大头,尤其并发一上来,显存直接成指数级消耗。你那个4bit后8G显存的说法,多半是纯推理、单并发、短上下文的理想值,跟生产环境完全是两码事,建议直接按20G预算来规划。量化参数那块,group_size设128、sym开不开其实对显存影响不大,主要影响的是精度,你OOM的根源还是显存分配没做隔离。vLLM里有个gpu_memory_utilization参数,可以手动调低,比如设成0.85,然后配合max_num_seqs和max_model_len一起限制,别让模型把显存全占了,给kv cache留点余地。另外你提到并发3个就爆,我怀疑是max_num_seqs默认值开太大了,vLLM为了吞吐会一次性预留所有序列的kv cache,这比你想的吃显存多了。还有个野路子,如果你测试组只是内部用,可以试试把vLLM的continuous batching关掉,或者干脆用fastapi自己包一层推理逻辑,手动控制并发数,虽然吞吐低点但稳。最后问下,你AWQ的calibration数据集是用的官方默认还是自己根据知识库语料重新做的?这个对量化后的实际占用和显存碎片也有影响,我之前换了校准集后OOM频率明显少了。
8G显存那个说法是纯推理单batch的纸面数据,你还要算上LoRA adapter、激活值和KV cache,7B部署服务端预留20G以上是常态,别被那些测评忽悠了。group_size设128、sym开True能压一点,但治标不治本。vLLM里可以设--kv-cache-dtype和--max-num-seqs,或者干脆用--gpu-memory-utilization限制到0.85,留出余量给并发。另外建议你查一下是不是多轮对话历史没截断,2K上下文对7B来说确实容易爆,加个prompt长度裁剪比调量化更见效。