最近在试着用LLaMA-Factory微调了一个7B模型,然后搭了个简单的Agent做工具调用。由于对性能要求不高,想本地跑,但发现单轮对话显存就飙到18G(我的卡是RTX 3090,24G)。一开多轮对话或者并发,直接OOM。试了量化(4bit)和vLLM,推理速度是快了,但显存占用还是很高。想问下大家,除了换更大显存的卡,有没有其他办法?比如把Agent的上下文切短、用KV cache压缩、或者模型分片部署?感谢各位老哥指点。
部署大模型做Agent时,显存总爆掉,有啥优化技巧吗?
全部回复
共 133 条切短上下文实测最有效,再配合KV cache量化能省不少,4bit加vLLM还能爆就有点怪了。
这问题我熟,之前用7B模型跑Agent也被显存搞到头疼。你试试把工具的schema描述精简一下,别一股脑全塞进system prompt,按需加载能省不少。另外KV cache这块,现在有一些流式重计算或者滑动窗口的trick,对长上下文很有效,3090应该能压到12G以内。还有个小众办法,把不常用的工具定义挪到外部检索里,用的时候再拼进去,实测多轮对话稳很多。
实测把system prompt压到200字内+开vLLM的continuous batching,单卡能扛住4路并发不爆。
agent的history用滑动窗口截断,别全塞进KV cache,比什么量化都管用。
把Agent的system prompt和工具定义精简一下,能省不少显存,KV cache复用也可以试试。
这问题我熟,之前用7B跑Agent也是被显存搞到头大。你试试把系统提示词和工具描述压缩一下,Agent的对话历史别全量塞进prompt,做个滑动窗口只保留最近几轮关键信息,能省不少。另外可以看看SGLang,它自带radix cache,对多轮场景的显存复用效果比vLLM更激进。还有个小众点的招,把工具调用的中间结果用外部存储暂存,别全放在显存里,能明显缓解压力。
试试把工具调用改成流式+强制清理历史KV,能省不少,另外7B用GPTQ比AWQ省显存。
3090 24G跑7B agent确实有点尴尬,我之前用13B开源模型做工具调用也踩过这坑。你试过把agent的system prompt和工具描述塞到KV cache里预填充吗?就是每次请求都带上那部分固定token,这样多轮对话时这部分就不用重新算,实测能省下2-3G。另外你提到上下文切短,这个方向其实挺对的,但别光切长度,得看agent的对话历史里哪些轮次真的对工具调用有影响,我写了个简单的滑动窗口策略,只保留最近3轮加关键中间结果,显存直接降了30%。vLLM那个显存占用高,多半是它默认预分配了很大的KV cache池,你可以调下--kv-cache-dtype和--max-num-seqs,把池子设小点换吞吐量。还有个偏方,用bitsandbytes的8bit优化器重新加载模型,虽然推理时省不了多少,但能让你在微调阶段就摸清显存底线。分片部署其实不太适合单机场景,除非你打算上多卡,否则通信开销比省下的显存还亏。你试过用torch.compile配合cudagraph吗?有时候能把中间激活内存压下去,不过得看模型结构。最后建议你监控下是不是工具调用返回的JSON解析过程在偷偷缓存历史结果,我遇到过类似问题,清理下临时变量能挤出一两个G。
你这情况我太熟了,3090跑7B按理说不该这么紧。建议先查下是不是Agent把历史全塞进prompt了,最好只保留最近两三轮的tool call结果,能省出一大截。另外vLLM的KV cache可以手动调下gpu_memory_utilization,别让它默认吃满,留个1-2G给推理峰值。分片部署倒没必要,单卡场景下收益不大,倒是可以试试把system prompt和工具定义模板固化,避免每轮重复编码。
你这情况我熟,3090跑7B agent确实紧巴巴。我试过把历史对话用摘要压缩成固定长度,只保留最近两轮原始消息,显存能省下不少。另外可以试试用--enable-chunked-prefill把长prompt分成块处理,vLLM里这个开关对显存尖峰挺有效。还有个偏方是把工具调用的system prompt精简到极致,能砍一点是一点,实测能省个几百M。
切短上下文真的立竿见影,我之前限制最近5轮对话直接省了快6G显存。
7B模型单轮18G确实偏高,你确认下是不是KV cache没开PagedAttention,另外4bit量化后权重才4G左右,剩下的应该都是激活和cache吃掉的。可以试试把max_model_len调小,Agent场景一般用不到太长上下文,再配合vLLM的gpu_memory_utilization限制一下。多轮对话的话建议每次只保留最近几轮历史,老的做摘要压缩,比硬扛KV cache省多了。
7B模型单轮就吃18G确实偏高,建议先查一下是不是KV cache没限制住,或者工具调用的prompt塞得太长,很多时候显存不是被权重吃掉的,而是被上下文撑爆的。我自己跑Agent的时候会把系统提示和工具描述压到最短,能省下不少。4bit量化其实对权重有效,但KV cache该占还是占,所以得配合max_model_len和gpu_memory_utilization一起调,vLLM里这两个参数卡一卡效果挺明显。KV cache量化可以试试,FP8或者int8的KV能砍掉一半左右,不过要看你用的推理框架支不支持。模型分片在单卡上意义不大,除非你有第二张卡做tensor parallel,不然还是老老实实控上下文。另外多轮对话记得做历史截断或者摘要,不然轮数一多必炸。
试试限制并发数为1,加上vLLM的gpu_memory_utilization调到0.8,多轮对话截断历史能省不少显存。