ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

96GB 显存能跑多大模型?三种 96GB 的带宽差 7 倍,附容量计算脚本

96GB 显存能跑多大模型?三种 96GB 的带宽差 7 倍,附容量计算脚本

「96GB 显存」至少对应三种不同硬件:96GB GDDR7 独显、96GB LPDDR4X 国产推理卡、从系统内存划出的 96GB 统一内存。容量一样,带宽相差约 7 倍。本文先拆清三种 96GB,再给权重 + KV Cache 的容量计算脚本、逐 token 解码的带宽上限估算,以及一套可复现的压测方法。

图注:96GB 显存的容量与带宽分层(来源:商红科技行业论坛原文配图;非实测)

先说结论

96GB 能不能跑某个模型,要分三笔账:

  1. 权重账:参数量 × 每参数字节;
  2. KV Cache 账:随上下文长度和并发线性增长;
  3. 带宽账:决定装进去之后跑多快,不报错但会慢。

只报「96GB 能跑 70B」是误导,因为 70B 在 32K 上下文和 128K 上下文下的 KV 占用差 4 倍。

一、先确认你说的是哪一种 96GB

「96GB」出现在哪实际是什么典型带宽能否当独立显存
RTX PRO 6000 Blackwell 96GB96GB GDDR7 独立显存1792 GB/s能
Atlas 300I Duo 96G96GB LPDDR4X 独立显存408 GB/s能
Ryzen AI Max+ 395 一类统一内存从系统内存划出,最大 96GB256 GB/s能,但与内存共享总线
96GB 内存条系统内存,不是显存与显卡无关不能

前三类容量相同,带宽比约为 1792 : 408 : 256 ≈ 7 : 1.6 : 1。容量决定「装不装得下」,带宽决定「每天用起来什么感觉」。

二、容量计算:权重 + KV Cache

权重部分:

权重 GiB = 参数量 × 每参数字节 / 2^30

FP16/BF16 约 2 字节/参数,FP8/INT8 约 1 字节,INT4 约 0.5 字节。

KV Cache 部分:

KV 每 token 字节 = 2 × 层数 × KV 头数 × 头维度 × 每元素字节

KV GiB = KV 每 token 字节 × 序列长度 × batch / 2^30

注意是KV 头数,不是注意力头数。GQA 模型里 KV 头数通常远小于注意力头数,KV Cache 会小一个量级。

可直接运行的容量计算脚本

#!/usr/bin/env python3

"""96GB 级显存容量规划:权重 + KV Cache,输出剩余余量。"""

GB = 1024 ** 3

def kv_per_token_bytes(layers: int, kv_heads: int, head_dim: int,

elem_bytes: int = 2) -> int:

return 2 * layers * kv_heads * head_dim * elem_bytes

def plan(params_b: float, bits: int, seq: int, batch: int,

layers: int, kv_heads: int, head_dim: int,

usable_gib: float = 96.0, kv_elem_bytes: int = 2) -> dict:

weight_gib = params_b * 1e9 * bits / 8 / GB

kv_gib = (kv_per_token_bytes(layers, kv_heads, head_dim, kv_elem_bytes)

* seq * batch / GB)

remain = usable_gib - weight_gib - kv_gib

return {

"weight_GiB": round(weight_gib, 2),

"kv_GiB": round(kv_gib, 2),

"remain_GiB": round(remain, 2),

"fits": remain > usable_gib * 0.10, # 至少留 10% 余量

}

if __name__ == "__main__":

cases = [

# 名称, 参数量B, 位宽, 序列, batch, 层数, KV头, 头维度

("70B INT8 32K", 70, 8, 32768, 1, 80, 8, 128),

("70B INT8 128K", 70, 8, 131072, 1, 80, 8, 128),

("70B INT4 128K", 70, 4, 131072, 1, 80, 8, 128),

("32B INT8 128K", 32, 8, 131072, 1, 64, 8, 128),

("32B FP16 128K", 32, 16, 131072, 1, 64, 8, 128),

]

for name, p, bits, s, b, l, kh, hd in cases:

print(name, plan(p, bits, s, b, l, kh, hd))

示例输出(96GB 可用、KV 用 FP16):

配置权重128K KV合计结论
70B INT8 + 32K约 70GB约 10GiB约 80GB够,余量约 16GB
70B INT8 + 128K约 70GB约 40GiB约 110GB装不下
70B INT4 + 128K约 40GB约 40GiB约 80GB够
32B INT8 + 128K约 32GB约 32GiB约 64GB余量充足
32B FP16 + 128K约 64GB约 32GiB约 96GB刚好卡满,不建议

这些数字是算术结果,不是实测;模型结构不同(层数、KV 头数)会改变结论。

三、带宽账:为什么跨过容量线是断崖

逐 token 解码时,每生成一个 token 都要把参与计算的权重读一遍。所以解码速度的上界近似为:

tokens/s ≈ 显存带宽 / 每 token 需要读取的权重字节

70B INT8 约 70GB 权重,1792 GB/s 的卡理论上界约 25.6 tokens/s;按 50%–70% 的实际效率,大约 13–18 tokens/s。这是量级判断,不是性能承诺。

一旦权重装不下、被迫把部分层卸载到系统内存,路径带宽从 1792 GB/s 变成 PCIe 5.0 ×16 的约 64 GB/s,相差约 28 倍。这就是「性能悬崖」:不是慢一点,是换了一个数量级的瓶颈。

四、可复现的压测方法

不要只看厂商给的 tokens/s。用同一个模型、同一份 prompt,分三段测:

# 1. 启动服务,限制上下文与并发

vllm serve <model> \

--max-model-len 32768 \

--gpu-memory-utilization 0.90 \

--max-num-seqs 8

# 2. 观察显存与 GPU 利用率

nvidia-smi --query-gpu=timestamp,memory.used,memory.total,utilization.gpu \

--format=csv -l 1

测试分三组:

组别输入观察说明
短 prompt、短输出256 / 128 tokensTTFT、TPOT看基础延迟
长 prompt、短输出8K / 128TTFT看预填充能力
短 prompt、长输出256 / 4KTPOT看逐 token 解码带宽
高并发8 / 16 并发吞吐、P99看 KV Cache 与调度

重点看两件事:显存是否在长上下文时接近打满;输出变长后 TPOT 是否明显上升。后者是带宽受限的典型信号。

五、三个容易误判的点

MoE 省计算不省容量。106B 总参数、12B 激活的模型,权重仍要按 106B 驻留;激活参数只减少每 token 计算量。

多卡容量不等于单卡容量线性叠加。两张 48GB 不等于一张 96GB:并行切分、通信缓冲、负载不均衡都会吃掉有效容量。

MIG 切片与装大模型互斥。96GB 切成 4 个 24GB 实例后,单个模型只能用 24GB;要隔离就接受单模型预算收缩,要装大模型就整卡跑。

边界与适用条件

  • 带宽上限是理论量级,实际吞吐受模型结构、量化方式、批大小、框架实现影响。
  • KV Cache 的每元素字节可按需改为 FP8,但会带来精度与实现兼容问题,需实测。
  • 统一内存机型的可用带宽受内存子系统影响,不能按独显带宽套算。

工程落地中的一个选择

如果要做本地推理选型,建议先用自己的模型和真实上下文跑一轮压测,再决定 96GB 档位。商红科技做工作站与服务器的选型交付,可以按「权重 + KV + 带宽」三笔账把配置和边界一起过一遍;更细的参数表与边界条件,见这份公开拆解。最终结论仍应以你自己的压测数据为准。

商红科技能接的是推理平台选型、整机部署与压测配合这一段;具体 tokens/s 不做事先承诺,以你的实测为准。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进