省流
非常多人都热衷本地部署大模型,不过想要在有限能力的本地设备部署一个fancy的大模型,挑战相当多的,总的来说本地部署最大的一个难关是存储问题,存储问题搞定后再考虑考虑怎么取舍一下优化性能问题。
DeepSeek-V4.1-Flash模型大小约 510GB,NV的DGX Spark 仅 128GB 统一内存,常规思路装不下。 deepseek-v41-flash-spark 给出了两条路:方案一 原生 FP4 专家 + 热集常驻内存、其余从 SSD 流式读取,虽保留全部专家但速度受 SSD 限制;方案二 CB3 压缩 + 只保留约 36%–40% 专家全常驻,Decode 不再读SSD,速度快得多但模型被裁剪且依赖具体任务的校准语料内存。本文简要介绍实现要点与适用场景。
问题介绍
moe专家的容量瓶颈
DeepSeek-V4.1-Flash 为 MoE结构,40 层 × 每层 384 路由专家,每 token 每层激活 6 个,共 15,360 个专家,每个含 w1/w2/w3。checkpoint 中为 FP4 E2M1 + UE8M0 scale,存储形状如下(weight 每字节两个 FP4):
w1/w3.weight [2304,2560] + scale [2304,160];w2.weight [5120,1152] + scale [5120,72]
单专家存储量:
2×(2304×2560+2304×160) + (5120×1152+5120×72) = 18,800,640 B ≈ 18.8MB全部:18,800,640×15,360 ≈ 288.8GB
另有注意力、Embedding、LM Head、共享专家、Router、DSpark 等常驻权重;量化后 Dense 约 7.6GB,DSpark 三阶段 draft 专家另约 7.2GB FP4。就算不计激活与余量,128GB 也装不下 288.8GB 路由专家。
KV 与 Prefill 临时workspace
在v4.1里面,采用了压缩全局 KV + 每层 128-token 滑窗,技术报告 FP4 全局 KV 约 890B/token,256K 约 0.23GB,仓库用 BF16 存压缩 KV 与 Indexer Key,四源层压缩比 2/2/2/1,得 3200B/token,256K 约 0.84GB,再加 43 层滑窗 Ring 约 0.18GB,合计约 1GB,远小于专家占用。长上下文更常卡在 Prefill的临时激活(默认 2048-token chunk 约 7.2GB,并随上下文增长)。
全量化也难以塞进 90GB
moe的w1 w2 w3及他们的scale加起来大概:3×2304×5120×384×40 ≈ 5436 亿个,若专家池为 85–90GB,平均约 1.25–1.32 bit/weight;纯 2bit量化也需约 136GB,混合精度仍难压到 1.3bit 且保质量,迫不得已,方案只有全专家可达 + 部分常驻,慢点但是不损失模型,或 裁剪 + 全常驻,快点但是模型已经不是原来的那个了。
方案一:hot expert常驻内存
原则是不删专家、不重量化路由权重。固定 Expert Arena 放热专家,专家miss 时从 SSD 读 18.8MB 并apply LRU 淘汰策略;启动前用 expert_trace / expert_stats 的离线 Trace 做 warm start。为了方便理解,做个类比:Arena=内存,NVMe=盘,LRU=淘汰,Trace=预装顺序。
典型配置大概是Arena 约 73.8GB、3926个槽(约 25.6% 总专家容量);其中 400 槽 专供 Prefill(一层最多用满 384 专家,须 ≥384,默认 400 留余量),其余约 3526 槽为 Decode LRU(真正稳定的热集,约 23% 专家)。
热专家与 Prefill 隔离
统计路由专家的频率并排序,仓库做了个实验:3000/4000/5000 常驻专家对应约 80.5%/85.5%/89.1% 预测 LRU 命中;实测 3926 槽约 83% 命中。Prefill 一层大约触发 370–381/384 专家,若prefill阶段走LRU必然会不断刷新hot expert,所以Prefill阶段的专家存储干脆拿400个固定槽位来存储,不进 LRU,LRU只留给Decode阶段。
SSD读取性能
moe参数里面 scale 连续,约 1.1MB大小,weight 连续,约 17.7MB,配合分块并发、双线程池、独立 CUDA Stream、Pinned Buffer DMA。18.8MB 对象约 4.1–5.6GB/s(并发越高性能越好)读完。
Engram 两表各约 101.5GB,这一部分不常驻内存,它的地址只依赖 token n-gram,约 48 行×264B/token(12.7KB)。用于DSpark draft的专家约 7.2GB 必须常驻内存,draft 5 token、主模型验 6 位,约 1.75→2.64 tok/s。
实测与取舍
配置:GB10、73.8GB expert Arena放热专家、原生 FP4、DSpark on、32K、固定 512 输出 token。实测下来启动 90s、TTFT 7–11s、Decode 中位 2.68 tok/s、专家命中率 83%、约 0.92GB 专家读/token、SSD读取约 530GB、接受长度约 3.03。瓶颈几乎全在 SSD的传输,不过呢至少证明了在触及全专家的这个情况下DGX Spark工程上可跑通。
在这个case下,15,360 专家均可路由、权重保持FP4、不用剪枝,是一个适合作为质量对照的baseline,但是缺点也比较明显,吞吐只有~2–3 tok/s,冷 Prefill TTFT 太高,这几乎让人难以忍受,比较适合实验、Trace、低频离线这种任务,不适合交互式的服务。
方案二
CB3量化 + 剪枝后的专家全部常驻
动机与思路
方案一已接近 SSD读写上限,要十几 token/s 级的吞吐必须 Decode 不读SSD上的expert。但90GB 仅仅能放约 31% FP4 专家,CB3量化将单专家 18.8MB→14.45MB(约 76.9% 体积),并且每层只保留 top 36%–40% 专家且 Router 只能选它们,这一部分全部存储进Expert Arena这块内存,由此Decode 的专家命中率可达100%。CB3 kernel 与打包细节略显复杂,感兴趣可自己查看原仓库。
稠密侧的weight为了帮助腾出更多的Expert Arena,同时保持精度,注意力投影与 wo_a 用 FP4、LM Head FP8、共享专家保持 FP8,由此稠密侧weight 约 7.6GB 量级。
选哪些专家:频率 vs Saliency
从直觉上来看,仅按 路由频率 剪枝貌似可取,但是实测下来,会在一些稀有 token上精度下降,仓库经过了一番研究后,改用 Saliency(Router 权重 × 专家输出 L2 范数,语料上求和)剪枝。61 个 thinking模式上,稀有token精度回升;此外,还构建了一个Keep-set,用以覆盖业务语料的独特特性(比如代码/前端/散文等)
性能与风险
31% FP4 全常驻时约 13–16 tok/s,40%的weight apply CB3 量化约 19–23 tok/s;实际性能还受到DSpark在不同任务里面的接受长度( markup ~5 token/步 vs 散文 ~2.5)的影响,延迟的花约100毫秒级
由此,优点明显,交互速度、TTFT、可根据任务定制、运行时优化空间更大(LUT量化或者应用CUDA Graph),同时缺点当然也有,不是完整模型,强依赖校准数据集, CB3量化为有损,长 Prefill 还是比较吃内存(例如 保留40%的专家到89G的Expert arena,设置最长上下文256K,如果prefill长度~195K可用内存就已经极低了,原因见上文分析;较稳的实测点约36%的专家到81G的Expert arena,留出空间给Prefill的临时workspace)。
方案一二选哪个?
方案一的要求是所有 FP4 专家仍可路由,适合作为对照实验,能接受 ~2–3 tok/s的吞吐,瓶颈在于SSD传输带宽,方案二的要求是特定领域的在线服务,缺少通用性,可以达到十几到几十 tok/s的吞吐。
But,要我的话,我选方案二,我需要的是特定垂直领域的帮手哈哈

