llama.cpp 架构
llama.cpp 是 Georgi Gerganov 用纯 C/C++ 编写的 LLM 推理引擎,最初为 LLaMA 模型设计,现已支持 40+ 模型架构。其核心设计哲学:
- 零依赖:仅依赖 C/C++ 标准库,编译后单二进制运行
- 跨平台:x86/ARM CPU、NVIDIA/AMD/Apple GPU、WebAssembly
- 量化优先:原生 GGML/GGUF 量化格式,在 CPU 上实现实用级推理速度
┌─────────────────────────────────────────┐
│ CLI / Server / API │
│ (llama-cli / llama-server) │
├─────────────────────────────────────────┤
│ GGML Compute Graph │
│ (Operator Fusion + SIMD/NEON) │
├──────────┬───────────┬──────────────────┤
│ CPU │ CUDA │ Metal / Vulkan │
│ Backend │ Backend │ Backend │
│ (AVX2/ │ (NVIDIA) │ (Apple/AMD/Intel)│
│ AVX512/ │ │ │
│ NEON) │ │ │
└──────────┴───────────┴──────────────────┘
GGUF 格式
GGUF(GGML Universal Format)是 llama.cpp 的模型文件格式,取代了早期的 GGML 格式。
GGUF 结构
GGUF File Layout:
┌────────────────────┐
│ Magic Number │ "GGUF" (4 bytes)
├────────────────────┤
│ Metadata │ KV pairs (architecture, vocab, hyperparams)
├────────────────────┤
│ Tokenizer │ Token embeddings / vocabulary
├────────────────────┤
│ Tensor Data │ Quantized weights (aligned blocks)
└────────────────────┘
GGUF vs SafeTensors
| 特性 | GGUF | SafeTensors |
|---|---|---|
| 量化支持 | ✅ 内置多种量化 | ❌ 仅原始精度 |
| 元数据 | ✅ 丰富 KV | ⚠️ 有限 |
| 加载速度 | 快(内存映射) | 快 |
| 通用性 | llama.cpp 生态 | HF 生态 |
| 分片支持 | ✅ | ✅ |
量化方案详解
llama.cpp 支持丰富的量化方案,命名规则为 Q<bits>_<variant>:
量化方案对比
| 量化 | 每权重比特 | 模型大小 (7B) | PPL 变化 | 速度 (tok/s) | 推荐场景 |
|---|---|---|---|---|---|
| Q8_0 | 8.5 | 7.2 GB | +0.03 | 42 | 最高质量 |
| Q6_K | 6.6 | 5.5 GB | +0.05 | 48 | 高质量 |
| Q5_K_M | 5.7 | 4.8 GB | +0.08 | 54 | 均衡之选 |
| Q4_K_M | 4.8 | 4.1 GB | +0.15 | 60 | 最推荐 |
| Q4_0 | 4.5 | 3.8 GB | +0.35 | 68 | 极致速度 |
| Q3_K_M | 3.9 | 3.3 GB | +0.52 | 65 | 低端设备 |
| Q2_K | 2.6 | 2.2 GB | +1.2 | 70 | 极限压缩 |
量化原理
// Q4_K_M 量化结构(简化)
// 每个 block 包含 32 个权重
typedef struct {
uint8_t scales[16]; // 6-bit 量化刻度
uint8_t quants[128]; // 4-bit 量化值 (32 weights × 4 bits / 8 bits)
} block_q4_K;
// 每个权重的实际值 = scale × quant
// Q4_K_M 中的 "K" 表示使用 super-block 结构
// "M" 表示混合精度:attention 层用 Q6_K,其余用 Q4_K
模型转换与量化
# 从 HuggingFace 下载原始模型
huggingface-cli download meta-llama/Llama-3.1-8B-Instruct \
--local-dir ./Llama-3.1-8B
# 转换为 GGUF(需要 llama.cpp 源码)
cd llama.cpp
python convert_hf_to_gguf.py \
../Llama-3.1-8B \
--outfile ../Llama-3.1-8B-FP16.gguf \
--outtype f16
# 量化为不同精度
./llama-quantize Llama-3.1-8B-FP16.gguf Llama-3.1-8B-Q4_K_M.gguf Q4_K_M
./llama-quantize Llama-3.1-8B-FP16.gguf Llama-3.1-8B-Q5_K_M.gguf Q5_K_M
./llama-quantize Llama-3.1-8B-FP16.gguf Llama-3.1-8B-Q8_0.gguf Q8_0
CPU/GPU 混合推理
llama.cpp 支持将模型的不同 layer 分配到不同计算后端。
Layer Offload 策略
# 全 CPU 推理
./llama-cli -m Llama-3.1-8B-Q4_K_M.gguf -p "Hello" -n 512
# 全 GPU 推理(-ngl 999 = 所有层放 GPU)
./llama-cli -m Llama-3.1-8B-Q4_K_M.gguf -p "Hello" -n 512 -ngl 999
# 混合推理(-ngl 20 = 20 层放 GPU,其余放 CPU)
./llama-cli -m Llama-3.1-70B-Q4_K_M.gguf -p "Hello" -n 512 -ngl 20
性能参考
以 Llama 3.1 8B Q4_K_M 为例:
| 配置 | 硬件 | 速度 (tok/s) | 说明 |
|---|---|---|---|
| 纯 CPU | Ryzen 9 7950X | 28 | 16 核全用 |
| 纯 CPU | Apple M2 Pro | 35 | 统一内存优势 |
| -ngl 10 | Ryzen + RTX 4060 8G | 45 | 部分 layer offload |
| -ngl 33 (全部) | RTX 4060 8G | 62 | 全 GPU |
| -ngl 999 | RTX 4090 24G | 110 | 全 GPU |
自动 Layer 分配
# 自动计算最优 layer offload 数量
import subprocess, json
def auto_offload(model_path, gpu_vram_gb):
"""根据 GPU 显存自动计算 offload 层数"""
# 获取模型信息
result = subprocess.run(
['./llama-gguf', model_path, '--json'],
capture_output=True, text=True
)
info = json.loads(result.stdout)
total_layers = info['metadata']['llm.tensor_count']
layer_size_mb = info['metadata']['file_size_mb'] / total_layers
# 预留 1GB 给 KV Cache 和上下文
available_mb = (gpu_vram_gb * 1024) - 1024
max_offload = int(available_mb / layer_size_mb)
return min(max_offload, total_layers)
offload = auto_offload("Llama-3.1-70B-Q4_K_M.gguf", gpu_vram_gb=24)
print(f"Offloading {offload} layers to GPU")
性能调优
线程配置
# 物理核心数(不用超线程)
nproc # 查看核心数
# 设置线程数 = 物理核心数
./llama-cli -m model.gguf -t 16 -p "Hello" -n 512
# 批处理线程(prefill 阶段)可以更多
./llama-cli -m model.gguf -t 16 -tb 24 -p "Hello" -n 512
| 线程数 | 速度 (tok/s) | 说明 |
|---|---|---|
| 4 | 18 | 不足 |
| 8 | 28 | 线性提升 |
| 16 | 35 | 接近峰值 |
| 32 | 34 | 超线程无收益 |
| 64 | 30 | 下降(调度开销) |
上下文长度与 KV Cache
# 默认上下文 2048,生产环境需要增大
./llama-cli -m model.gguf -c 8192 -p "Hello" -n 512
# KV Cache 量化(减少显存/内存占用)
./llama-cli -m model.gguf -c 32768 \
--cache-type-k q8_0 \
--cache-type-v q8_0 \
-p "Hello" -n 512
| KV Cache 类型 | 内存占用 (32K ctx, 8B) | PPL 变化 |
|---|---|---|
| f16 (默认) | 4.0 GB | 基准 |
| q8_0 | 2.0 GB | +0.02 |
| q4_0 | 1.0 GB | +0.15 |
Flash Attention
# 启用 Flash Attention(需要编译时开启)
cmake -B build -DGGML_CUDA=ON -DGGML_FLASH_ATTN=ON
cmake --build build
# 运行时启用
./llama-cli -m model.gguf -fa -p "Hello" -n 512
Server 模式
# 启动 OpenAI 兼容 API 服务器
./llama-server \
-m Llama-3.1-8B-Q4_K_M.gguf \
--host 0.0.0.0 \
--port 8080 \
-c 8192 \
-ngl 33 \
-t 16 \
-fa \
--api-key "your-secret-key"
# 支持 OpenAI 格式请求
curl http://localhost:8080/v1/chat/completions \
-H "Authorization: Bearer your-secret-key" \
-H "Content-Type: application/json" \
-d '{
"model": "llama3.1",
"messages": [{"role": "user", "content": "Hello"}],
"stream": true
}'
并发处理
# 启用 continuous batching(llama.cpp 新版本)
./llama-server \
-m model.gguf \
-c 8192 \
-np 4 \ # 4 个并行 slot
-cb \ # continuous batching
--port 8080
移动端部署
Android 编译
# 交叉编译 for Android (ARM64)
mkdir build-android && cd build-android
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-28 \
-DGGML_NEON=ON \
-DGGML_OPENMP=ON
cmake --build . -j
# 在手机上运行(通过 Termux 或 adb push)
./llama-cli -m model-Q4_K_M.gguf -t 8 -p "Hello" -n 256
性能参考(移动端)
| 设备 | 模型 | 量化 | 速度 (tok/s) | 内存占用 |
|---|---|---|---|---|
| iPhone 15 Pro (A17 Pro) | Llama 3.2 3B | Q4_K_M | 28 | 2.1 GB |
| Samsung S24 (SD8 Gen3) | Llama 3.2 3B | Q4_K_M | 22 | 2.1 GB |
| iPhone 15 Pro | Llama 3.1 8B | Q4_K_M | 12 | 5.2 GB |
| Pixel 8 Pro | Llama 3.2 3B | Q4_K_M | 18 | 2.1 GB |
Apple Silicon 优化
# Metal 后端(Apple GPU 加速)
cmake -B build -DGGML_METAL=ON
cmake --build build
# 运行时使用 Metal
./llama-cli -m model.gguf -ngl 99 -p "Hello" # 全部 layer offload 到 Metal
| 配置 | 模型 | 速度 (tok/s) |
|---|---|---|
| M2 Pro CPU only | 8B Q4_K_M | 35 |
| M2 Pro + Metal | 8B Q4_K_M | 58 |
| M2 Max + Metal | 70B Q4_K_M | 14 |
| M3 Ultra + Metal | 70B Q4_K_M | 22 |
编译优化指南
# 针对 CPU 特定指令集优化
cmake -B build \
-DGGML_AVX2=ON \ # Intel/AMD Haswell+
-DGGML_AVX512=ON \ # Intel Skylake-X+ / AMD Zen4+
-DGGML_FMA=ON \ # FMA3 指令
-DGGML_F16C=ON \ # FP16 转换指令
-DGGML_OPENMP=ON # 多线程并行
# 编译时 LTO 优化
cmake -B build -DGGML_LTO=ON -DCMAKE_BUILD_TYPE=Release
# 最优 CPU 编译(AVX512 系统)
cmake -B build \
-DGGML_AVX512=ON \
-DGGML_AVX2=ON \
-DGGML_FMA=ON \
-DGGML_F16C=ON \
-DCMAKE_BUILD_TYPE=Release \
-DGGML_LTO=ON
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
