核心结论

即使模型以 int4 加载,在推理过程中临时反量化为 float16 进行计算,显存仍然够用,是因为:

  1. 反量化是“按需、分块、临时”的,不是一次性把整个模型转成 float16;
  2. 只有当前参与计算的权重/激活值被反量化,用完即释放;
  3. 现代推理框架(如 GGUF + llama.cpp / vLLM / Transformers + bitsandbytes)做了极致显存优化
  4. int4 模型本身占用极小显存,留出了足够空间给临时 float16 缓冲区

详细解释

1. int4 量化大幅降低模型存储开销
  • 一个 7B 参数的模型:
    • float16:7B × 2 bytes ≈ 14 GB
    • int4:7B × 0.5 bytes ≈ 3.5 GB
  • 所以加载 int4 模型后,显存只占 ~3.5GB,剩下大量空间可用
2. 反量化 ≠ 全模型转 float16

关键误区:不是把整个 int4 模型一次性反量化成 float16 存在显存里!

实际过程(以矩阵乘法为例):

输入 (float16) 
   ↓
权重 (int4, 压缩存储)
   ↓
【仅对当前需要计算的权重块】→ 反量化为 float16(临时张量)
   ↓
执行 matmul(input, weight_float16)
   ↓
释放临时 float16 权重
   ↓
输出 (float16)
  • 这个 临时 float16 权重块很小(比如一次只反量化一个 layer 的 QKV 投影矩阵)
  • 计算完立刻释放,不会累积
3. 激活值(Activations)仍是主要显存消耗者

在推理中,显存大头往往是:

  • 中间激活值(activations):batch_size 越大,激活值越多
  • KV Cache(用于自回归生成):生成长文本时会累积

权重(weights) 即使临时反量化,也只占一小部分。

举例:7B 模型生成 512 token,batch=1

  • int4 权重:~3.5 GB
  • KV Cache:~2–3 GB
  • 临时反量化缓冲区:可能 < 0.5 GB(分块处理)
  • 总计 < 8 GB → 在 8GB 显卡上可运行
4. 推理引擎的优化技术

主流框架采用多种技术减少反量化开销:

技术 说明
分块计算(Tiling) 每次只反量化一小块权重
内核融合(Kernel Fusion) 反量化 + 矩阵乘在一个 CUDA kernel 中完成,避免中间张量驻留
就地反量化(In-place dequant) 直接输出到计算缓冲区,不额外分配内存
使用 int4 GEMM 内核(如 cuBLASLt) 某些硬件支持直接 int4 计算,无需反量化(但 Ollama 默认仍用反量化)

Ollama 底层基于 llama.cpp,它使用 GGUF 格式 + 分块反量化,显存效率极高。


类比理解

想象你有一本压缩的电子书(int4 模型):

  • 平时它只占 10MB 硬盘空间;
  • 当你想阅读第 5 章时,只解压第 5 章到内存(临时 float16);
  • 读完就释放,不会把整本书都解压
  • 所以内存(显存)始终够用。

那为什么训练不能用 int4?

因为训练需要:

  • 全程保留梯度(float16/float32)
  • 频繁更新权重
  • 无法分块释放

所以训练必须用 float,而推理可以“用时再解压”


总结

问题 答案
int4 模型反量化成 float16 会不会爆显存? 不会,因为反量化是临时、分块、按需
显存主要被什么占用? 激活值、KV Cache、临时计算缓冲区,不是全量权重
为什么 int4 能在小显存跑大模型? 存储省 75%,计算时只临时展开小块
Ollama / llama.cpp 如何做到的? GGUF + 高效分块反量化 + 内核优化

所以你观察到的现象完全正常:int4 加载 → 推理时局部反量化 → 显存依然满足

如果你用的是 8GB 显卡跑 qwen3:8b-int4,这正是量化 + 优化推理引擎带来的红利!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐