MacBook Air M4 编译 llama.cpp 运行 GLM 模型:Metal GPU 加速实战
在上一篇教程中,我们介绍了使用 Ollama 一键部署 GLM-4 模型的方法。本文将带你更深入一层——手动编译 llama.cpp,利用 Apple M4 芯片的 Metal GPU 加速来运行 GLM 模型。这种方式虽然步骤更多,但提供了更精细的控制和更极致的性能调优空间。
llama.cpp 简介
llama.cpp 是由 Georgi Gerganov 开发的开源项目,使用纯 C/C++ 实现,专注于在消费级硬件上高效运行大语言模型。它的核心优势包括:
- 极致性能:针对 CPU 和 GPU 做了深度优化,支持 AVX2/AVX-512/Metal/CUDA 等多种加速方案
- 低依赖:纯 C/C++ 实现,无需安装庞大的 Python 环境和 PyTorch
- GGUF 格式:支持模型量化压缩,大幅减少内存占用
- API 服务:内置 HTTP 服务器,兼容 OpenAI API 格式
- 跨平台:支持 macOS、Linux、Windows,甚至树莓派
第一步:环境准备
安装 Xcode Command Line Tools
llama.cpp 的编译需要 C/C++ 编译器,macOS 上通过安装 Xcode Command Line Tools 来获取:
# 检查是否已安装
xcode-select -p
# 如果未安装,执行以下命令安装
xcode-select --install
安装 Homebrew 和依赖工具
# 安装 Homebrew(如果尚未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 安装编译依赖
brew install cmake git
# 验证安装
cmake --version
git --version
第二步:编译 llama.cpp(Metal GPU 加速)
克隆源码
# 克隆 llama.cpp 仓库
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
使用 CMake 编译
在 macOS 上,Metal GPU 加速默认启用,无需额外设置任何编译参数。同时 Accelerate 框架(BLAS 加速)也会自动启用。
# 创建构建目录并编译(Metal 默认启用)
cmake -B build
cmake --build build --config Release -j 8
# -j 8 表示使用 8 个线程并行编译,加快编译速度
# M4 芯片有 10 核 CPU,可以根据需要调整线程数
编译完成后,可执行文件位于 build/bin/ 目录下。主要工具包括:
llama-cli:命令行交互式对话llama-server:启动 HTTP API 服务llama-quantize:模型量化工具llama-convert:模型格式转换工具
验证 Metal GPU 加速
# 查看编译信息,确认 Metal 支持
./build/bin/llama-cli --help | grep metal
# 运行模型时会自动输出 Metal 信息:
# ggml_metal_init: allocating
# ggml_metal_init: found device: Apple M4
# ggml_metal_init: loading library
第三步:获取 GLM-4 GGUF 模型
方式一:下载预量化 GGUF 文件(推荐)
HuggingFace 上有社区已经转换好的 GLM-4 GGUF 模型,可以直接下载使用。推荐以下仓库:
# 安装 huggingface-cli 工具
pip install huggingface-hub
# 下载 GLM-4-9B-Chat Q4_K_M 量化版(推荐,6.3GB)
huggingface-cli download \
bartowski/glm-4-9b-chat-GGUF \
glm-4-9b-chat-Q4_K_M.gguf \
--local-dir ./models
# 或者下载 Q5_K_M 版本(7.1GB,质量更高)
huggingface-cli download \
bartowski/glm-4-9b-chat-GGUF \
glm-4-9b-chat-Q5_K_M.gguf \
--local-dir ./models
# 下载完成后验证文件
ls -lh models/*.gguf
方式二:从原始模型转换并量化
如果你想从 GLM-4 原始权重文件(safetensors 格式)自行转换,可以按以下步骤操作:
# 安装 Python 依赖
pip install -r requirements.txt
# 下载原始模型(约 19GB)
huggingface-cli download THUDM/glm-4-9b-chat --local-dir ./glm-4-original
# 转换为 GGUF 格式(FP16,约 19GB)
python convert_hf_to_gguf.py ./glm-4-original \
--outfile ./models/glm-4-9b-chat-fp16.gguf
# 量化为 Q4_K_M(约 6.3GB)
./build/bin/llama-quantize \
./models/glm-4-9b-chat-fp16.gguf \
./models/glm-4-9b-chat-q4_k_m.gguf \
Q4_K_M
第四步:运行 GLM-4 模型
命令行交互对话
# 基本运行(自动使用 Metal GPU 加速)
./build/bin/llama-cli \
-m ./models/glm-4-9b-chat-Q4_K_M.gguf \
-c 8192 \
-n -1 \
-i \
--color
# 参数说明:
# -m 指定模型文件路径
# -c 8192 上下文窗口大小(tokens)
# -n -1 无限生成(直到模型自行结束)
# -i 交互模式
# --color 彩色输出
带系统提示词的对话
# 使用 GLM-4 的聊天模板
./build/bin/llama-cli \
-m ./models/glm-4-9b-chat-Q4_K_M.gguf \
-c 8192 \
-i \
--color \
-sys "你是一个专业的中文编程助手,请用简洁准确的方式回答问题" \
--chat-template chatglm
单次生成(非交互模式)
# 单次提示生成
./build/bin/llama-cli \
-m ./models/glm-4-9b-chat-Q4_K_M.gguf \
-c 2048 \
-n 512 \
-p "请用 Python 实现一个二分查找算法,并添加详细注释" \
--no-display-prompt
第五步:启动 API 服务
启动 OpenAI 兼容 API
# 启动 HTTP 服务(兼容 OpenAI API 格式)
./build/bin/llama-server \
-m ./models/glm-4-9b-chat-Q4_K_M.gguf \
-c 8192 \
--host 0.0.0.0 \
--port 8080 \
-np 4
# 参数说明:
# --host 0.0.0.0 监听所有网络接口(局域网可访问)
# --port 8080 服务端口
# -np 4 并行处理 4 个请求
测试 API 调用
# 使用 curl 调用 OpenAI 兼容接口
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "glm-4",
"messages": [
{"role": "system", "content": "你是一个专业的AI助手"},
{"role": "user", "content": "解释一下什么是链表数据结构"}
],
"temperature": 0.7,
"max_tokens": 1024
}'
Python SDK 调用
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="not-needed"
)
response = client.chat.completions.create(
model="glm-4",
messages=[
{"role": "user", "content": "写一个 Python 装饰器示例"}
],
temperature=0.7
)
print(response.choices[0].message.content)
第六步:性能调优
关键性能参数
| 参数 | 说明 | 推荐值 |
|---|---|---|
-ngl | GPU 层数(Metal 加速) | 99(全部放 GPU) |
-c | 上下文窗口大小 | 4096~8192 |
-b | 批处理大小 | 512 |
-ub | 物理批处理大小 | 512 |
-t | CPU 线程数 | 4~8 |
--mlock | 锁定模型在内存中(防止交换) | 推荐启用 |
--no-mmap | 禁用内存映射(加载更慢但运行更稳定) | 按需 |
优化运行示例
# 完整优化参数运行
./build/bin/llama-server \
-m ./models/glm-4-9b-chat-Q4_K_M.gguf \
-c 8192 \
-ngl 99 \
-b 512 \
-ub 512 \
-t 6 \
--mlock \
--host 0.0.0.0 \
--port 8080
性能基准测试
# 运行性能基准测试
./build/bin/llama-bench \
-m ./models/glm-4-9b-chat-Q4_K_M.gguf \
-ngl 99 \
-p 512 \
-n 128
# 输出示例(MacBook Air M4 16GB):
# | model | size | params | backend | ngl | test | t/s |
# | ------------------------------ | ---------: | ---------: | ---------- | --: | ---------- | ----: |
# | glm-4-9b-chat-Q4_K_M | 6.30 GiB | 9.00 B | metal | 99 | pp 512 | 120.5 |
# | glm-4-9b-chat-Q4_K_M | 6.30 GiB | 9.00 B | metal | 99 | tg 128 | 42.8 |
其中 pp(prompt processing)表示处理输入的速度,tg(token generation)表示生成输出的速度。42.8 tokens/s 意味着每秒可以生成约 40 个汉字,体验非常流畅。
第七步:后台常驻服务
使用 launchd 创建系统服务
# 创建 launchd 配置文件
cat > ~/Library/LaunchAgents/com.llamacpp.server.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.llamacpp.server</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/llama.cpp/build/bin/llama-server</string>
<string>-m</string>
<string>/path/to/models/glm-4-9b-chat-Q4_K_M.gguf</string>
<string>-c</string>
<string>8192</string>
<string>-ngl</string>
<string>99</string>
<string>--host</string>
<string>0.0.0.0</string>
<string>--port</string>
<string>8080</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/llamacpp.log</string>
<key>StandardErrorPath</key>
<string>/tmp/llamacpp-error.log</string>
</dict>
</plist>
EOF
# 加载服务
launchctl load ~/Library/LaunchAgents/com.llamacpp.server.plist
# 停止服务
launchctl unload ~/Library/LaunchAgents/com.llamacpp.server.plist
常见问题
1. 编译报错:找不到 cmake
# 确保 Homebrew 安装的 cmake 在 PATH 中
echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
# 验证
which cmake
cmake --version
2. 运行时提示 Metal 不可用
# 检查 macOS 版本(需要 macOS 13.0+)
sw_vers
# 确认编译时启用了 Metal
cmake -B build -DGGML_METAL=ON
cmake --build build --config Release -j 8
# 如果仍然不行,检查 Metal 框架是否正常
# 系统报告 -> 图形/显示器 -> Metal
3. 内存不足导致系统卡顿
# 减小上下文窗口
./build/bin/llama-server -m model.gguf -c 2048 -ngl 99
# 限制 CPU 线程数(避免抢占系统资源)
./build/bin/llama-server -m model.gguf -c 4096 -ngl 99 -t 4
# 使用更小的量化版本
# Q3_K_M (5.1GB) 或 Q2_K (4.0GB)
性能对比:Ollama vs llama.cpp
| 对比项 | Ollama | llama.cpp(手动编译) |
|---|---|---|
| 安装难度 | ⭐ 极简 | ⭐⭐⭐ 需编译 |
| 性能 | 优秀 | 极致(可手动调优) |
| 灵活性 | 中等 | 极高 |
| 模型管理 | 内置管理 | 手动管理 |
| API 兼容 | OpenAI 兼容 | OpenAI 兼容 |
| 适合人群 | 普通用户 | 开发者/极客 |
总结
手动编译 llama.cpp 虽然步骤比 Ollama 多,但换来了更精细的控制能力。你可以自由调整 GPU 层数、批处理大小、线程数等参数,榨干 M4 芯片的每一分性能。同时 llama.cpp 的 HTTP 服务兼容 OpenAI API 格式,可以无缝集成到各种应用中。
在系列下一篇中,我们将探索 Apple 官方的 MLX 框架,这是专为 Apple Silicon 设计的机器学习框架,能为 GLM-4 模型提供最原生的 M4 芯片体验。






