1. 先搞清楚显存到底被谁吃掉了
很多人拿到一张显卡,第一反应是“我这卡有12G显存,跑个7B模型应该绰绰有余吧”,结果一加载直接爆显存,或者跑起来慢得像幻灯片。问题出在哪儿?显存不是只看模型权重那一个数字,它是一整套开销的叠加。我见过太多人只盯着模型文件大小去选卡,最后发现实际占用是文件体积的两三倍。
先把显存消耗拆成四块来看,这样你心里才有本账。
第一块是模型权重本身。这部分最好算,也最直观。模型有多少参数,乘以每个参数占用的字节数,就是权重占用的显存。FP32精度下每个参数4字节,FP16是2字节,INT8是1字节,INT4是0.5字节。一个7B参数的模型,FP16加载大约需要14GB显存,INT4量化后只要3.5GB左右。这就是为什么量化技术对低显存用户这么重要——它直接把权重这块砍到了零头。
第二块是KV Cache。这是最容易被忽略、也最容易在长文本场景下爆炸的部分。Transformer在生成每个token时,需要缓存之前所有token的Key和Value矩阵,避免重复计算。这个缓存的大小和序列长度成正比,和层数、注意力头数、头维度都相关。公式大致是:2 × 层数 × 序列长度 × 隐藏维度 × 精度字节数。注意那个2,因为Key和Value各一份。序列长度翻倍,KV Cache就翻倍,这就是为什么处理长文档时显存会突然飙升。
第三块是激活值和中间计算缓存。前向传播过程中,每一层的输出、注意力分数矩阵、FFN中间结果都需要临时显存。这部分和batch size强相关,batch越大占用越高。推理时batch通常为1,这部分开销相对可控,但训练时它会成为大头。
第四块是框架和运行时的固定开销。PyTorch、CUDA context、cuDNN这些底层库本身就要占几百MB到1GB多不等。不同框架版本、不同驱动版本,这个数字会有波动。有时候你算得好好的刚好够用,结果框架一启动就超了,就是这块在作怪。
把这四块加起来,才是你真正需要的显存总量。我一般会在这个总和上再留20%的余量,因为实际运行中还有碎片化、临时峰值这些不可控因素。下面这张表可以帮你快速估算不同规模模型的大致需求。
| 模型规模 | FP16权重 | INT8权重 | INT4权重 | 建议最低显存(含KV Cache和开销) |
|---|---|---|---|---|
| 1.5B | 3GB | 1.5GB | 0.8GB | 4GB |
| 7B | 14GB | 7GB | 3.5GB | 8GB(INT4)/ 16GB(FP16) |
| 13B | 26GB | 13GB | 6.5GB | 12GB(INT4)/ 28GB(FP16) |
| 34B | 68GB | 34GB | 17GB | 24GB(INT4)/ 72GB(FP16) |
| 70B | 140GB | 70GB | 35GB | 48GB(INT4)/ 多卡FP16 |
这张表是推理场景的粗略参考,训练场景要在此基础上再乘2到4倍,因为还要存梯度、优化器状态和更大的激活值。
注意:表格里的“建议最低显存”已经包含了KV Cache和框架开销的估算,但KV Cache会随序列长度增长,如果你要处理32K甚至更长的上下文,需要额外增加显存预算。
2. 量化精度怎么选才不踩坑
量化是低显存跑大模型的核心手段,但量化不是免费的午餐,精度损失是实实在在的。我试过不少量化方案,踩过的坑包括:INT4量化后模型胡言乱语、INT8量化后推理速度反而变慢、某些量化格式在特定框架上根本不支持。这里把经验整理一下,帮你少走弯路。
2.1 FP16、INT8、INT4的实际差异
FP16是默认的推理精度,几乎不损失效果,显存占用是FP32的一半。如果你的显存够,优先用FP16,省心省力。INT8量化把权重压到1字节,显存直接减半,精度损失通常在1%以内,大多数任务感知不到。INT4再砍一半,但精度损失开始明显,尤其是推理、数学、代码这类需要精确输出的任务,INT4可能会让模型变“笨”。
我实测过一个7B模型在INT4下的表现:日常对话没问题,但让它做多步推理或者写复杂代码,错误率明显上升。所以我的建议是:对话和摘要类任务可以用INT4,推理和代码类任务至少用INT8,有条件就上FP16。
2.2 量化格式的兼容性问题
量化格式不是通用的。GPTQ、AWQ、GGUF、bitsandbytes的NF4,每种格式对应的加载方式和框架支持都不一样。GGUF主要给llama.cpp用,GPTQ和AWQ给vLLM或AutoGPTQ用,bitsandbytes的NF4在HuggingFace Transformers里可以直接加载。你下载模型之前,先确认你的推理框架支持哪种格式,否则下下来加载不了,白费功夫。
还有一个坑:某些量化模型在特定显卡架构上会出问题。比如早期INT4量化在部分老架构上会出现数值溢出,生成乱码。遇到这种情况,换一个量化版本或者换一种量化格式通常能解决。
2.3 量化对推理速度的影响
量化不总是让推理变快。INT8和INT4需要反量化操作,如果硬件不支持对应的低精度计算指令,反量化的开销可能抵消掉显存带宽节省带来的收益。NVIDIA的Tensor Core对FP16和INT8有原生支持,INT4在较新的架构上也有优化。如果你用的是老卡,INT4可能比FP16还慢。实测下来,在支持INT4的卡上,INT4推理速度通常比FP16快1.5到2倍,但在不支持的卡上可能持平甚至更慢。
实操心得:量化之前先查一下你的显卡架构对低精度计算的支持情况。NVIDIA这边,图灵架构开始支持INT8,安培架构开始支持INT4。AMD显卡的量化支持相对滞后,选量化方案时要更谨慎。
3. 不同显存档位的模型选择实战
显存档位决定了你的模型选择范围,但“能跑”和“跑得好”是两回事。我按常见的显存档位来拆解,每个档位给出推荐模型和配置方案。
3.1 4GB到6GB显存:小模型和量化极限
这个档位属于入门级,能跑的东西有限,但也不是完全没得玩。4GB显存下,1.5B到3B参数的模型用INT4量化可以跑起来,7B模型用INT4加上小上下文也能勉强运行,但速度会比较慢,而且稍微长一点的输入就会爆显存。
推荐方案:1.5B到3B的模型用INT4或INT8量化,上下文限制在2K以内。如果一定要跑7B,用GGUF的Q4_K_M量化,配合llama.cpp的CPU+GPU混合推理,把部分层卸载到内存里。这样速度会慢,但至少能跑。
这个档位适合做简单的文本分类、关键词提取、短对话这类任务。不要指望它能做复杂的推理或者长文档处理。
3.2 8GB到12GB显存:7B模型的主场
8GB到12GB是目前最主流的消费级显卡档位,也是7B模型最舒服的运行区间。7B模型用INT4量化大约占3.5GB到4GB权重,加上KV Cache和框架开销,8GB显存可以留出足够的上下文空间。12GB就更宽裕了,可以跑INT8量化的7B,或者INT4量化的13B。
推荐配置:7B模型 + INT4量化 + 4K到8K上下文,这是8GB显存下的甜点配置。12GB显存可以尝试13B模型 + INT4量化,但上下文要控制在4K以内。如果要用FP16跑7B,12GB刚好够,但上下文只能开到2K左右,再长就爆了。
这个档位适合个人开发者做本地推理、聊天机器人、文档问答这类应用。实测下来,8GB显存跑7B INT4,生成速度大约在每秒20到40个token,取决于显卡的具体型号和内存带宽。
3.3 16GB到24GB显存:13B到34B的战场
16GB到24GB是进阶档位,选择范围一下子宽了很多。16GB可以跑13B INT4或者7B FP16,24GB可以跑34B INT4或者13B INT8。这个档位开始能处理比较复杂的任务了,比如多轮对话、中等长度的文档分析、代码生成。
推荐配置:24GB显存下,34B INT4是性价比很高的选择,权重占17GB左右,剩下7GB给KV Cache和开销,上下文可以开到4K到8K。如果任务对精度要求高,13B INT8也是好选择,权重13GB,剩余空间充足。
这个档位的一个常见误区是“显存越大越好,直接上最大的模型”。实际上,模型规模和推理速度、效果之间需要平衡。34B INT4的效果不一定比13B FP16好,尤其是在量化损失敏感的任务上。我建议先明确任务需求,再选模型规模,而不是反过来。
3.4 48GB及以上:大模型和多卡方案
48GB及以上的显存,通常是专业卡或者多卡组合。这个档位可以跑70B INT4,或者34B FP16。如果要多卡,还需要考虑卡间通信的开销和显存池化的方案。
多卡推理有两种主流方式:张量并行和流水线并行。张量并行把每一层的计算切分到多张卡上,通信开销大但显存利用率高;流水线并行把不同层放到不同卡上,通信开销小但会有流水线气泡。对于推理场景,张量并行更常见,因为延迟更低。
推荐配置:两张24GB卡做张量并行,可以跑70B INT4,上下文开到8K。四张24GB卡可以跑70B INT8或者FP16。多卡方案的成本和复杂度都高,适合团队或者对效果有极致要求的场景。
| 显存档位 | 推荐模型规模 | 推荐量化 | 上下文长度 | 适用场景 |
|---|---|---|---|---|
| 4-6GB | 1.5B-3B | INT4/INT8 | 2K | 文本分类、短对话 |
| 8-12GB | 7B-13B | INT4 | 4K-8K | 聊天、文档问答 |
| 16-24GB | 13B-34B | INT4/INT8 | 4K-8K | 代码生成、多轮对话 |
| 48GB+ | 70B | INT4/INT8 | 8K+ | 复杂推理、长文档 |
4. 显存优化的几个实用技巧
显存不够,除了换卡和量化,还有一些工程手段可以榨出更多空间。这些技巧在实际部署中非常有用,尤其是当你差那么一点点显存就能跑起来的时候。
4.1 KV Cache的优化策略
KV Cache是长文本场景下的显存杀手,但它是可以优化的。最直接的方法是限制上下文长度,但这样会丢失信息。更好的方案是用滑动窗口注意力,只保留最近N个token的KV Cache,超出的部分丢弃。这样显存占用就固定了,不会随序列长度无限增长。
另一个方案是KV Cache量化。把KV Cache从FP16压到INT8,显存直接减半,精度损失很小。vLLM和TensorRT-LLM都支持这个特性。实测下来,KV Cache INT8量化对生成质量的影响几乎可以忽略,但显存节省非常明显。
还有PagedAttention这类技术,把KV Cache分页管理,减少碎片化,提高显存利用率。vLLM默认就用了这个方案,效果很好。
4.2 模型卸载与分层加载
当显存实在不够时,可以把部分层卸载到内存里,需要的时候再加载回显存。这就是CPU+GPU混合推理的思路。llama.cpp的--n-gpu-layers参数就是干这个的,你可以指定多少层放在GPU上,剩下的放CPU。
这个方案的代价是速度。GPU和CPU之间的数据传输走PCIe总线,带宽远低于显存带宽,所以卸载的层越多,速度越慢。我的经验是,如果卸载超过一半的层,速度会降到难以接受的程度。所以这个方案适合“能跑就行”的场景,不适合对延迟敏感的应用。
4.3 批处理与并发控制
推理服务通常要处理多个并发请求,batch size越大,吞吐越高,但显存占用也越大。这里需要做一个权衡:显存有限的情况下,限制并发数,用队列处理请求,而不是盲目增大batch。
vLLM的连续批处理是个好方案,它动态调整batch里的请求,把显存利用率拉满,同时不会因为某个长请求阻塞其他请求。如果你自己写推理服务,建议用类似的策略,而不是简单的固定batch。
注意:并发控制不只是显存问题,还涉及计算资源的分配。GPU的计算单元是有限的,并发太高会导致每个请求的延迟都上升。找到吞吐和延迟的平衡点,需要根据实际负载来调。
5. 常见问题与排查实录
实际部署中遇到的问题五花八门,这里整理几个高频问题和排查思路,都是我自己踩过的坑。
5.1 显存明明够却报OOM
这种情况通常是显存碎片化或者框架预留导致的。PyTorch的CUDA内存分配器会缓存已分配的内存,有时候缓存不释放,导致看起来显存不够。可以试试设置PYTORCH_CUDA_ALLOC_CONF环境变量,调整分配策略。另外,torch.cuda.empty_cache()可以手动释放缓存,但不要在推理循环里频繁调用,会影响性能。
还有一种可能是框架的默认预留。比如TensorFlow会默认占用全部显存,需要设置allow_growth或者per_process_gpu_memory_fraction来限制。
5.2 模型加载成功但推理速度极慢
速度慢的原因很多,常见的有:量化格式不被硬件原生支持、KV Cache没有优化、batch size太小导致GPU利用率低、PCIe带宽瓶颈(模型卸载场景)。排查的时候先用nvidia-smi看GPU利用率,如果利用率很低,说明是CPU或者IO瓶颈;如果利用率高但速度还是慢,可能是计算精度或者内存带宽的问题。
还有一个容易忽略的点:显卡的功耗限制。有些卡默认功耗墙设得比较低,跑满负载时会降频。可以用nvidia-smi -pl调整功耗上限,但要注意散热。
5.3 长文本处理时显存突然飙升
这就是KV Cache在作怪。序列长度增加时,KV Cache线性增长,到某个点就爆了。解决方案前面提过:滑动窗口、KV Cache量化、限制上下文长度。另外,有些框架会在处理长文本时一次性分配全部KV Cache,而不是动态增长,这会导致峰值显存远高于实际需求。遇到这种情况,可以试试换用支持PagedAttention的框架。
5.4 多卡方案中的显存不均衡
多卡推理时,如果负载分配不均,会出现一张卡显存快满了,另一张卡还很空的情况。张量并行通常能均衡分配,但流水线并行可能会有不均衡。排查的时候用nvidia-smi逐卡看显存占用,如果差异大,检查并行策略的配置。
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 显存够但OOM | 碎片化/框架预留 | 看nvidia-smi实际占用 | 调整分配策略/限制预留 |
| 推理速度极慢 | 量化不兼容/功耗墙 | 看GPU利用率/频率 | 换量化格式/调功耗 |
| 长文本显存飙升 | KV Cache增长 | 监控序列长度与显存关系 | 滑动窗口/KV量化 |
| 多卡显存不均 | 并行策略问题 | 逐卡看显存占用 | 调整并行配置 |
6. 显卡选购与显存需求的匹配思路
选显卡的时候,显存容量是第一优先级,但也不是唯一指标。内存带宽、计算单元数量、架构特性都会影响实际体验。我按几个典型场景来说说怎么匹配。
6.1 个人开发者:性价比优先
个人开发者预算有限,通常是在消费级显卡里选。8GB到12GB是甜点档,能跑7B到13B的量化模型,覆盖大多数个人应用场景。如果预算允许,16GB会更从容,能跑13B INT4或者7B FP16,上下文空间也更充裕。
选卡的时候,除了显存容量,还要看显存带宽。同样是8GB,带宽高的卡推理速度明显更快。另外,NVIDIA的卡在生态支持上更成熟,量化方案和推理框架的兼容性更好。AMD的卡性价比高,但软件生态还在追赶,选之前要确认你用的框架和量化格式是否支持。
6.2 小团队:平衡效果与成本
小团队通常需要部署服务给多人使用,对吞吐和延迟有要求。24GB档位的卡比较合适,能跑34B INT4或者13B INT8,效果和速度都能兼顾。如果预算允许,可以考虑两张24GB卡做张量并行,跑70B INT4,效果会好很多。
团队场景还要考虑并发。单卡并发能力有限,需要根据预期用户数来估算需要的卡数。一个粗略的估算方法是:每张24GB卡大约能支持5到10个并发请求(7B INT4,4K上下文),具体取决于延迟要求。
6.3 显存之外的考量因素
显存容量之外,还有几个因素会影响实际体验。内存带宽决定了数据搬运的速度,带宽越高,推理越快。计算单元数量影响并行计算能力,对batch size大的场景更重要。架构特性决定了支持哪些低精度计算指令,直接影响量化方案的效率。功耗和散热决定了能否长时间满负载运行,对服务场景很关键。
还有一个容易被忽略的点:驱动和框架的兼容性。新卡刚出的时候,驱动和框架的支持可能不完善,会遇到各种奇怪的问题。等一段时间,生态跟上了再入手,会省心很多。
实操心得:买卡之前,先去推理框架的官方文档或者社区看看,确认你的目标模型和量化格式在目标卡上有没有已知问题。有时候一张卡参数很好看,但实际跑起来各种坑,不如选一张生态成熟的卡。
7. 从显存计算到实际部署的完整流程
把前面的内容串起来,形成一个可操作的流程。当你拿到一个新模型,想在自己的卡上部署时,按这个流程走,能少踩很多坑。
7.1 第一步:算清楚显存需求
先看模型参数量,确定权重的显存占用。然后根据你的任务场景,估算KV Cache的大小。序列长度、层数、隐藏维度这些参数从模型的config文件里都能找到。再加上框架开销的预留(一般留1GB到2GB),得到总需求。
如果总需求超过你的显存,先考虑量化。INT8通常够用,INT4是极限方案。量化之后还不够,就考虑模型卸载或者换更小的模型。
7.2 第二步:选量化格式和推理框架
根据你的显卡架构和推理框架,选一个兼容的量化格式。NVIDIA卡优先考虑GPTQ或AWQ,配合vLLM或TensorRT-LLM。如果要用CPU+GPU混合,选GGUF配合llama.cpp。确认框架支持你的量化格式,再下载模型。
7.3 第三步:配置和调优
加载模型后,先跑一个简单的测试,看显存占用和生成速度。然后根据实际情况调整:上下文长度、batch size、KV Cache策略。如果显存紧张,开启KV Cache量化或者滑动窗口。如果速度慢,检查GPU利用率和功耗状态。
7.4 第四步:压力测试和监控
部署到生产环境之前,做压力测试,看并发情况下的显存和延迟表现。监控工具用nvidia-smi或者更专业的GPU监控方案,实时看显存、利用率、温度、功耗。设置告警阈值,显存接近上限时及时处理。
这个流程看起来简单,但每一步都有细节。我自己的习惯是,每换一个新模型或者新卡,都重新走一遍流程,不凭经验拍脑袋。因为模型架构、量化方案、框架版本都在变,之前的经验不一定适用。
最后分享一个小技巧:如果你不确定某个配置能不能跑,先用小模型或者短上下文试,确认流程通了再放大。这样即使出问题,排查成本也低。另外,社区里有很多人分享过各种卡跑各种模型的实测数据,选型之前搜一搜,能省不少时间。