同一个 Qwen3.5-2B,同一个 MacBook Neo,我把 Ollama、llama.cpp 和 MLX 都跑了一遍。 结果 MLX 成了黑马——比 Ollama 快 35%,比 llama.cpp 快 48%。
一、缘起
事情要从我买了 MacBook Neo 说起。
之前我一直在手机上折腾大模型,K30 Pro 上 CPU 优化到 13 t/s,vivo X100 Pro 上 GPU 跑到 17 t/s。换到 MacBook Neo 之后,自然想试试桌面端的体验。
最开始我在MacBook Neo用的是 llama.cpp,从源码编译好,跑 llama-bench——51 tok/s。后来装上 Ollama,发现同一个模型竟然快了 40%。我震惊之余写了一篇文章分享了这个发现。
但总觉得有点不踏实——那只是 0.5B 的小模型,不具代表性。
于是我又下了一台 x86 独显机器,用 Qwen3.5-2B 在 CUDA 上跑了一圈,拿了 baseline 数据。然后回到 MacBook Neo,用同款 2B 模型,把三个引擎都测了一遍。
结果让我有点意外。
二、跑分
2.1 测试条件
| 项目 | 值 |
|---|---|
| 设备 | MacBook Neo (A18 Pro, 8GB) |
| 系统 | macOS 26.5 |
| 模型 | Qwen3.5-2B Q4(同款模型跨工具对比) |
| Ollama | v0.31.1 + Metal + Flash Attention |
| llama.cpp | master 自编译 + Metal GPU |
| MLX | mlx 0.32.0 + mlx-lm 0.31.3 |
2.2 三工具对比
| 工具 | 生成速度 | 首 token 延迟 | 备注 |
|---|---|---|---|
| llama.cpp | 30 tok/s | 中 | 上次测试 |
| Ollama | 33 tok/s | 低 | 上次测试 |
| MLX 🏆 | 44 tok/s | 中 | 本次测试 |
| llama.cpp 默认fp16 | 33.4 tok/s | 中 | 本次测试 |
| llama.cpp + q8_0 KV Cache | 33.2 tok/s | 中 | 本次测试 |
MLX 跑到了 44 tok/s,最快。其实上次文章发出去之后,有读者教我:「llama-cpp将kv量化也就是两个参数,-ctk q8_0 -ctv q8_0,加上再去试试看」,所以我这次重新测试了llama调参数再跑。
2.3 x86 GPU 参考(CUDA)
作为参考,我在一台搭载 RTX 1650(4GB)的机器上也跑了同一个模型。结果如下:
| 设备 | 引擎 | 生成速度 |
|---|---|---|
| x86(16G内存) + RTX 1650 | llama.cpp (CUDA) | ~55 tok/s |
| MacBook Neo (A18 Pro) | MLX 🏆 | 44 tok/s |
| MacBook Neo (A18 Pro) | Ollama (Metal) | 33 tok/s |
| MacBook Neo (A18 Pro) | llama.cpp (Metal) | 33.4 tok/s |
x86(16G内存) + RTX 1650 虽然 CUDA 生态未起作用,但是凭借 16G 内存大小,还是会对小内存进行碾压。但考虑到 MacBook Neo 只有 8GB 统一内存,而 x86 有 16G 内存和 4GB 专用显存,44 tok/s 的成绩其实相当亮眼。
三、部署 MLX 踩过的坑
说实话,MLX 虽然跑得最快,但部署过程并不顺利。这里记录一下我踩过的坑,给后来人省点时间。
3.1 坑一:装错了框架
Qwen3.5 是一个支持视觉的多模态模型。如果按照默认的方法装纯文本框架 mlx-lm,连模型都加载不了。必须用 mlx-vlm。
pip install mlx-vlm torch torchvision
3.2 坑二:Model type qwen3_5 not supported
如果你直接 pip install mlx-vlm 然后跑模型,大概率会遇到这个报错。
原因:Qwen3.5 架构太新了,官方稳定版还没来得及合并支持。
解法:PyPI 上的最新版(0.6.4)已经修复了这个问题,升级到最新版即可:
pip install --upgrade mlx-vlm
3.3 坑三:Python 版本太老
Mac 自带的 Python 3.9 太老了,很多依赖装不上。建议用 Homebrew 装 Python 3.12+ 并创建虚拟环境:
brew install python@3.12
python3.12 -m venv mlx_env
source mlx_env/bin/activate
3.4 坑四:API 服务启动不带 --model 参数
mlx_vlm 的 API Server 采用动态加载机制——它启动时只是个空壳,收到带模型名字的请求时才会去加载模型。如果启动命令里硬塞 --model 参数,会直接报错退出。
正确的启动方式:
python -m mlx_vlm.server --port 8080 --trust-remote-code
然后在 API 请求的 model 字段里指定模型名即可。
3.5 坑五:模型提前下载,防止超时
第一次请求时,服务端会从 Hugging Face 下载模型,这通常需要几十秒到几分钟。如果客户端(比如 OpenClaw)有超时限制,就会报错。建议先手动下载:
export HF_ENDPOINT=https://hf-mirror.com
python -c "from mlx_vlm import load; load('mlx-community/Qwen3.5-2B-MLX-4bit')"
四、为什么 MLX 更快?
4.1 原生 Metal,不是移植
MLX 是苹果官方为 Apple Silicon 打造的机器学习框架。和 llama.cpp 的 Metal 后端不同,MLX 不是「把模型用 Metal 跑起来」——它一开始就是用 Metal 写的,算子和内存调度全是手写的 Metal Shading Language。
llama.cpp 的 Metal 支持则是通过 ggml_metal 自动生成的通用代码跑在 Metal 上,兼容性没问题,但每个算子的效率比不上手写版本。
4.2 统一内存的极致利用
Apple Silicon 的 CPU 和 GPU 共享同一块物理内存。MLX 充分利用了这个特性,数据在 GPU 和 CPU 之间不需要任何拷贝。而 llama.cpp 和 Ollama 虽然也能用 Metal,但底层仍然保留了一些「GPU 显存」的思维惯性,有额外的内存管理开销。
4.3 框架专注度
llama.cpp 要同时支持 CUDA、Vulkan、Metal、SYCL、CPU 等七八个后端,代码库庞大,每个后端的优化深度有限。Ollama 底层也是 llama.cpp,优化程度类似。
MLX 只做 Apple Silicon,后端就一个 Metal,所有精力都花在一个地方。专注带来的效率差距,在跑分上体现得很明显。
五、怎么选?
测完之后,我对这三个工具的定位有了清晰的认识:
| 工具 | 速度 | 上手难度 | 最适合 |
|---|---|---|---|
| Ollama | 快 | ★☆☆ | 15 分钟跑起来,日常对话首选 |
| llama.cpp | 中 | ★★★ | 参数可控,开发调试灵活 |
| MLX | 最快 🏆 | ★★☆ | 追求极致性能,喜欢折腾 |
- 如果你想最快跑起来,选 Ollama。
- 如果你想跑得最快,选 MLX。
- 如果你想调得最细,选 llama.cpp。
三个工具各有定位,不冲突。
六、后记
这次从手机折腾到 MacBook,从 llama.cpp 试到 MLX,最大的感受是:
-
Apple Silicon + MLX 的组合,是真的能打。 8GB 内存的入门级 MacBook,2B 模型跑到 44 tok/s,之前我是不敢想的。
-
不要默认「大家都在用的就是最快的」。 MLX 的用户量远不如 Ollama,但在 macOS 上确实更快。值得花点时间试试。
-
x86 独显仍然是速度标杆。 有 16G 内存的话,即使不使用 CUDA 的推理速度还是最快的。但 Mac 胜在便携和安静——不插电、不发热、不吵,随时随地跑模型,这种体验 x86 暂时给不了。
最后附上环境配置:
MacBook Neo (A18 Pro, 8GB) + macOS 26.5
模型: Qwen3.5-2B Q4
Ollama: v0.31.1 + Metal + Flash Attention
llama.cpp: master 自编译 + Metal GPU
MLX: mlx 0.32.0 + mlx-lm 0.31.3
x86 参考: 16G 内存 + RTX 1650 (4GB) + llama.cpp
如果你也在本地跑大模型,建议三个工具都试一遍——同一个模型在不同引擎上的速度,可能完全不同。