← 返回文章列表

MacBook Neo使用MLX再测大模型

同一个 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(同款模型跨工具对比)
Ollamav0.31.1 + Metal + Flash Attention
llama.cppmaster 自编译 + Metal GPU
MLXmlx 0.32.0 + mlx-lm 0.31.3

2.2 三工具对比

工具生成速度首 token 延迟备注
llama.cpp30 tok/s上次测试
Ollama33 tok/s上次测试
MLX 🏆44 tok/s本次测试
llama.cpp 默认fp1633.4 tok/s本次测试
llama.cpp + q8_0 KV Cache33.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 1650llama.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,最大的感受是:

  1. Apple Silicon + MLX 的组合,是真的能打。 8GB 内存的入门级 MacBook,2B 模型跑到 44 tok/s,之前我是不敢想的。

  2. 不要默认「大家都在用的就是最快的」。 MLX 的用户量远不如 Ollama,但在 macOS 上确实更快。值得花点时间试试。

  3. 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

如果你也在本地跑大模型,建议三个工具都试一遍——同一个模型在不同引擎上的速度,可能完全不同。