3、CPU 推理基础:llama.cpp 的纯 CPU 推理流程,量化模型(Q4_0, Q5_K_M)的使用

好,咱们进入实战环节。这一章我带你走一遍最基础的 CPU 推理流程。说白了,就是让大模型在你的笔记本上跑起来,不依赖任何显卡。

你可能会问:“CPU 跑大模型?那不是慢得要死吗?” 嗯,确实不快,但够用。而且,很多生产环境压根没有 GPU。我去年帮一家金融客户做私有化部署,他们的服务器清一色都是 Intel Xeon,连个 NVIDIA 的卡影儿都没有。所以,纯 CPU 推理,是基本功。

3.1 编译 llama.cpp:从源码开始

首先,你得把 llama.cpp 编译出来。别怕,步骤很简单。

git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
mkdir build && cd build
cmake ..
make -j4

这里有个小坑。我刚开始编译的时候,直接 make 没加 -j4,结果等了快十分钟。你想想看,多核时代,不加并行编译,那不是浪费资源吗?

我的习惯: 编译时用 -j$(nproc) 自动获取 CPU 核心数。比如 make -j$(nproc),省心又高效。

编译完成后,你会看到 mainquantize 这两个可执行文件。前者用来跑推理,后者用来做量化。嗯,咱们后面会用到。

3.2 下载模型:选一个合适的基座

模型从哪来?我推荐去 Hugging Face 下载 GGUF 格式的。GGUF 是 llama.cpp 的原生格式,加载速度比老式的 GGML 快不少。

举个例子,下载一个 7B 参数的模型:

wget https://huggingface.co/TheBloke/Llama-2-7B-GGUF/resolve/main/llama-2-7b.Q4_0.gguf

注意文件名里的 Q4_0,这就是量化标识。Q4_0 表示 4-bit 量化,模型大小从原来的 13GB 左右压缩到 3.5GB 左右。你想想看,一个 3.5GB 的文件,普通笔记本都能装得下。

核心概念: 量化就是把模型参数的精度降低。比如从 16-bit 浮点数变成 4-bit 整数。代价是精度损失,但换来的是体积缩小和推理加速。

3.3 纯 CPU 推理:跑起来看看

模型下载好了,编译也完成了。现在咱们跑一次推理试试。

./main -m llama-2-7b.Q4_0.gguf -p "Hello, how are you?" -n 128

参数解释:

  • -m:指定模型文件路径
  • -p:输入提示词(prompt)
  • -n:生成的最大 token 数

我第一次跑的时候,心里还挺忐忑的。结果等了大概 10 秒,屏幕上开始一个字一个字地往外蹦。说实话,那个感觉挺奇妙的。虽然速度比不上 ChatGPT,但至少证明这条路走得通。

你可能会问:“为什么这么慢?” 原因很简单:CPU 的并行计算能力远不如 GPU。CPU 擅长串行任务,而矩阵乘法这种大规模并行计算,天生就是 GPU 的菜。

3.4 量化模型对比:Q4_0 vs Q5_K_M

量化不是只有一种。llama.cpp 支持多种量化方案。我常用的两种是 Q4_0 和 Q5_K_M。

量化类型 位宽 模型大小(7B) 推理速度(token/s) 质量损失
Q4_0 4-bit ~3.5 GB ~15 中等
Q5_K_M 5-bit ~4.3 GB ~12 较低

从表格能看出来,Q5_K_M 比 Q4_0 大了将近 1GB,但质量损失更小。怎么选?

  • Q4_0:适合内存紧张、追求速度的场景。比如在 4GB 内存的旧笔记本上跑。
  • Q5_K_M:适合对输出质量有要求、内存还算宽裕的场景。我个人的习惯是,只要内存够,优先用 Q5_K_M。
避坑指南: 我曾经在 8GB 内存的机器上跑 Q5_K_M 的 13B 模型,结果直接 OOM(内存溢出)。后来才发现,模型加载时不仅需要存储参数,还需要额外的推理缓存。所以,选模型时一定要留出 2-3GB 的余量。

3.5 自己动手量化:从 FP16 到 Q4_0

如果你手头有一个 FP16 的原始模型,想把它量化成 Q4_0,怎么做?

llama.cpp 提供了 quantize 工具:

./quantize ./models/llama-2-7b-fp16.gguf ./models/llama-2-7b-q4_0.gguf Q4_0

这个命令会把 FP16 模型转换成 Q4_0。转换过程大概需要几分钟,取决于你的 CPU 性能。

我记得第一次做量化时,心里没底,怕把模型搞坏了。结果量化完跑了一下,发现输出质量虽然略有下降,但完全在可接受范围内。说白了,对于大多数对话场景,Q4_0 和 FP16 的差异,普通人根本感觉不出来。

3.6 核心逻辑:一张图看懂

说了这么多,咱们用一张图把整个流程串起来。

CPU 推理核心流程 1. 下载 GGUF 模型 2. 编译 llama.cpp 3. 量化(可选) 4. 推理 如果模型已是量化版,跳过此步 量化方案对比 Q4_0 Q5_K_M FP16(原始) 4-bit / 3.5GB 5-bit / 4.3GB 16-bit / 13GB 速度最快 / 质量中等 速度中等 / 质量较好 速度最慢 / 质量最好

这张图把整个流程分成了四步。你从左边开始,下载模型、编译工具、按需量化,最后跑推理。每一步都有对应的工具和参数,照着做就行。

3.7 一些实用技巧

最后,分享几个我踩过的坑和总结的技巧:

  • 线程数设置:-t 参数控制线程数。比如 -t 8 表示用 8 个线程。我建议设置为物理核心数,而不是逻辑核心数。超线程对推理加速帮助不大。
  • 批处理大小:-b 参数。默认是 512,如果内存紧张,可以降到 256 或 128。
  • 上下文长度:-c 参数。默认是 512,如果你需要长对话,可以设成 2048 或 4096。但注意,上下文越长,内存占用越大。
我的经验: 在 8 核 CPU 上,-t 8 -b 256 -c 2048 是一个比较稳妥的组合。既能保证速度,又不会把内存吃光。

好了,这一章的内容就到这里。你学会了如何编译 llama.cpp、下载量化模型、跑纯 CPU 推理,还了解了 Q4_0 和 Q5_K_M 的区别。这些是后续所有硬件加速的基础。嗯,先消化一下,咱们下一章见。