前言

Ollama 适合个人使用,但当你要在生产环境提供 API 服务时——高并发、低延迟、高吞吐——就需要专业的推理框架了。

目前开源社区主流的两个选择是 vLLM(GPU 推理)和 llama.cpp(CPU/GPU 通用推理)。这篇文章讲清楚它们分别怎么用,以及怎么选。


一、高并发推理架构与原理

在单机或集群部署大模型服务时,最核心的诉求是高吞吐(Throughput)与低首字延迟(TTFT, Time To First Token)。

  • 传统推理瓶颈:静态分配 KV Cache,长文本请求会独占预留显存,导致大量显存碎片(浪费高达 60%~80%),同时一个 batch 里的请求必须等最长的请求生成完毕才能结束。
  • vLLM 破局点:借助 PagedAttention(虚拟内存分页)与 Continuous Batching(按 token 粒度调度插队),显存利用率接近 100%,并发吞吐提升 3~10 倍。

二、vLLM:GPU 高性能推理实战

安装

1
pip install vllm

启动 OpenAI 兼容 API

1
2
3
4
5
6
# 一行命令极速拉起服务
vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192 \
--gpu-memory-utilization 0.90

关键参数:

参数 作用 建议
--max-model-len 最大上下文长度 根据需求设,越长越吃显存
--gpu-memory-utilization 显存使用上限占比 0.85~0.95,留一点给系统
--tensor-parallel-size 多卡并行 有几张 GPU 就设几
--dtype 推理精度 auto 自动选
--quantization 量化方式 awq/gptq/fp8 等

调用

1
2
3
4
5
6
7
8
9
10
11
12
13
from openai import OpenAI

client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-needed"
)

response = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=[{"role": "user", "content": "介绍一下 Kubernetes"}],
max_tokens=500
)
print(response.choices[0].message.content)

性能基准参考

在单张 A100 80GB 上,vLLM 部署 Qwen2.5-7B:

并发数 吞吐量 (tokens/s) 平均延迟 (ms)
1 ~50 ~200
8 ~350 ~450
32 ~1200 ~900
64 ~1800 ~1500

这不是精确数字(取决于 prompt 长度、输出长度等),但足以看出 vLLM 在高并发下的优势。


三、llama.cpp:CPU 和边端推理

llama.cpp 是一个纯 C/C++ 实现的推理引擎,不需要 Python 运行时,不需要 CUDA。它能在 CPU 上跑、在 GPU 上跑、在手机和树莓派上跑。

Ollama 底层用的就是 llama.cpp。

安装

1
2
3
4
5
6
7
# macOS
brew install llama.cpp

# Linux(从源码编译)
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make -j

运行模型

1
2
3
4
5
6
7
# 启动 HTTP 服务
./llama-server \
-m /path/to/qwen2.5-7b-q4_k_m.gguf \
--host 0.0.0.0 \
--port 8080 \
-c 4096 \
-ngl 32

关键参数:

参数 作用
-m 模型文件路径(GGUF 格式)
-c 上下文窗口大小
-ngl 多少层卸载到 GPU(0 表示纯 CPU)
-t CPU 线程数
-b batch 大小

llama.cpp 的 HTTP 服务也兼容 OpenAI API 格式:

1
2
3
4
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="not-needed"
)

四、模型量化实践

GGUF 量化(llama.cpp 用)

1
2
3
4
5
# 1. 将原版 HuggingFace 模型转换为未量化的 f16 精度 GGUF 格式(输出为 model-f16.gguf)
python llama.cpp/convert_hf_to_gguf.py /path/to/original/model --outfile model-f16.gguf

# 2. 将 f16 模型量化为 Q4_K_M 格式(量化器必须同时指定输入、输出及量化级别)
./llama-quantize model-f16.gguf model-q4.gguf Q4_K_M
量化级别 模型大小(7B) 质量损失 适用
Q8_0 ~7.5 GB 极小 追求质量
Q4_K_M ~4.5 GB 很小 推荐,平衡之选
Q4_0 ~4.0 GB 小 省显存
Q2_K ~2.8 GB 有感知 极致省空间

Q4_K_M 是大多数场景的最佳选择——质量接近无损,体积减半。

AWQ 量化(vLLM 生产推荐)

AWQ(Activation-aware Weight Quantization)仅对显著权重进行保护,实现极低精度下的质量无损:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from transformers import AutoTokenizer
from awq import AutoAWQForCausalLM

model_path = "Qwen/Qwen2.5-7B-Instruct"
quant_path = "./qwen2.5-7b-awq"

# 1. 加载 Tokenizer 与模型
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoAWQForCausalLM.from_pretrained(model_path, **{"low_cpu_mem_usage": True})

# 2. 传入 tokenizer 执行 4-bit 量化
model.quantize(tokenizer, quant_config={"zero_point": True, "q_group_size": 128, "w_bit": 4, "version": "GEMM"})

# 3. 导出量化产物
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)

五、vLLM vs llama.cpp 选型决策

维度 vLLM llama.cpp
运行环境 必须 NVIDIA / AMD GPU 纯 CPU 可跑,也支持 Apple Silicon / GPU 加速
吞吐能力 极高(Continuous Batching 并行) 中等(受限于 CPU 核心与内存带宽)
并发能力 轻松支撑 50~200+ 高并发 适合 1~5 低并发或单人私有化使用
首字延迟 (TTFT) 极低(支持 Chunked Prefill) 纯 CPU 较慢,GPU 加速后中等
部署依赖 较重(依赖 Python / CUDA / PyTorch) 极致轻量(单个 C++ 编译可执行二进制)
适合场景 企业高并发 API 网关、知识库中台 嵌入式设备、边缘盒子、个人本地调试、低成本容灾
模型格式 HuggingFace Safetensors、AWQ、GPTQ、FP8 GGUF

六、vLLM 生产部署全配置与性能调优

[!WARNING]
在 Bash / Shell 启动脚本中,反斜杠 \ 后面绝不能跟空格或注释,否则会导致续行符失效而报错中断!

生产环境推荐启动配置:

1
2
3
4
5
6
7
8
9
10
# vLLM 生产级启动命令(参数后杜绝直接挂载注释)
vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 8192 \
--gpu-memory-utilization 0.90 \
--max-num-seqs 128 \
--enable-prefix-caching \
--enable-chunked-prefill \
--disable-log-requests

关键生产参数详解:

  • --gpu-memory-utilization 0.90:预留 10% 显存给 CUDA 运行时与临时激活值,防止瞬时峰值 OOM。
  • --max-num-seqs 128:限制最大并发请求序列数,防止过载导致排队超时。
  • --enable-prefix-caching:强烈推荐。自动缓存 Prompt 相同的前缀(如知识库 Prompt 或固定 System 指令),长前缀命中缓存时首字时间从几百毫秒骤降至几毫秒!
  • --enable-chunked-prefill:生产关键优化。将长 Prompt 的 Prefill 过程切分为小块(Chunks)与 Decode 步穿插执行,彻底解决“一个 8K 超长请求进入导致其他正在生成的几十个并发请求全部卡顿”的生产痛点。

监控与网关接入:

  1. Prometheus 监控指标:vLLM 内置导出 /metrics 端点,可直接监控 GPU 显存利用率、KV Cache 占用率(vllm:gpu_cache_usage_factor)与 P99 首字延迟。
  2. Nginx 负载均衡:生产必须在 vLLM 前置 Nginx 或 Kong 做 API Key 鉴权、速率限制(Rate Limiting)及失败重试。