最近在折腾本地部署,用vLLM跑Qwen2.5-7B,服务器是两张RTX 4090(24G*2)。按说7B模型用FP16推理大概14G显存,加上KV Cache也够吧?但一启动就报CUDA OOM,试了调低max_num_seqs、换GQA,甚至只加载单卡,还是崩。后来看nvidia-smi发现显存被其他进程占了一部分,但就算全清空也只撑了半分钟。是不是我量化方式不对?或者vLLM版本太新有bug?求指点,卡在第一步好难受。
部署7B大模型到服务器,显存明明够却报OOM,有老哥遇到过吗?
全部回复
共 178 条先查下是不是vLLM默认给每张卡都预分配了显存,你设了tensor_parallel_size=2的话,它会把KV cache按两卡平分,但实际加载模型时每张卡的峰值可能超了。我之前用8B也遇到类似情况,最后是加了--gpu-memory-utilization 0.85才稳住。另外你确认下CUDA_VISIBLE_DEVICES有没有生效,有时候多卡环境下vLLM会忽略这个变量,直接去抓所有GPU,导致单卡显存被重复占用。还有个坑是Qwen2.5的attention实现可能比老版本吃更多显存,你试试换回0.4.x版本,或者直接改用AWQ量化,4bit下7B只要6G左右,连KV cache都算上也才9G,肯定不OOM。
你这情况我上次也遇到过,倒不是显存总量不够,是vLLM的显存预留机制在搞事,默认会按比例缓存KV加上CUDA context,两张卡之间通信还要额外吃显存。建议把gpu_memory_utilization设成0.85以下试试,另外确认下是不是张量并行把模型切得太碎了。还有啊,4090的驱动和vLLM版本搭配很敏感,换0.6.3或者0.5.5这种稳定版能省心不少。
显存看着够但实际跑起来崩,多半是碎片化或者预分配没算对。你单卡跑的时候有没有设max_model_len?7B模型如果默认开8K上下文,KV Cache峰值能吃掉4-5G,再叠加CUDA graph和中间激活,24G其实很紧。我建议先用unified memory模式跑下CPU offload看看能不能过,如果还OOM那就是vLLM和PyTorch不兼容的问题,换个镜像重装环境试试。
我之前用A100跑7B也遇到过,最后发现是环境变量NCCL_P2P_DISABLE没设导致多卡通信时申请额外显存。你试试只开单卡,然后强制设置PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128,这能缓解碎片化。另外vLLM新版对Q
先查下是不是P2P通信或者CPU内存映射把显存吃满了,之前我也遇到过,关掉跨卡通信就好了。
vLLM新版本对多卡显存预留策略改了,试试设--gpu-memory-utilization 0.7,大概率能救回来。
显存碎片化+多卡张量并行反而吃更高,先单卡试下吧,vLLM新版对Qwen支持确实有坑。
试试看开--gpu-memory-utilization 0.9,再不行就换0.6.3老版本,我上次就是这毛病。
我之前也遇到过类似情况,后来发现是vLLM默认会给每个序列预留很大比例的KV cache,加上显存碎片化,实际可用比预期少很多。你可以试试把gpu_memory_utilization调到0.8以下,或者换用sglang这类的推理框架,对显存控制更细。另外检查下CUDA版本和vLLM的兼容性,太新的版本有时确实有显存管理bug,回退到0.6.x稳定版可能就正常了。
我之前也踩过一模一样的坑,后来发现问题根本不在模型本身,而是vLLM那个“预分配”机制在作怪。它默认会按最大可能的KV Cache去预留显存,哪怕你设了max_num_seqs,它也会按最坏情况来算,两张卡之间还要做通信缓冲,实际占用比你估算的高很多。你可以试试在启动参数里加--gpu-memory-utilization 0.6,强制它只用60%的显存,给碎片和驱动留点余地,我这么调完就稳了。另外你说的“全清空也只撑半分钟”,大概率是跑了一会儿之后KV Cache涨上去了,或者有别的进程在偷偷吃显存,比如Jupyter或者桌面环境,你可以用nvidia-smi --query-compute-apps=used_memory去实时盯一下是谁在抢。还有个小细节,vLLM最近几个版本确实有内存碎片问题,特别是0.6.x,建议直接降到0.5.5或者试试最新0.7.2,我升完就再没OOM过。量化方式的话,FP16没问题,别急着上AWQ或者GPTQ,7B这个规模FP16最省心,先把显存预留调好再说。如果还是崩,可以试试在代码里设置VLLM_ALLOW_LONG_MAX_MODEL_LEN=true,有时候是上下文长度算错了把显存撑爆的。总之别怀疑卡不行,4090跑7B绰绰有余,就是软件层要吃一堆隐性开销。
显存碎片化了解一下,4090的24G实际可用没那么多,建议把max-model-len调小点试试。
八成是vLLM的显存预留策略问题,换0.6.3版本或者直接上AWQ量化,能省一大截。
遇到过,而且就是Qwen2.5-7B配vLLM,折腾了整整一晚上。你查过CUDA_VISIBLE_DEVICES没?有时候vLLM默认会尝试把张量并行开起来,两张卡各分一半权重,但实际显存分配是按峰值算的,不是简单把模型大小加KV Cache就行。我后来用CUDA_VISIBLE_DEVICES=0强制单卡,再把gpu_memory_utilization设到0.85,才勉强跑起来。另外你确认下是不是用的最新版vLLM,0.6.x之后对Qwen2.5的attention后端改过,有些版本确实会莫名多占几个G,回退到0.4.2反而稳。还有个坑是PagedAttention的block大小,默认16,你试下调成8,能省不少碎片。至于量化,FP16没问题,别用GPTQ,那个和vLLM的兼容性时好时坏。最后建议你启动前先跑一下nvidia-smi看下有没有残留的python进程,有时候显存看着是0,但实际被CUDA context占着,用fuser -v /dev/nvidia*清一遍再试。半分钟才崩的话,也可能是你max_model_len设太大了,我设4096都够用,你如果设了8192以上,KV Cache峰值会翻倍。
4090双卡跑7B按理说真不该OOM,不过你查过vLLM的版本没?之前我遇到类似情况是2.3.x的bug,降到2.2.4就稳了。另外确认下是不是pytorch和CUDA版本不匹配,有时候nvcc显示12.1但torch实际用的11.8,显存分配会出鬼。量化的话建议先别折腾AWQ,直接FP16试跑个默认参数,排除配置问题。实在不行用transformers原生加载跑一步看看,能跑就是vLLM的锅。
我之前也踩过类似的坑,不过我是单卡3090跑7B,一开始也是看显存刚好够就冲了,结果直接OOM到怀疑人生。后来发现vLLM默认会给每个序列预留不少KV cache,而且它跟HuggingFace的缓存机制还不一样,你调max_num_seqs其实治标不治本,得看看是不是gpu_memory_utilization这个参数没设,默认只留一点点余量,实际能用的显存比你算的少很多。还有你说的量化,FP16其实不是重点,7B模型权重加激活就差不多15G了,你再算上CUDA context和碎片,两张卡如果没开tensor parallel反而容易因为显存分配不均炸。我建议你先把vLLM降到0.6.x版本试试,新版确实有些显存管理改动,另外用--gpu-memory-utilization 0.9强制占用,再把--max-model-len调小,比如2048,这样能省出不少空间。如果还不行,你就用transformers原生的generate跑一次,排除vLLM的嫌疑,反正我最后是换了flash-attention加手动分片才稳住的,你可以先试试把HuggingFace缓存目录清一下,有时候旧格式的模型文件会占额外显存。
这问题我上个月刚踩过,vLLM版本太新确实有坑,0.6.3之前对Qwen2.5的GQA支持有问题,会莫名多分配好几G显存,你直接锁到0.6.2试试。另外别光看模型权重14G,vLLM默认会给每个序列预留大量KV cache,max_num_seqs调到4还不够的话,把gpu_memory_utilization直接设成0.7,强制它别贪心。还有个隐藏杀手是CUDA graph,这东西吃显存很猛,实在不行关了跑,性能损失但至少能起来。你单卡都崩的话,大概率是显存碎片化,重启进程前先清一波,或者用torch.cuda.empty_cache()看下实际可用量。最后问下,你加载时是不是用了--dtype float16?其实可以试下auto,让它自己选bf16,4090对bf16支持更好,显存占用也会小一截。我这边现在跑7B挺稳的,峰值也就18G左右,你按这个思路排查应该能解决。
vLLM这玩意儿吃显存比想象中狠多了,它默认会给每个序列预留不少buffer,而且PagedAttention的block管理也有额外开销。我之前跑13B模型,两张卡看起来空闲,但一开vLLM直接爆,后来发现是它的默认gpu_memory_utilization参数设太高,把显存全吃满了。你可以试试把这个参数调到0.8左右,或者手动设一下max_model_len,别让KV Cache无限膨胀。还有你说的量化方式,其实FP16本身没问题,但如果用AWQ或GPTQ,得确认下是不是模型文件本身有问题,有时候量化后的权重反而更占显存。另外,vLLM版本确实坑多,我之前用0.4.x跑Qwen系列老报奇怪的错,降到0.3.x就稳了。建议你先用transformers原生加载跑一下,排除vLLM的锅,再一步步排查显存占用。反正多试几个组合,别死磕一个版本。
我之前也踩过类似的坑,折腾了两天才发现是vLLM那个版本的默认行为改了,它会预分配一部分显存给后续的调度和paged attention,nvidia-smi看着没满,但CUDA context已经吃掉了不少。你试过把gpu_memory_utilization参数手动调低到0.85或者0.9吗?有时候默认值在双卡环境下会按单卡总显存算,导致每张卡都试图预留,结果反而互相挤爆。另外你说清空显存后只撑半分钟,这有点像KV Cache的碎片化问题,不是光调max_num_seqs能解决的,试试把block_size调小一点,比如16或者8,对长序列的碎片会友好很多。至于量化,FP16本身没问题,但如果你用的是AWQ或者GPTQ的权重,得确认vLLM的量化kernel和你的CUDA版本匹配,不匹配的时候会偷偷回退到未优化的路径,显存消耗直接翻倍。还有个小细节,检查一下是不是有个叫triton的缓存目录残留了旧环境变量,我之前就是被这玩意儿坑过,导致每次启动都重复初始化额外的buffer。要是还不行,干脆降到0.6.x的稳定版试试,新版有时候为了支持新模型会牺牲一些兼容性,尤其是对双卡通信的优化不一定比老版本稳。
试试把gpu_memory_utilization调到0.9,vLLM默认预留太多,我之前也卡这。
4090的24G跑7B按理说真够,但vLLM对KV Cache的预分配很激进,试试设--gpu-memory-utilization 0.7,或者干脆换llama.cpp。
遇到过类似的坑,大概率不是显存总量的问题,而是碎片化或者预留空间。vLLM默认会吃满所有可见显存,你先看下Pytorch的缓存分配器是不是把显存都占了,设个CUDA_VISIBLE_DEVICES=0,然后加--gpu-memory-utilization 0.85试试。另外4090的驱动和CUDA版本不匹配也会触发莫名OOM,我用12.2配vLLM 0.6.3就稳。你那个跑半分钟才崩,也可能是KV Cache在高并发下瞬时涨太快,把max_num_batched_tokens调小到256看看。
显存碎片和CUDA context占的坑容易被忽略,试试加个--gpu-memory-utilization 0.9?我之前这么解决的。
max_num_seqs调太低反而会触发碎片问题,你直接设成1跑一次看还崩不崩,能跑就是显存分配策略的锅。
看到你说两张4090跑7B还OOM,我第一反应就是vLLM的显存预分配策略在搞鬼。这玩意儿默认会按最大并发数把KV cache算得特别激进,哪怕你调低max_num_seqs,它也可能把剩余显存全吃满,建议直接手动设一下gpu_memory_utilization,比如0.6,让它留出余量。另外你提到的量化方式,其实FP16本来就不该爆,但如果你用的是AWQ或GPTQ的量化版,有时候反而会因为反量化算子临时占用额外显存,不如先试原版BF16加载。还有个小坑是vLLM新版本对某些4090的驱动和CUDA版本兼容性确实有雷,我之前遇到类似问题,回退到0.6.x版本就稳了,你可以看看日志里有没有显存碎片警告。如果单卡也崩,那就不是跨卡通信的问题了,建议用torch.cuda.empty_cache()清一下缓存,然后逐行打印显存占用,看看是不是embedding层或者attention的中间变量在偷偷膨胀。实在不行就换transformers原生加载跑一遍,排除vLLM的干扰,至少能确认模型本身没问题。最后补一句,别信nvidia-smi显示的“已用”,那是包含其他进程的,用nvidia-smi --query-gpu=memory.used,memory.free --format=csv看单卡实际可用更靠谱。
vLLM的预分配机制挺坑的,7B模型虽然显存占用看着够,但加上paged attention和CUDA context本身那几百MB,两张卡之间通信还得吃显存,实际可用空间比你想的少得多。建议先试试禁用张量并行,单卡只跑batch size=1,然后看下vLLM日志里实际预留的KV cache显存是多少,说不定是默认配置把剩余空间全吃了。我之前用0.6.3版本也遇到过类似情况,换回0.5.5就稳了,你可以降个版本试试,别急着怀疑量化。
vLLM新版本确实偶尔有显存碎片化的问题,我之前用0.6.3也遇到过类似情况,换回0.5.5就稳了。另外你检查过HuggingFace的config.json里有没有设置rope_scaling或者sliding_window吗,这些参数会把KV Cache撑大好几倍。还有个小坑,nvidia-smi显示的占用和CUDA实际可用显存不是一回事,建议先用torch.cuda.mem_get_info看看真实空闲。7B模型FP16其实13G左右,但max_model_len如果设太高,预分配显存直接爆炸,试试把长度砍到2048再跑。