AI 实用 02|本地跑大模型:显存怎么算,方案怎么选

先算清楚:你到底需要多少显存

所有"跑不动"的问题,八成能用一道乘法估出来:

显存 ≈ 参数量 × 每参数字节数  +  上下文 KV cache  +  运行开销(约 1~2 GB)

每参数字节数取决于量化精度:

量化 每参数约 7B 模型 14B 32B 70B
FP16(原始) 2.0 字节 14 GB 28 GB 64 GB 140 GB
Q8_0 1.06 字节 7.5 GB 15 GB 34 GB 75 GB
Q5_K_M 0.72 字节 5.1 GB 10 GB 23 GB 51 GB
Q4_K_M 0.60 字节 4.3 GB 8.6 GB 19 GB 43 GB
Q3_K_M 0.50 字节 3.6 GB 7.2 GB 16 GB 36 GB

Q4_K_M 是目前的性价比拐点。再往下压(Q3、Q2)质量掉得明显,尤其是数学、代码和多语言能力;往上是 Q5/Q8,质量提升有限但显存翻倍。

别忘 KV cache,它经常是"爆显存"的真凶

上下文越长,KV cache 越大。粗略经验:

  • 7B / Q4,8K 上下文:约 0.5~1 GB
  • 32B / Q4,8K 上下文:约 2~4 GB
  • 70B / Q4,8K 上下文:约 5~8 GB
  • 开到 32K 上下文:上面数字基本乘 4

所以"32B 模型 19G,我有 24G 卡,稳了"这个判断是错的——加 8K 上下文和运行开销,24G 卡很容易直接 OOM。

保守公式:

需要的显存 ≈ 权重 + 0.1 GB × (上下文 K 数) × (参数量 / 7)

7B、8K:4.3 + 0.8 ≈ 5.1 GB。32B、8K:19 + 3.6 ≈ 22.6 GB。这个估算够用。

三种方案,按场景选

方案 适合 优点 缺点
Ollama 个人、单机、快速验证 一行命令跑起来,自带模型库 并发能力一般,参数可控性低
llama.cpp 想要精细控制、CPU 混合推理 量化最全,CPU/GPU 混合,跨平台 要自己下模型、配参数
vLLM 团队服务、多并发 API 吞吐极高(PagedAttention + 连续批处理) 吃显存,对模型格式有要求

判断标准:一个人用 → Ollama;要压榨硬件或没显卡 → llama.cpp;给团队提供 API → vLLM。

方案一:Ollama(十分钟就能跑起来)

# 安装(Linux)
curl -fsSL https://ollama.com/install.sh | sh

# 拉取并运行
ollama pull qwen3:8b
ollama run qwen3:8b

# 列出现有模型
ollama list

它默认在本机 11434 端口提供 HTTP 接口,且兼容 OpenAI 的部分接口格式,所以很多客户端能直接对接:

curl http://localhost:11434/api/chat -d '{
  "model": "qwen3:8b",
  "messages": [{"role": "user", "content": "用一句话解释什么是向量数据库"}],
  "stream": false
}'

让它能被局域网访问,并支持并发

OLLAMA_HOST=0.0.0.0:11434 \
OLLAMA_NUM_PARALLEL=4 \
OLLAMA_MAX_LOADED_MODELS=2 \
OLLAMA_KEEP_ALIVE=30m \
ollama serve
  • NUM_PARALLEL:同时处理几个请求。每加一个并发,KV cache 就多一份,显存要留够。
  • KEEP_ALIVE:多久没请求就卸载模型。设长一点能避免反复加载(加载一个 8B Q4 模型要几秒)。
  • MAX_LOADED_MODELS:同时驻留几个模型,多了会抢显存。

自定义系统提示与参数:Modelfile

FROM qwen3:8b

PARAMETER temperature 0.3
PARAMETER num_ctx 8192
PARAMETER top_p 0.9

SYSTEM """你是一名严谨的技术文档助手。
回答时先给结论,再给依据。不确定的内容必须标注"不确定",禁止编造。"""
ollama create my-assistant -f Modelfile
ollama run my-assistant

num_ctx 默认可能小于你要的值,一定要显式设置,否则长文档会被截断,表现为"模型看不到后半段"。

方案二:llama.cpp(控制力最强)

# 编译(有 CUDA 就开)
cmake -B build -DGGML_CUDA=ON
cmake --build build -j

# 单次推理
./build/bin/llama-cli -m qwen3-8b-q4_k_m.gguf \
  -ngl 99 \          # 全部层放 GPU,99 表示尽量多
  -c 8192 \          # 上下文长度
  -t 8 \             # CPU 线程数
  -p "你好,介绍一下你自己"

# 起一个 OpenAI 兼容服务
./build/bin/llama-server -m model.gguf -ngl 99 -c 8192 \
  --host 0.0.0.0 --port 8080

-ngl 是关键参数。显存不够时不要直接归零,而是逐层减少(-ngl 20、-ngl 30),把一部分层留在 CPU 上——这就是"混合推理",速度会降但能跑起来。

一个实用的判断流程:

  1. 显存 ≥ 权重 + KV,-ngl 99。
  2. 稍微不够,逐级降 -ngl,观察 llama-server 输出的 offload 信息。
  3. 显存很小,考虑更小的模型或更低量化,别硬扛。

方案三:vLLM(要高并发就用它)

pip install vllm

python -m vllm.entrypoints.openai.api_server \
  --model Qwen/Qwen3-8B \
  --served-model-name qwen3-8b \
  --dtype auto \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.90 \
  --port 8000

多卡并行:

--tensor-parallel-size 2      # 张量并行,切成 2 份放在两张卡上

几个必须理解的参数:

  • --gpu-memory-utilization:vLLM 会预分配这个比例的显存给 KV cache。设 0.9 意味着它主动占掉 90%。同卡上还有别的进程时,这个值必须降下来,否则直接 OOM。
  • --max-model-len:模型能接受的最大上下文。设太大,vLLM 会为最坏情况预留 KV 空间,可能直接起不来。从 8192 开始,不够再加。
  • --tensor-parallel-size:必须能整除注意力头数,双卡最常用。

vLLM 真正的价值在吞吐:它把多个请求的 KV cache 分页管理(PagedAttention),能把不同长度的请求连续批处理。同样一台机器,vLLM 的并发吞吐通常是 Ollama 的数倍。

代价是:模型格式要求严格(HuggingFace 格式,不是 GGUF),启动慢(要编译 CUDA 图),显存占用高。

硬件怎么挑

显卡的第一指标不是算力,是显存和带宽

推理(尤其是生成阶段)是内存带宽受限的,不是算力受限。所以:

  • 一张 24G、带宽 1 TB/s 的卡,跑 7B Q4 比一张 16G、带宽 400 GB/s 的卡快得多。
  • 显存不够直接没法跑,显存够但带宽低只是慢。先保显存,再看带宽。

消费卡 vs 服务器卡

消费卡(如 RTX 4090) 服务器卡(如 L40S / H100)
单卡显存 24 GB 48 / 80 GB
多卡互联 无 NVLink,走 PCIe NVLink,带宽高一个量级
适合 7B~32B 单卡推理 70B 以上、多卡张量并行、高并发
功耗/噪音 高,不适合长时间满载 数据中心级

如果目标是 32B 以内的单机推理,消费卡完全够用。做 70B 或多卡并行,就得考虑服务器平台(PCIe 通道数、供电、散热都要重新算)。

没有好显卡怎么办:CPU 也能跑

./llama-cli -m qwen3-4b-q4_k_m.gguf -ngl 0 -c 4096 -t 16

现代服务器 CPU(支持 AVX-512,最好有 AMX)跑 7B Q4,量级在 每秒 5~15 个 token。这意味着:

  • 短问答(一两百字)能忍,几十秒出结果。
  • 长文生成基本不可用。

CPU 推理适合"离线批处理"而不是"交互对话"——晚上跑任务,早上看结果。

常见坑

  1. 只看权重不看 KV,24G 卡装 32B 一开长上下文就 OOM。
  2. num_ctx 用默认值,长文档被静默截断,还以为是模型笨。
  3. 多个服务抢同一张卡,vLLM 的 gpu-memory-utilization 没调低。
  4. 量化过度(Q2/Q3),中文和代码质量明显下降,却怪模型不行。
  5. 并发数开太大,每个请求的 KV 都要显存,实际并发上限比想象的低。
  6. 模型来源不明,加载了带后门的权重。只从官方或可信仓库下载。
  7. 用 GGUF 去喂 vLLM,格式不对,起不来。
  8. 忽略加载时间,KEEP_ALIVE 设太短,每次请求都重新加载模型。

一条选择路径

个人试用 / 快速验证                    → Ollama
没独显 / 想要 CPU+GPU 混合 / 精细控制   → llama.cpp
团队提供 API / 需要高并发 / 有服务器卡  → vLLM

先按"能用起来"选,跑出真实瓶颈再换。**大多数人卡在"选方案"这一步,其实任何一个先跑通都比继续纠结有价值。