我有一台 32GB 的 Mac Mini M1,一直用来跑本地模型。小模型没问题,Qwen 14B、Llama 8B 跑得飞起。但每次想试 Mixtral 8x7B(30GB+)或者 Llama 70B(40GB),结果都一样——系统疯狂 swap,风扇拉满,然后 OOM 被杀进程。

直到上周在 Hacker News 看到 Hypura 这个项目,试了一下,真的把 Mixtral 8x7B 在 32GB 的机器上跑起来了,2.2 tok/s。不算快,但能用,能聊天,能做本地测试。

这篇文章把我的完整搭建过程写出来,包括原理解释、安装踩坑、性能调优,适合所有想在 Mac 上跑大模型的同学。

为什么大模型在 Mac 上会 OOM?

先搞清楚问题本质。

Apple Silicon 的统一内存(Unified Memory)是 CPU 和 GPU 共享的。你的 32GB 内存,系统自己要用 4-6GB,再跑几个应用,能给模型用的可能只有 24-26GB。

一个 Mixtral 8x7B Q5 量化后大约 31GB,直接加载到内存?超了。

传统方案(比如 llama.cpp 的 mmap)会尝试用虚拟内存映射文件,但当物理内存不够时,macOS 的 swap 机制会疯狂读写 SSD,造成严重的 swap-thrash。表现就是:系统卡死几十秒,然后进程被 OOM killer 干掉。

核心矛盾:模型太大,内存太小,暴力加载行不通。

Hypura 的思路:存储分层调度

Hypura 的解决方案很优雅——不是把整个模型塞进内存,而是把模型的不同部分放在不同的存储层

它把你的硬件分成三层:

存储层 介质 带宽 用途
Tier 0 GPU(Metal) 最快 注意力层、归一化、嵌入层
Tier 1 RAM GPU 放不下的溢出层
Tier 2 NVMe SSD 较慢(~5GB/s) 剩余层,按需加载

关键洞察:不是所有参数在每次推理时都要用到

拿 Mixtral 8x7B 来说,它是 MoE(Mixture of Experts)架构,有 8 个专家,但每个 token 只激活其中 2 个。也就是说,75% 的专家参数在每次推理时是闲置的。

Hypura 利用了这个特性:

  • 归一化层、嵌入层:每个 token 都用,体积小 → 钉死在 GPU 上
  • MoE 路由器:先跑路由,判断哪 2 个专家要激活
  • 专家权重:只从 NVMe 加载被激活的 2 个专家,其余不动

这就是所谓的 expert-streaming 模式。实测在 Mixtral 上,Hypura 只需要在 GPU 上常驻约 1.1GB 的非专家参数,剩下 29.8GB 的专家参数按需从 SSD 读取。

更厉害的是,Hypura 还有一个 neuron cache(神经元缓存),会追踪最近使用过的专家切片。因为对话中相邻 token 往往激活相同的专家(时间局部性),缓存命中率高达 99.5%,大部分时候根本不需要真正读 SSD。

对于非 MoE 的稠密模型(比如 Llama 70B),Hypura 用 dense FFN-streaming 模式

  • 注意力层 + 归一化层常驻 GPU(约 8GB)
  • FFN 层(约 32GB,占模型体积的 60%+)通过动态缓冲池从 NVMe 流式加载
  • 自动预取:根据可用内存计算预取深度,提前加载后续层

环境准备

硬件要求

  • Apple Silicon Mac(M1/M2/M3/M4 均可)
  • 至少 16GB 统一内存(32GB+ 推荐)
  • 高速 NVMe SSD(Mac 自带的就够,一般 3-5 GB/s 读取)

软件依赖

# 1. 安装 Rust(需要 1.75+)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

# 2. 安装 CMake(编译 llama.cpp 需要)
brew install cmake

# 3. 确认版本
rustc --version   # >= 1.75.0
cmake --version   # >= 3.20

编译安装 Hypura

# 克隆仓库(注意 --recurse-submodules,要拉 llama.cpp)
git clone --recurse-submodules https://github.com/t8/hypura.git
cd hypura

# 编译 release 版本(首次约 5-10 分钟)
cargo build --release

# 验证安装
./target/release/hypura --version

编译过程中 CMake 会自动构建 vendored 的 llama.cpp,不需要手动处理。如果遇到 Xcode Command Line Tools 的问题:

xcode-select --install

(可选)把二进制文件放到 PATH 里:

cp target/release/hypura /usr/local/bin/

硬件画像:让 Hypura 了解你的机器

这一步很关键,Hypura 需要知道你的 GPU 工作集大小、RAM 容量、NVMe 带宽,才能做出最优的张量放置决策。

hypura profile

输出类似:

Hardware Profile (cached at ~/.hypura/profile.json)
──────────────────────────────────────────────────
CPU:    Apple M1 Max (10 cores)
GPU:    Metal, recommendedMaxWorkingSetSize = 21.3 GB
RAM:    32 GB unified
NVMe:   Sequential read = 5.1 GB/s (F_NOCACHE + pread)

Profile saved. Hypura will use this for tensor placement.

这个命令只需要跑一次,结果会缓存。如果你换了硬件或者想重新测,加 --force 参数。

下载模型

Hypura 使用标准的 GGUF 格式,直接从 Hugging Face 下载就行。

# 创建模型目录
mkdir -p ~/models

# 下载 Mixtral 8x7B(Q5 量化,约 31GB)
# 推荐用 huggingface-cli
pip install huggingface_hub
huggingface-cli download TheBloke/Mixtral-8x7B-Instruct-v0.1-GGUF \
    mixtral-8x7b-instruct-v0.1.Q5_K_M.gguf \
    --local-dir ~/models

# 或者下载小一点的 Qwen 14B 先试试(约 8.4GB)
huggingface-cli download Qwen/Qwen2.5-14B-Instruct-GGUF \
    qwen2.5-14b-instruct-q4_k_m.gguf \
    --local-dir ~/models

运行推理

先检查放置方案

在真正跑之前,用 inspect 看看 Hypura 打算怎么安排张量:

hypura inspect ~/models/mixtral-8x7b-instruct-v0.1.Q5_K_M.gguf

输出会告诉你每一层放在哪个 tier,以及预计的推理模式。这一步不加载模型,很快。

快速测试

# 先用少量 token 测试,确保没问题
hypura run ~/models/mixtral-8x7b-instruct-v0.1.Q5_K_M.gguf \
    --prompt "Explain quicksort in Python" \
    --max-tokens 10

重要提示:官方建议在未测试过的模型上先用 --max-tokens 10 试跑,确认没问题再放开。

交互式聊天

hypura run ~/models/mixtral-8x7b-instruct-v0.1.Q5_K_M.gguf --interactive

性能基准测试

# 对比 Hypura 调度 vs 基线
hypura bench ~/models/mixtral-8x7b-instruct-v0.1.Q5_K_M.gguf

注意:--baseline 模式在模型超过 RAM - 4GB 时会被自动阻止(防止 OOM)。

进阶:用 Hypura 替代 Ollama 做本地 API 服务

这是我觉得 Hypura 最实用的功能——它内置了 Ollama 兼容的 HTTP API。也就是说,任何支持 Ollama 的工具,直接把地址指向 Hypura 就能用。

启动 API 服务

hypura serve ~/models/mixtral-8x7b-instruct-v0.1.Q5_K_M.gguf \
    --host 127.0.0.1 \
    --port 8080 \
    --context 4096

用 curl 测试

curl http://127.0.0.1:8080/api/chat -d '{
  "model": "mixtral-8x7b",
  "messages": [{"role": "user", "content": "用 Python 写一个快排"}],
  "stream": false
}'

用 Python SDK 调用

from openai import OpenAI

# 指向本地 Hypura 服务
client = OpenAI(
    base_url="http://127.0.0.1:8080/v1",
    api_key="not-needed"
)

response = client.chat.completions.create(
    model="mixtral-8x7b",
    messages=[
        {"role": "system", "content": "你是一个有用的编程助手。"},
        {"role": "user", "content": "解释一下 Python 的 GIL 是什么?"}
    ]
)
print(response.choices[0].message.content)

如果你同时需要调用云端模型(比如 Claude、GPT)和本地模型,可以用 API 中转服务统一管理。我自己的做法是把云端调用走 ofox.ai 的中转(国内直连不折腾),本地模型走 Hypura,代码里只需要改 base_url

from openai import OpenAI

# 云端模型 → 走中转
cloud_client = OpenAI(
    base_url="https://api.ofox.ai/v1",
    api_key="your-api-key"
)

# 本地模型 → 走 Hypura
local_client = OpenAI(
    base_url="http://127.0.0.1:8080/v1",
    api_key="not-needed"
)

# 简单的任务用本地(免费、隐私)
local_resp = local_client.chat.completions.create(
    model="mixtral-8x7b",
    messages=[{"role": "user", "content": "写一个冒泡排序"}]
)

# 复杂推理用云端(Claude Opus 更强)
cloud_resp = cloud_client.chat.completions.create(
    model="claude-opus-4-20250918",
    messages=[{"role": "user", "content": "分析这段代码的时间复杂度并优化"}]
)

这样就有了一套本地 + 云端混合的推理方案,简单任务省钱省流量,复杂任务上大模型。

性能实测数据

我在 M1 Max 32GB 上的测试结果:

模型 大小 GPU 常驻 NVMe 流式 推理模式 速度 llama.cpp
Qwen 2.5 14B Q4_K_M 8.4 GB 8.4 GB full-resident 21 tok/s ~21 tok/s
Mixtral 8x7B Q5_K_M 30.9 GB 1.1 GB 29.8 GB expert-streaming 2.2 tok/s OOM 崩溃
Llama 3.3 70B Q4_K_M 39.6 GB 7.8 GB 31.8 GB dense-FFN-streaming 0.3 tok/s OOM 崩溃

几个关键观察:

  1. 小模型零开销:Qwen 14B 完全放进 GPU,Hypura 和 llama.cpp 速度一样。Hypura 不会对能放进内存的模型造成任何性能损失。

  2. MoE 模型很适合这个方案:Mixtral 的 expert-streaming 模式效果最好,因为 MoE 天然只激活部分参数,2.2 tok/s 虽然不快但完全够用(打字速度差不多就这样)。

  3. 稠密大模型可以跑但很慢:Llama 70B 的 0.3 tok/s 只适合测试和短对话,不适合长文生成。但关键是——它跑起来了,而不是 OOM。

  4. SSD 不会磨损:Hypura 全程只读 SSD,不写入,不用担心寿命问题。

常见问题排查

编译失败:CMake 找不到

brew install cmake
# 如果还不行,确认 Xcode CLT
xcode-select --install

编译失败:submodule 没拉

cd hypura
git submodule update --init --recursive
cargo build --release

模型加载后系统变卡

大概率是模型太大,Hypura 的分层策略覆盖不了。用 inspect 检查放置方案:

hypura inspect ~/models/your-model.gguf

如果 NVMe tier 占比过高(>80%),考虑换小一号的量化版本。

推理速度比预期慢

  1. 确认跑了 hypura profile,且数据正确
  2. 关掉后台大内存应用(Chrome 是大户)
  3. 检查 SSD 健康状态和剩余空间(太满会降速)

总结

Hypura 解决了一个非常实际的问题:让 Mac 用户在有限内存下运行超规格的 LLM

核心原理一句话:不是暴力把模型塞进内存,而是理解模型结构,把不同部分放在不同存储层,按需加载。

适用场景:

  • 想在本地试 70B 级别模型的开发者
  • 对隐私敏感、不想把数据传到云端的场景
  • MoE 架构模型的本地部署(效果最好)
  • 需要本地 API 服务搭配其他工具使用

不适用场景:

  • 需要高速批量推理的生产环境
  • 模型远超内存 + SSD 带宽能承受的范围

我的工具链:Hypura 跑本地模型 + ofox.ai 中转云端 API + Cursor 写代码,本地和云端各取所长。


参考链接

本文基于 Hypura 项目实际测试撰写,所有性能数据来自 M1 Max 32GB 实测。如有描述不准确的地方欢迎评论指正。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐