我平时被问得最多的一句话,就是“我这卡到底能跑多大的模型?”显存计算这件事看着门槛不高,真上手算的时候却很容易翻车,因为大家总是只盯着参数量,忘了 KV Cache、激活值、框架开销这些“隐形住户”。这篇就把显存计算的底账摊开,从权重、量化、训练微调、到逐档显卡能跑什么模型,按我自己的经验一条条讲清楚。适合准备本地部署大模型、想微调或做RAG、以及对资产购机有预算顾虑的开发者参考。
1. 显存计算的基本盘:别只盯着参数量
1.1 为什么模型占用不是参数的简单倍数
刚接触本地模型的人,最容易犯的一个错误是拿“参数量”直接估算显存。比如听说某7B(70亿参数)模型火了,第一反应就是“才70亿个参数,那不得随便跑?”
如果按这种思路走,你会在加载模型的那一瞬间就收到 CUDA Out of Memory。原因很简单:一字节到底能装多少东西,取决于每个参数用多少位来存,而这个数字在不同精度下完全不同。
参数占用的基础计算公式是:
[ \text{权重显存} = \text{参数数量} \times \text{每个参数的字节数} ]
不同数据类型的字节数差异,我用一张表来展示更直观:
| 精度类型 | 每个参数的字节数 | 7B模型权重体积 |
|---|---|---|
| FP32 | 4字节 | 约28GB |
| FP16 / BF16 | 2字节 | 约14GB |
| INT8 | 1字节 | 约7GB |
| INT4 | 0.5字节 | 约3.5GB |
所以同样是7B,FP16的权重就占14GB,INT4量化后只剩3.5GB左右。你看,一个精度选择直接差了4倍。
这里再解释一个很多新手困惑的点:为什么7B是“约70亿”而不是刚好70亿?因为模型结构里还包含词嵌入(embedding)、输出头(head)、LayerNorm等没被稀疏化掉的全量参数,实际数值可能落在67亿到75亿这个范围。也就是说,计算时别抠得太死,你在8GB卡上想跑13B模型,哪怕精度压到INT8,光权重就是13GB,显然不可能。取一个量级估算就够做决策了。
1.2 推理时那些容易被忽略的“隐形”显存
权重只是第一批货物,真正把显存堆爆的往往是另外三样东西:KV Cache、激活值、框架自身开销。
先说KV Cache(键值缓存)。它的作用是把计算过的注意力矩阵的键和值缓存下来,避免每次生成一个token都从头算一遍。Transformer生成时是逐token生成,重的计算反而不断回归前面的注意力结果。KV Cache的显存大小和两个因素直接相关:输入上下文长度和模型层数。层数越多、上下文越长,占用越大。
有个经验比例:对于7B级别模型,显存建议按“权重 + 2GB到4GB”预留,这部分就是给KV Cache和激活值用的。比如13B模型的FP16权重约为26GB,如果只有32GB显存,那不是刚好够,而是大概率会溢出。因为你还要跑生成的中间计算结果,还有PyTorch的缓存池,实际峰值轻松突破30GB。
最后是框架开销。用PyTorch或Transformers库加载一个模型时,显存占用往往比模型文件体积多出20%甚至更多。原因是CUDA在执行时会提前分配一块完整的计算图缓存、内存池(如PyTorch的内存缓存机制,它会预申请一块显存网络),这跟你买卖的实际货物无关,是仓库收管理费。
综合一下,推理场景下显存总量可以按这个公式粗估:
[ \text{推理显存} \approx \text{权重} + \text{KV Cache} + \text{激活值} + \text{预留20%} ]
我把这些“隐形住户”单独列一节,就是因为它们才是让显存估算翻车的最大元凶。光会算权重还远不够。
2. 训练和微调,显存直接翻几倍
2.1 全参训练的三座大山:权重、梯度、优化器
推理只是前菜,你要是想微调,显存计算就是另一个故事了。全参数训练阶段,你不仅要把模型的权重放进去,得再放一份梯度、一份优化器状态。
梯度的大小和权重是完全一致的:模型有多大,梯度就有多大。这意味着权重+梯度至少是2倍关系。
更夸张的是优化器状态。拿最常用的Adam优化器举例,它需要为每个参数保存两个动量变量(一阶动量和二阶动量),也就是两倍的额外参数,每个都存FP32。所以Adam优化器每个参数要额外消耗8字节,而模型的每个参数本身才2字节(FP16)或4字节(FP32且需要维护FP32副本用于数值稳定)。
我们把全参微调7B模型的显存需求合起来算一下:
| 组件 | 单个参数占用 | 7B总占用 |
|---|---|---|
| 权重(FP16) | 2字节 | 14GB |
| 梯度(FP16) | 2字节 | 14GB |
| Adam优化器状态(FP32) | 8字节 | 56GB |
| 合计 | 约12字节 | 约84GB |
也就是说,想全参微调一个7B模型,没有80GB级别以上的显存根本不用想。这就是很多人第一次看到“全参微调”就头皮发麻的原因——它确实不是消费级显卡能碰的。
即便退一步用AdamW配合混合精度训练,一个参数的消耗也基本在16字节左右。因为权重本身还有FP32的主副本、梯度FP16副本、动量FP32副本等。所以训练阶段最偷懒的估算方式就是:
[ \text{训练显存} \approx \text{参数量} \times 14 \sim 18 \text{字节} ]
然后还要在这个基础上加激活值,因为训练需要保存每一层的中间激活来反向传播。7B模型加上一个稍长的上下文,训练峰值轻松破100GB。
2.2 LoRA、Q-LoRA 为什么能救消费级显卡
如果你没有多卡,也没有昂贵的大显存专业卡,是不是就不能微调了?当然不是,这也是 LoRA 和 Q-LoRA 这类方法存在的意义。
LoRA 的思路很简单:我不动基座模型的全量权重,只在每个线性层旁边挂一个低秩的旁路(论文里俗称适配器),训练的时候只更新这个旁路。基座模型的权重全程被冻结。这样梯度只有权重和优化器状态都缩小到极小的规模。
比如7B模型,如果LoRA的秩设置为32,插入的旁路参数量大约只有几千万到一亿级别,远低于7B。训练时显存主要花在基座模型的权重、冻结层的前向计算和极少量的优化器状态上。
更极端一点,Q-LoRA 会在加载时先对基座模型做4bit量化,把7B模型的权重压到3.5GB左右,然后再插入LoRA适配器。这样你在显存只有8到12GB的卡上就能微调7B模型,虽然不是全部更新,但对适配特定任务已经足够。
我自己实际测试过类似方案,在约12GB显存的消费级显卡上微调一个7B基座的对话模型,训练序列长度控制在1024以内,Batch Size设为1,加上梯度累积到16步,基本能稳定跑完一个Epoch。显存占用的分布大致是:基座量化权重3.5GB、LoRA可训练参数0.2GB、激活值和CUDA开销3到4GB,峰值在8GB上下。
所以不管是跑推理还是微调,选择哪种方案取决于你的显存预算。如果只是想把模型跑起来,优先考虑量化推理;如果想做领域适配,LoRA或Q-LoRA是更实际的路子。
3. 量化与模型选择的“折算表”
3.1 精度怎么换算:FP16、INT8、INT4、GGUF
上一节我已经给了一个精度对照表,这节把它放进实际模型里,你就能一瞬间看清“我的卡到底行不行”。
先普及一下量化模型常见的几种格式:HuggingFace开源社区里常见的有GPTQ、AWQ、GGUF。它们的核心思路一致,都是在尽量少损失效果的前提下,把权重压到更低的bit位。GGUF背后是社区在本地运行大模型时的一个主流选择,硬件友好度非常高,CPU和GPU都能跑,而且提供了多种量化等级。
GGUF 的命名里通常会有 Q4_K_M、Q5_K_M、Q8_0 这种后缀。以我的经验,本地消费级显卡上最实用的是一档叫 Q4_K_M 的量化,它约为4.25bit/参数。把几个代表性模型的Q4_K_M量化后体积列出来:
| 模型 | 原始FP16体积 | Q4_K_M体积 | 大致GPU需求 |
|---|---|---|---|
| 7B | 14GB | 4.8GB左右 | 6GB以上可跑 |
| 13B | 26GB | 8.6GB左右 | 10GB以上稳妥 |
| 34B | 68GB | 20GB左右 | 22GB以上更好 |
| 70B | 138GB | 42GB左右 | 48GB以上适配 |
注意,GPU需求这里我是在“整数占+实际运行开销”的角度给的,已经预留了KV Cache和框架运行余量。不能简单拿体积等于显存,否则又会在加载后瞬间溢出。
选型时我的习惯是:看着模型体积先乘1.3到1.4倍,比较接近真实峰值占用。比如42GB的70B Q4量化文件,一张显存显示为48GB的卡实际上跑起来挺吃力的,通常要留到64GB级别才舒服。
3.2 从8GB到24GB,各显存档位能跑什么
这里整理了我在不同显存档位上的实际经验和推荐方案,按由小到大的顺序来讲:
| 显存档位 | 推荐模型规模 | 说明 |
|---|---|---|
| 8GB | 7B的INT4量化版 / 3BFP16 | 跑Q4量化的7B是极限,建议上下文不超过4096 |
| 12GB | 7B的FP16或INT8 / 13B的INT4 | 这个档位用13B量化模型体验明显更好 |
| 16GB | 13B FP16 / 34B INT4 | 适合给中小规模服务提供推理能力 |
| 24GB | 13B FP16跑满 / 34B INT4放宽上下文 | 大多数开源模型的首选档位 |
| 48GB及以上 | 70B INT4 | 本地大模型体验的甜美点 |
8GB是一个很尴尬的起点。跑7B量化模型,可用显存实际上只有7GB左右,因为显卡驱动、桌面环境、画面渲染都要占走一部分。我见过很多人在8GB卡上加载一个Q4的7B模型后,明明模型就5GB左右,结果显存直接顶到99%,然后生成速度急剧下降。原因就是KV Cache不够长,显存碎片严重。
到了16GB就是比较舒服的中端档位了,你可以在FP16精度下跑7B,或者在4bit下跑一个34B,输出的质量会有明显提升。24GB档位是我个人建议的普通发烧友甜品点。它突出的优势是能装下带量化的大多数开源模型,且每个模型都留出了足够的KV Cache空间。
如果你预算有限,我的建议是优先保容量、再谈速度。宁可上一张24GB但核心频率普通的卡,也别强上16GB的顶配。模型本身“跑不跑得动”是首要问题,生成快慢跟显存带宽更相关。
4. 实操:三步摸清你的显卡上限
4.1 第一步:用命令拿到显存和带宽的真实数据
估算再说得天花乱坠,不如先看一眼实际设备。在Linux服务器或本机上,最简单的方式是通过显卡驱动自带的监控命令来查看。打开终端执行以下命令:
nvidia-smi你会看到每个GPU卡的显存总量(Memory-Usage)和当前占用,以及利用率。但这里有个小细节:如果GPU上没有跑任何程序,Memory-Usage显示的是那个“已用”数值,可能有几百MB到1GB,那是系统预留和驱动缓冲,并不会全释放。实际规划容量时,要把这个数值当作“已占用”的一部分算进去。
如果你想在两个显卡的同名工具下比较哪个更适合跑模型,一条命令不够,还得看带宽。用下面这两行Python代码获取:
import torch props = torch.cuda.get_device_properties(0) print(f"显存总量: {props.total_memory / 1024**3:.2f} GB") print(f"内存频率与显存带宽: 可查专用工具,这里以运行速度为准")显存带宽会直接决定生成速度。同一规格的两个模型,如果一张卡的带宽高30%,生成速度可能快一倍。对于购买前的决策,可以去查对应规格表的带宽数值。也可以参考一个粗公式:消费级显卡的带宽大致等于 GPU核心频率 × 显存位宽 × 显存代数折算系数。不展开,因为你如果真要对比,直接拿实测速度最快。
4.2 第二步:用模型文件大小做快速预估
这一步是很重要的实战技巧:你先去模型仓库看中意的模型,把它的“文件体积”记为第一参考。比如选GGUF量化模型时,官方压缩包或模型卡页面都会写体积。假设你找到一个7B Q4_K_M的文件,体积4.85GB。
接下来做两步心算:
- 把4.85GB乘以1.3,约6.3GB,这对应实际运行时的基础占用;
- 再考虑设定上下文长度。假设你想让模型记住4096个上下文,可以额外预留2GB的KV Cache。
加起来约8.3GB,所以你的卡至少有12GB显存才比较放心,8GB会非常勉强。我就是按照这个逻辑快速筛选掉了90%不适合自己显卡的模型,完全不需要真的去下载。
如果你用的是HuggingFace上默认的FP16模型,就拿模型规模直接乘以2倍算权重。例如13B就是26GB,那至少需要32GB显存才算安全。少一丝都不建议,因为我踩过太多次“下载半天、加载0.5秒就崩”的坑了。
4.3 第三步:实际加载与跑通试验
理论算得再准,最终还是要跑一次看真实峰值。在本地用Transformers库加载模型时,我一般会先设置一个最低参数的加载环境:
from transformers import AutoModelForCausalLM, AutoTokenizer import torch model_id = "you/model-path" tokenizer = AutoTokenizer.from_pretrained(model_id) model = AutoModelForCausalLM.from_pretrained( model_id, torch_dtype=torch.float16, device_map="auto", load_in_4bit=True, # 消费级显存建议打开量化参数 ) prompt = "测试一下这个模型能不能正常生成" inputs = tokenizer(prompt, return_tensors="pt").to("cuda") outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0], skip_special_tokens=True))这段代码跑起来后,再开另一个终端执行nvidia-smi,观察峰值显存。什么时候看最准?在生成过程中反复执行几次nvidia-smi -l 1来循环采样,就能看到临时波动巅峰。如果提示CUDA Out of Memory,就把上下文调短、Batch Size调小,或者把量化档位从Q6降到Q4。
我自己测试时还会额外加一个“把max_new_tokens调大”的步骤,因为有些早期的OOM是发生在生成长文本后段而不是初始化阶段。如果你能在256个token生成后稳定不掉显存,那说明余量充足。如果只测了模型加载,就轻易下结论“能跑”,很容易在生成长文的时候翻车。
5. 常见坑与排查实录
5.1 OOM 不全是因为显存不够
CUDA Out of Memory可能是业界最常见的报错,但它的触发原因比你想象的复杂得多。有时候你的显存明明还有剩余,却依然报OOM。原因是显存碎片化:模型加载时申请了一大块连续内存,如果这块区域被之前的小张量撕碎了,新的大张量就申请不下来。
我试过的一个典型场景是:先加载了一个小模型,又释放掉,再加载大模型,中途因为显存碎片导致失败。解决办法很简单:让程序从头跑一次,打满整个显存;或者在上层设置环境变量让进程完全退出后重新启动。
另一个常见坑是,显存没问题但系统内存不够。PyTorch加载模型时,如果设备是GPU,会先在CPU内存中创建模型副本再搬过去。一个7B模型在CPU端可能是14GB,如果你的系统内存只有16GB,其他程序再占一点,就可能在加载阶段就崩溃。排查时别只盯着GPU,CPU内存也要留足。
5.2 显存看似够,速度却慢得离谱:问题在带宽
你可能遇到过这种情况:模型只有6GB,显卡却有16GB,按说足够轻松,但生成速度只有每秒几个token。这通常是显存带宽瓶颈,而不是显存容量问题。
大模型推理本质上是一个“带宽密集型”任务。生成每个token都要把所有权重从显存读到计算核心,权重越大,读的时间就越长。一个7B Q4模型单次前向推理要读大约4GB的权重,如果你的显存带宽只有200GB/s左右,光把权重读完就需要20毫秒,加上计算和调度开销,速度自然上不去。
所以模型选型不只是“能放进去”的问题,还要考虑“能读多快”。如果你在意生成速度,同样的显存容量下,优先选择带宽更高的显卡。这也是为什么某些16GB卡实际跑模型时反而比8GB卡慢——因为虽然容量大了,但带宽可能没跟上。
5.3 几个极容易踩的误区
第一,认为“量化模型质量一定差”。实际上Q4_K_M级别对于大部分对话和文本生成场景,质量损失在可感知范围之外,我的经验是70B的Q4_K_M效果普遍好过13B的FP16。核心原则是:模型参数量越大,即使压缩,潜力上限也更高。
第二,以为“24GB显存就能直接跑70B模型”。24GB意味着约48GB以上的实际需求被腰斩了,只能跑一个Q2或Q3极低量化版本。效果大概率不如一个34B Q4模型。合理的选择是34B量化,或减少上下文长度勉强跑低量化70B。
第三,忽视上下文长度对显存的影响。模型加载时的体积只是起点,实际运行中如果设置了8192甚至更高的上下文,多消耗的KV Cache可能是几个GB量级。很多人在跑长文档、做RAG时发现显存上涨,主要就是上下文长度的贡献。
| 报错或现象 | 常见原因 | 解决思路 |
|---|---|---|
| CUDA Out of Memory | 模型过大或KV Cache太长 | 降低量化档位、缩短上下文、减小batch |
| 加载时CPU内存爆掉 | 系统内存不足 | 加内存、使用流式加载或量化格式 |
| 显存占用高但生成极慢 | 带宽不足或模型过大 | 换高带宽显卡、用更低bit量化 |
| 生成的文字逻辑开始混乱 | 量化等级压得太低 | 尝试Q5或Q6、或换更大模型 |
| 加载成功但一生成就OOM | 动态申请过度分配失败 | 关闭可能的内存池机制、重启进程 |
最后再分享一个我自己琢磨出来的估算习惯:无论什么模型,我都习惯先在显存总数里扣掉1.5到2GB“房租”(驱动、界面、短暂缓存),再用剩下的空间去匹配模型体积和上下文差价。这样算出来的结论往往比直接拿模型体积对比显存总量更接近真实可运行状态。实践过很多次,这个预留值误差不大。希望这套显存计算的思路也能帮你在换卡和选模型的时候少走一点弯路。