精选理由
这是个在 M1 Max 上跑 2.8T MoE 的工程 hack,把不可能变成可能,虽然慢得只有聊天室节奏,但玩法足够硬核,玩硬件的看完会想开 issue 贡献数据。
AI 摘要
Deltafin 项目成功在 64 GB M1 Max 上运行了 2.8T 参数的 MoE 模型 Kimi K3,当前中位推理速度为 0.0687 token/s(14.6 秒/token)。完整安装需约 1.7 TB 本地磁盘,流式模式仅需 215 GB 但推理速度降至 3 分钟以上/token。项目提供 OpenAI 兼容 API 服务器,支持聊天和代码补全,但建议客户端超时设为小时级别。
正文 · AI 翻译
在单台 Apple Silicon Mac 上运行 Kimi K3(2.8T 参数)的实验
Deltafin 是一个小型研究项目,它运行着一个远超所在机器规模的混合专家模型。目前,在我们 64 GB 的 M1 Max 上,精确路径中位数为 0.0687 token/秒(14.6 秒/token)。迄今为止,所有已发布的运行都来自那台第一代机器——而非更新的 Max 或 Ultra——并且,基于能力限制的路径加上自动内存预算管理,使得同一引擎能够延续到更新的 Apple Silicon Mac 上。
安装
三条命令,然后你就可以开始生成了。唯一需要真正做决定的是第三步。
# 1. environment (Python 3.12+, and Xcode CLT for clang) python3 -m venv venv ./venv/bin/pip install torch numpy safetensors tiktoken ml_dtypes blobfile \ "transformers==4.56.2" einops tokenizers
# 2. build the fused MXFP4 kernel clang -O3 -mcpu=native -shared -DNO_MAIN -o tools/libmxfp4gemv.dylib tools/fused_gemv.c
# 3. download the model (see the two modes below) ./venv/bin/python tools/setup_k3.py --full
两种模式
--full(推荐) --stream
所需磁盘空间 约 1.7 TB 约 215 GB
下载时间 5–10 小时,可断点续传 约 30 分钟
后续速度 在我们的 M1 Max 上,中位数为 14.6 秒/token 对于任何尚未缓存的内容,约 3 分钟以上/token
推理时的网络需求 无 持续连接
每个 token 需要读取 16 个专家 × 92 层 = 25.8 GB 的专家数据。从本地磁盘读取大约需要 4 秒;通过网络则需要几分钟。这一事实就是两列之间全部差异所在。
运行 `setup_k3.py` 时不加任何标志,当磁盘空间允许时它会选择 `--full` 模式,否则会回退到流式模式,并准确告知你需要释放多少空间。
从流式模式开始,后续升级
流式模式是尝试 Deltafin 的好方法,无需预先投入 1.7 TB 的磁盘空间。无论何时你想要更快的速度,一条命令即可完成升级——无需重新安装,无需重新配置,并且它会利用所有已缓存的内容:
./venv/bin/python tools/fetch_experts_all.py # resumable, run anytime ./venv/bin/python tools/fetch_experts_all.py --dry-run # just show the numbers ./venv/bin/python tools/fetch_experts_all.py --layers 1-40 # partial is fine too
对于流式安装,空闲时的预热器可以根据记录的路由器轨迹来识别缺失的专家。其默认是一个只读方案;网络获取是显式进行的,并且它可以原子地将旧的 `.npz` 条目转换为原始的快速格式:
./venv/bin/python tools/warm_expert_cache.py ./venv/bin/python tools/warm_expert_cache.py --convert-npz --fetch 128
每当 Deltafin 仍处于流式模式时,它会在启动时打印一条提醒——无论是对于 CLI 还是 API 服务器——显示当前本地已缓存的专家池比例以及完成全部缓存所需的代价。
可选:int8 脊柱网络
将非专家权重的每 token I/O 减半,在我们的检查中未发现明显的质量变化。只需几分钟:
./venv/bin/python tools/convert_spine_int8.py
使用方式
# ask a question; generates until the model finishes its answer ./venv/bin/python tools/kimi_run.py --chat --prompt "What are the three largest moons of Saturn?"
# raw completion (no chat template); runs until you press Ctrl-C, or cap it ./venv/bin/python tools/kimi_run.py --prompt "The capital of France is" --max-new 16
Token 会边生成边打印,因此你始终能看到文本实时呈现。按 Ctrl-C 可在任意位置干净地中断并输出已生成的结果;`--max-new N` 参数可限制生成长度。一个诚实的提醒:K3 在回答前会进行思考,大约每分钟生成 4.1 个 token,因此一次完整的聊天回答可能需要一段时间——观看其流式输出本身就是体验的一部分。
设置 `K3_TRACE=buffered` 可将路由选择记录到 `router_trace.jsonl` 文件中,供离线分析使用。性能测试运行时请关闭追踪功能。
兼容 OpenAI 的服务器
Deltafin 可提供标准的 OpenAI API 服务,因此聊天界面、openai SDK 以及编程智能体只需修改基础 URL 即可使用:
./venv/bin/python tools/serve_openai.py --port 8000
curl http://127.0.0.1:8000/v1/chat/completions -H 'Content-Type: application/json' \ -d '{"model": "deltafin-kimi-k3", "messages": [{"role": "user", "content": "Hello!"}]}'
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8000/v1", api_key="none") r = client.chat.completions.create( model="deltafin-kimi-k3", messages=[{"role": "user", "content": "Hello!"}])
print(r.choices[0].message.content) # the answer print(r.choices[0].message.reasoning_content) # K3's thinking, when present
已实现 `/v1/chat/completions`、`/v1/completions` 和 `/v1/models` 接口,流式传输(`"stream": true`)功能也可正常工作。大多数读取 `OPENAI_BASE_URL` 和 `OPENAI_API_KEY` 的工具,只需将地址指向该服务器即可运行。
在将任何自动化工具指向该服务器之前,请先阅读以下注意事项:
时间。回答会在准备好时返回——请将客户端的超时时间设置为小时级别,而非秒级。省略 `max_tokens` 参数可让模型完成整个回答(推荐);原始补全(raw completions)默认不会自行终止,其默认值为 256。运维人员可通过 `K3_SERVER_MAX_TOKENS` 设置硬性上限。
流式安装在此处的速度要慢得多。一个聊天模板提示词至少需要 60 个 token,且预填充阶段会触及每层的多个专家,因此在缓存部分填充的情况下,一次聊天请求可能需要数小时来获取结果。使用完整安装时,则只是正常的(慢速)推理。当处于流式模式时,服务器会在启动时打印一条警告信息。
仅支持贪婪解码。`temperature` 和 `top_p` 参数虽被接收但会被忽略,且一次只处理一个请求(第二个并发请求将收到 429 状态码)。
智能体目前仅作为探索性功能,并非正式工作流程。编程助手在理论上可以工作,但其冗长的系统提示词会导致预填充成本高昂。
配置
所有功能无需配置即可运行:Deltafin 会在有 GPU 时自动选择 GPU,在 int8 骨干网络已构建时自动选择该网络,并在启动时告知其选择结果。以下变量可用于覆盖默认设置:
变量 默认值 含义
K3_DEV auto 可用时使用 GPU(mps),否则使用 CPU
K3_SPINE auto 已构建时使用 int8(推荐),否则使用 bf16
K3_INT8_LM_HEAD 1 在支持时使用打包的 MPS int8 输出头;精确的密集回退方案仍然可用
K3_SPEC 1 n-gram 推测(无损)
K3_TEMPLATES 1 模板层缓冲区复用
K3_PRELOAD / K3_PREFETCH 1 后台层加载 / 专家预取
K3_METAL_POSITION_BATCH 0 精确的主动启用 T>1 位置主序 Metal MoE;实测接受推测通过率提升 +2.0%,需按每台 Mac 重新调优
K3_MOE_TOP_K 16 明确的质量/速度调节旋钮;减少路由专家数可降低专家数据量并可能改变输出
K3_CPU_MOE_BATCH 自动 精确的持久化 CPU MXFP4 工作线程环;填充计数器在八线程下实测提升 +3.6%
K3_ASYNC_CACHE_WRITE 0 主动启用的缓存未命中写入重叠;K3_CACHE_WRITE_QUEUE(4)限制未完成缓冲区数量,K3_CACHE_WRITE_WORKERS(1)可按每台 Mac 重新调优
K3_APPROX 0 fp16 数值计算;在接近平局时不可复现
K3_RAM_GB / K3_PIN_LAYERS 自动 覆盖 RAM 预算
K3_PROFILE 0 每次推理的逐阶段计时
K3_TRACE 关闭 缓冲写入:每次推理一个路由器追踪块;立即同步写入每一层
DELTAFIN_ROOT 仓库根目录 缓存和权重存放的位置
K3_HF_HOST / K3_HF_PATH Hugging Face 将专家获取指向镜像
K3_SERVER_MAX_TOKENS 无限制 可选的服务器生成硬上限
K3_RESPONSE_MEMO_ENTRIES 32 精确的进程内重放缓存,用于相同的确定性 API 请求;设为 0 则禁用
系统要求
一台 Apple Silicon Mac。所有已发布的数据均来自同一台初代 M1 Max(64 GB)——这是迄今为止唯一经过基准测试的 Mac。更多 RAM 会被自动利用(128 GB 的机器可固定数倍于当前模型的层数),而更新的芯片能带来更高的内存带宽、更多的 GPU 资源和更快的存储。详见《为什么更新的 Mac 应该更快》。
Xcode 命令行工具,用于 clang(xcode-select --install)。
Python 3.12 或更新版本。
磁盘空间:完整安装约需 1.7 TB,流式模式约需 215 GB(详见安装说明)。
可访问 Hugging Face 的网络连接。
工作原理
K3 的权重总计约 1.56 TB,超过了这台机器的可用磁盘空间,更不用说 RAM 了。然而,本地推理之所以仍然可行,关键在于混合专家模型每个 token 只触及自身的一小部分。
常驻主干(约 114 GB:注意力层、共享专家、潜在投影、嵌入向量)一次性下载完成,每个 token 从本地 NVMe 逐层读取,量化为 int8 后在 GPU 上计算。
82,432 个路由专家(约 1.45 TB)。对于每个 token,K3 的路由器为每层选取 16 个专家,并且只读取这些专家。如果条件允许,建议在本地全部安装;否则,Deltafin 会按需从 Hugging Face 获取它们——每个专家一个 HTTP 范围请求——存入不断增长的磁盘缓存中。
前向传播运行的是 Moonshot 自身的建模代码,未经修改。一个纯 PyTorch 的小型垫片替代了其所需的仅支持 CUDA 的 fla 内核。
flowchart LR subgraph HF["Hugging Face CDN"] W[("96 safetensors shards<br/>1.56 TB · MXFP4")] end subgraph MAC["MacBook (M1 Max, 64 GB)"] subgraph DISK["NVMe"] SP[("resident spine<br/>114 GB bf16 → 60 GB int8")] EC[("expert cache<br/>raw shard spans")] end subgraph TOK["per token"] R{"router<br/>top-16 of 896<br/>× 92 layers"} L["93 decoder layers<br/>2 shared GPU templates"] K["fused MXFP4 GEMV<br/>NEON"] end end W -- "one range request<br/>per missing expert" --> EC SP -- "double-buffered<br/>layer loader" --> L EC -- "mmap" --> K R -- "selected experts" --> K K --> L L -- "logits" --> R
预期表现
以下所有当前数据均在一台 M1 Max(10 核 CPU、32 核 GPU、64 GB 内存、内置 NVMe)上测得,模型完整安装在本地,采用 int8 驻留权重和输出头、Metal MoE、精确 fp32 数值计算、贪婪解码,并禁用了追踪功能。
当前列汇集了来自平衡的 ABBA/BAAB 测试序列的六次精确全模型运行结果。每次运行使用五个 token 的提示词 The capital of France is,验证了三个 token 的补全结果 Paris. The,并在报告稳定吞吐量之前丢弃了第一个解码步骤。数值为中位数;范围显示了即使在同一台空闲机器上,这个 I/O 密集型工作负载的波动幅度。
指标 首个可用版本 当前 M1 Max 基准测试 变化
预填充 / 首个 token(5 token 提示词) 2,429 秒 28.0 秒中位数(24.9–37.9 秒) 约 87 倍
稳定解码,专家本地化 约 20 分钟/token 0.0687 token/秒(14.6 秒/token);运行范围 0.0503–0.0779 token/秒 约 82 倍
精确的三 token 生成,模型时间 — 56.5 秒中位数 —
同次运行的新进程墙钟时间 — 64.1 秒中位数 —
解码,专家流式传输 约 20 分钟/token 约 3 分钟/token 受网络限制
这就是“不起眼的 M1”的结果:一台老化的第一代 M1 Max,而非更新的 Max 或 Ultra。这是一个保守的参考点,并非跨 Mac 的基准测试。我们预计更新、带宽更高、内存更大的系统表现会更好,但在有人测量出这些数据之前,我们会单独标注那些数值。
近期精确路径的改进
以下最新的测量结果是在同一台 M1 Max 上进行的平衡 A/B 测试。每次全模型运行都检查了 token 预言机。
变化 测量结果 发布时的行为
打包的 MPS int8 输出头 稳定解码中位数提升 +17.3%,预填充提升 +23.1%,墙钟吞吐量提升 +26.8%;驻留输出头存储从 4.7 GB 降至 1.17 GB 在算子与 int8 权重均可用时启用,并带有异常保护的密集回退机制。
仅作参考的推测性快照。 0.001 毫秒而非 3.56 毫秒,且无需约 475 MB 的状态克隆。 默认启用;重放与部分接受测试可保留精确的未来序列。
面向已接受草稿的按位置主序 Metal MoE。 在真实 T=2 层上提升 +4.7%,全模型吞吐量汇总提升 +2.0%。 通过 `K3_METAL_POSITION_BATCH=1` 精确选择加入,待按每台 Mac 进行调优。
128 字节对齐的 CPU 工作线程计数器。 四线程时提升 +0.2%,八线程时提升 +3.6%。 在持久化 CPU 回退中自动生效。
中位数约为每分钟 4.1 个 token。一个典型的 M1 Max 性能画像主要由以下部分组成:
等待驻留主干读取(53 GB) 约 5 秒
读取每层选定的 16 个专家(25.8 GB) 约 4.3 秒
应用主干(传输 + 反量化) 约 3 秒
注意力机制与归一化(93 层) 约 2 秒
MoE 专家矩阵乘法 约 1 秒
解码阶段现在受限于驻留主干的磁盘带宽。这 53 GB 数据在每个 token 生成时都会被重新读取,而在此访问模式所能维持的约 7 GB/s 速率下,这大约占用了 14.6 秒中位数中的 7.5 秒——除非拥有更多 RAM(足以容纳主干而不挤占专家读取所需的页缓存),或者采用更小的主干,否则无法避免。
为何新款 Mac 应该更快
上述每一行都受限于 Apple Silicon 各代芯片间变化的硬件。M1 的结果并未完全阻断任何路径,但这里测量到了若干回退值;新款机器应根据自身的能力、运行时环境、内存和存储特征重新调优这些参数:
内存带宽。M1 Max 为 400 GB/s。M3/M4 Max 显著更高,而 Ultra 型号则大致翻倍——这直接影响主干加载和专家矩阵乘法。
GPU。更多核心能以更快速度执行相同的 Metal 内核;反量化着色器和注意力路径均随核心数扩展。
SSD。专家读取是占比最大的单一环节,其速度取决于内置硬盘的性能。后续 Mac 机型配备了更快的 NVMe。
内存。这是最重要的因素。53GB 的主干模型无法与其它所有内容一起放入一台 64GB 的机器中,因此每生成一个 token 都需要从磁盘重新读取——这大约占总耗时的一半。在 128GB 的机器上,它可以直接留在页面缓存中,这部分开销基本消失。Deltafin 也会自动将更多模型固定在那里,无需任何标志位。
运行时选择基于 Metal 特性族和算子能力检查,而非芯片名称字符串。这使得更新的系列(包括 M5)能够执行 M1 无法运行的路径,同时每个可选的本地路径都保留了精确的回退方案。
我们仅在这台 M1 Max 上进行了基准测试。如果你在 M3、M4 或 M5、Ultra 芯片,或者 128GB 及以上内存的机器上尝试,我们非常希望看到你的数据——请提交一个 issue,附上 `K3_PROFILE=1` 的输出和你的芯片型号。
当 n-gram 推测解码接受一个草稿时,一次前向传播会输出两个 token,因此重复文本的运行速度会成比例地加快。推测解码是无损的:被接受的草稿会精确复现参考序列,而被拒绝的草稿则会逐比特恢复模型状态。
两行解码结果之间的差距,正是完整安装(见上文)的全部意义所在:当专家模型在本地时,每个提示词都以第一行的速度运行,而不仅仅是那些专家恰好被缓存的提示词。
输出是贪婪且可复现的:相同的提示词每次运行都会产生相同的 token。
法国的首都是 → 巴黎。埃菲尔铁塔位于巴黎。卢浮宫博物馆也在巴黎。卢浮宫有……
需要明确其局限性:这是一个研究原型,而非实用的聊天配置。14.6 秒的中位数 token 生成速度距离交互式体验还很遥远,且长提示词成本高昂,因为预填充阶段会触及许多专家模型。我们认为它主要作为存在性证明和流式推理技术的测试平台而有趣。
技术方法
以下每种技术在保留之前,都已在真实权重上进行了测量。这些技术本身大多并非新颖;其中大部分是将下文致谢项目中提出的思路适配到 K3 的特定形态上。
输入/输出与流式处理
合并专家数据获取。每个专家的六个张量在分片文件中恰好是连续的(我们检查了全部 82,432 个分片),因此整个专家只需通过少量保持连接的连接池发起一次 17.55 MB 的范围请求。实测速度比逐个获取张量快约 6.4 倍。
原始字节磁盘缓存。缓存文件直接存储分片的原始字节——无容器格式,无解析过程。
并行专家读取。一个层中的 16 个选定专家由线程池使用带 `F_NOCACHE` 标志的 `pread` 系统调用同时读取,而非在内核计算时逐页按需缺页中断。实测冷启动数据:缺页中断方式为 0.87 GB/s,而读取方式为 6.85 GB/s。这使读取路径上每个 token 的处理时间从 40 秒降至 4.3 秒,并且 `F_NOCACHE` 能防止每 token 25 GB 的专家数据流量驱逐主干网络所需的页缓存。
双层缓冲加载。当前层计算时,工作线程同时读取下一层的主干数据。
前序 token 预取。在去重后的保留测试集上,连续 token 约有 31% 的专家选择会重复,因此每个 token 的专家集合会在后台为下一个 token 预先获取。
计算
融合 MXFP4 反量化与 GEMV 运算(`tools/fused_gemv.c`)——一个 NEON 内核,通过 16 条目查表一次性完成反量化与乘法,其中 e8m0 缩放因子以整数运算形式应用于 fp32 指数。该实现与参考实现逐位匹配,取代了原先慢得多的“先反量化再矩阵乘”路径。Metal 版本已作为验证原型存在。
模板层缓冲区复用。全部 69 个 KDA 层共享一组张量形状,全部 24 个 MLA 层共享另一组,因此两个持久驻留 GPU 的“模板”层可通过 `copy_()` 操作接收各层的权重。这避免了性能分析显示占每 token 处理时间很大比例的内存分配器开销。
int8 驻留主干网络。将每 token 的驻留 I/O 量减半。在我们的检查中,前 5 个候选下一 token 的顺序保持不变,最高 logit 值仅变动 0.07%。
自定义 Metal 反量化内核。加载主干层的大部分时间都花在行广播乘法上,MPS 对此操作的运行速度为 43 GB/s,而相同字节的纯拷贝速度可达 334 GB/s。一个融合了 int8→fp32 转换、行缩放和拷贝操作的简短 compile_shader 内核,速度达到了 297 GB/s;通过使用持久化暂存缓冲区并将传输操作从调度之间提升出来,每层加载时间从 118 毫秒降至 21 毫秒。逐位精确:每个张量上的 max|diff| = 0。
打包的 int8 输出头。内置的 MPS 仅权重量化矩阵乘法直接使用现有的行 int8 检查点,避免了 4.7 GB 的 fp32 头及其反量化操作。能力检查和一个捕获到的密集回退机制,确保了在多个 PyTorch 版本和 Apple GPU 系列上的兼容性。
纯 PyTorch KDA 适配层(tools/fla/)—— Kimi Delta Attention 的循环、短卷积和门控归一化,从 fla-core 的语义移植而来。分块执行和逐步执行的结果差异约为 1e-9。在解码阶段,循环在 CPU 上运行,其小状态比在 GPU 上执行一系列调度更适合放在 CPU 上。
解码
N-gram 推测。草稿通过对已生成文本进行后缀匹配而免费获得,并在一个共享固定成本的双位置批次中进行验证。这在此处是有价值的,正是因为常驻 I/O 和计算(而非专家提取)主导了热 token 的处理。在我们的测试中,接受的草稿精确复现了参考序列。回滚操作保留旧的不可变状态对象,而不是克隆约 475 MB 的数据,然后在常数时间内恢复它们;重放测试则保证了未来序列的精确一致性。
sequenceDiagram participant D as n-gram draft participant M as model (one T=2 pass) participant S as state snapshot D->>M: [last_token, draft] M->>M: 93 layers, shared cost alt draft verified M-->>D: 2 tokens accepted else draft wrong S-->>M: state restored (bit-exact) M-->>D: 1 token, nothing lost end
随 RAM 扩展
在启动时,Deltafin 为操作系统预留内存(max(10 GB, 18%)),并将尽可能多的常驻层固定在剩余内存允许的范围内。一台 128 GB 的机器无需任何配置就能固定比 64 GB 机器多几倍的层,并且专家缓存还能额外受益于任何空闲的页面缓存。
未来方向
大致按优先级排序:Metal 专家内核(已原型化)、一个合适的质量评估框架(针对官方 API 的平均负对数似然),以便可以测量而非争论有损的速度/质量权衡、更智能的专家预取,以及最终一个遵循 ds4 精神的原生引擎,届时大部分剩余开销应该会消失。
致谢
Deltafin 大量借鉴了他人公开发布的研究成果。按影响力大致排序如下:
colibri(JustVugg,Apache-2.0 许可)—— 展示了 744B 参数的 MoE 模型可在 25 GB 内存中运行,我们从中学习了路由器预取、专家固定技术、macOS 上的 F_NOCACHE 和 F_RDADVISE 策略,以及逐分片转换模式。其 M5 Max 性能报告 —— CPU 自旋等待会抢占共享功耗预算导致 GPU 饥饿 —— 改变了我们的任务调度方式。
ds4 / DwarfStar(Salvatore Sanfilippo,MIT 许可)—— 我们研究过的最清晰的专家流式传输设计:零拷贝专家缓冲区、掩码分发、基于选择的缓存淘汰、会话持久化,以及我们直接采用的质量评估方法(与官方 API 输出的平均负对数似然对比)。其核心理念 —— 正确性优先于速度,用计算掩盖 I/O —— 非常合理,我们努力遵循了这一原则。
月之暗面(Moonshot AI)—— 感谢他们公开了 K3 的权重并附带了可读的建模代码(Deltafin 直接运行该代码),以及 Kimi Delta Attention 设计,其小型循环状态使得在笔记本电脑上实现长上下文成为可能。
flash-linear-attention(fla-org,MIT 许可)—— 我们的 KDA 适配层移植了其内核和参考实现的语义。
llama.cpp / ggml —— 内核内反量化与 MXFP4 处理的先前技术,也是本地推理社区大部分知识的基础。
PyTorch、Transformers、ml_dtypes(我们用于 e2m1 的位精确性参考)以及 tiktoken。
许可协议
Deltafin 自身的代码采用 MIT 许可。本仓库中有两项内容不属于我们:
tools/fla/ 是 flash-linear-attention(MIT 许可,© 2023–2026 Songlin Yang, Yu Zhang, Zhiyuan Li)语义的纯 PyTorch 移植。该署名已在文件头部和 LICENSE 文件中重复声明。
Kimi K3 的权重和建模代码归月之暗面所有,并依据月之暗面自身的许可协议分发。这些文件在设置时下载,从未在此处进行供应商化 —— 使用前请阅读该许可协议。
Deltafin 是一个独立项目,与月之暗面无任何关联。
原文
Original Title
在 M1 Max 上运行 Kimi K3
Source
Hacker News 热门(buzzing.cc 中文翻译)
Site
github.com
Author
tito
Published
2026-07-29 10:49