2218 字
11 分钟

DeepSeek-V4-Flash 剪枝手术门禁全记录:从 T2 合并到 W512,双路线判死复盘

DeepSeek-V4-Flash 剪枝手术门禁全记录#

这是一篇长文,记录一次完整的”284B MoE 模型结构手术 + ppl 门禁验证”任务的所有操作、所有错误、所有经验。如果你在做大模型量化权重的结构裁剪,这里的每个坑大概率你也会踩。


一、任务背景#

目标是 DeepSeek-V4-Flash-0731(284B 总参 / 13-21B 激活,MIT 协议)的剪枝蒸馏产线。模型结构关键点:

  • 43 层,hidden 4096,64 注意力头,MLA 注意力
  • 第 0-2 层 = hash 路由:查表 tid2eid(vocab 129280 → 专家 id),无学习型 gate
  • 第 3-42 层 = 学习型 router(gate 权重 [256, 4096])
  • 256 路由专家 top-6 + 1 共享专家
  • 权重是 I8 容器封装的 FP4:每个 I8 字节存 2 个 4-bit 值(lo=byte&0x0F, hi=byte>>4),解包后维度翻倍;scale 是 F8_E8M0(无符号,value=2^(byte-127)),每 32 列共享一个 scale

两条候选手术路线(策划拍板):

  • R1(T2 合并):hash 层 256 专家按权重余弦聚成 64 簇,簇内 token 负载加权平均合并,tid2eid 指簇 id
  • R2(W512 宽度裁剪):全 43 层保持 256 专家,中间维 2048→512(范数重要性选 top-512)

门禁规则:ppl delta ≤5% 通过;5-10% 记蒸馏债;>10% 死亡。双路线均 >10% → 转 ktransformers 预案。


二、完整操作流水#

阶段 1:相似度计算(本地 CPU)#

  • SKETCH_DIM=2M 随机坐标草图:固定 seed 采样 2M 坐标(从每专家解包后 33.5M 维均匀采样),fp16 存 sketch(256×2M×2B=1GB/层),转 fp32 算 256×256 余弦 Gram
  • 流式反量化:单专家 fp32 物化 ~100MB,逐专家处理
  • 关键发现:hash 层 256 专家互相近正交——任意两专家余弦 0.027~0.034,全距仅 0.006,无任何 pair > 0.1。簇内/跨簇余弦比值 ≈ 1.035(≈1.0,正是文档定义的”预警”条件)

阶段 2:T2 合并(本地 CPU)#

  • 平均链接凝聚聚类 256→64 簇(无 scipy,自实现)
  • 簇内按 tid2eid 静态负载加权平均合并 → 反量化 → 合并 → 重量化(FP4+E8M0)
  • 产出 3 层 × 64 合并专家 + 新 tid2eid [129280,6](值域 0-63)
  • 发现 ~20% token 归簇后簇 id 重复 → 按策划裁决修复:碰撞位填全局负载最低的未用簇,保证每 token 6 个互异簇 id

阶段 3:GPU 机装配 + ppl 门禁#

  • 原版模型 48 shard 分发到 GPU 机(5×RTX 6000D)
  • 装配 5 变体:base / h_t2p / r1_combo / h_w512 / l_w512 / r2_combo
  • transformers 5.15 慢速推理测 ppl(2000 tokens 小样本定数量级)

三、所有踩过的坑(按严重度排序)#

坑 1:手术脚本硬链接写坏原版模型(最严重,两次)#

现象:原版模型的 shard 被手术覆盖,w1 从 [2048,2048] 变成 [512,2048],156G 模型目录损坏。

根因:装配时用 os.link() 硬链接原版 shard 到变体目录(省盘),手术脚本 write_shard() 直接 open(path,'wb') 写入——硬链接的文件被覆盖 = 原版 inode 被改写。而我 patch 的”写前 unlink”只改在远程旧文件上,本地脚本从未生效,又被新上传覆盖。

教训

  1. 手术输出目录绝不能硬链接将被修改的 shard——要么跳过手术目标 shard 让脚本新建,要么写前 os.unlink() 断硬链接
  2. patch 必须同步到所有副本(本地/远程),用 md5 校验
  3. 原版模型加只读保护 chmod -R a-w——我最后才做,之前白白丢了一次 156G

坑 2:本地原版被污染后,所有下游全部失效#

现象:基于污染源(w1=[512,2048])构造的 null/h_w512/l_w512/r2_combo 全部无效;null 变体 ppl 5.17 ≠ base 3.73,一度误判”流水线有 bug”。

教训数据源完整性是第一优先级。每次手术前验证源 shard 形状(w1 应为 [2048,2048]),用 header-only 读取(seek 到 header,不整读 3.5G 文件,本地 32GB 内存整读会 OOM/超时)。

坑 3:FP4 解包语义搞错#

现象:一开始把 I8 当成 int8(w_int8 * scale),产出”看起来正常”的统计(absmax 4.0, std 0.9)——实际上 FP4 是 2 值/字节,解包后维度翻倍(2048→4096 中间维)。

教训量化格式必须以模型加载器(transformers modeling / 参考实现)为准,不能凭 config 猜。从 GPU 机参考脚本确认了 dequant_fp4 的正确解包。E8M0 是无符号 2^(byte-127),不是带符号位。

坑 4:W512 手术 w1/w3 行裁剪被错误”重量化”#

现象:行裁剪应该是纯字节切片(FP4 沿列打包、行独立、零损失),我却把选中行解包→重打包→重新量化,引入 rel err 130% 的巨大噪声 → h_w512 ppl 爆炸。

修复:w1/w3 = 原字节行切片(weight[sel, :] 直接拷字节),只有 w2 列裁剪(打包方向)才需解包重打包(误差 ~0.107)。零精度损失的裁剪才是对的

教训结构性操作要识别”打包方向”——沿打包轴的裁剪需要重打包,垂直轴的裁剪可以纯字节拷贝。先验证重构误差(选中维 rel err 应为 0 或 ~0.1,而不是 1.3)。

坑 5:OOM(本地 32GB 跑手术)#

现象per_shard dict 累积所有层的张量字节(每层 ~1GB × 18 层 = 18GB+),加上系统进程(unattended-upgrades/networkd/wsdd 占 ~38GB)→ OOM。

修复:改成每层手术完立即写盘并释放(内存峰值 ~2GB/层),cgroup 2GB 限制下也能跑。

教训:批量处理大模型手术,逐层流式 + 及时释放是铁律。也要清理无关系统进程。

坑 6:混合专家数导致 grouped_mm 内核断言失败#

现象:h_t2p(hash 64 + 学习 256 专家)前向时 grouped_mm 内核断言 offsets.shape[0] == num_experts 失败。

解决model.set_experts_implementation({"": "batched_mm"}) 回退到朴素 Python 实现(慢但能跑,且所有变体走同一路径保证公平对比)。

教训混合专家数在 transformers 工具链里就是有毒的(交接文档早就警告)——这正是 T2 要统一专家数的原因。

坑 7:下载/传输基础设施反复失败#

  • hf-mirror 大文件下载:aria2c 多连接 TLS 断连、卡死
  • 本地代理HTTPS_PROXY=http://127.0.0.1:7890 导致 curl 下载卡死——--noproxy '*' 直连后 350MB/s(1G 文件 3 秒)
  • ModelScope:直连下载 156G 稳定完成(比 HF 快)
  • scp 断连:传输中断留下损坏 shard(null shard4 只传了 2.8G)→ 用 rsync —partial 断点续传修复
  • 无卡模式 2GB cgroup 内存:读 3.5G shard 直接 OOM——手术脚本要用 mmap 流式读

教训:大文件传输首选 rsync(断点续传+校验);国内环境优先 ModelScope 直连;代理是大坑要显式绕过。

坑 8:AutoDL 实例反复出问题#

  • 欠费停机 → 释放 → 数据丢失(本地有备份才救回)
  • token 服务端吊销(JWT 未过期但 API 报”登录超时”)
  • 无卡模式 ↔ GPU 模式切换会中断传输
  • 开 GPU 卡需要余额 ≥ 卡费预授权(17 元不够 5×6000D 开机,报”余额不足”)

教训传输用无卡模式(便宜),只有 ppl 才开 GPU 卡;关键数据本地必须备份。


四、最终门禁结果(干净流水线,2000 tokens,base ppl=3.73)#

变体ppldelta裁决
null(流水线恒等对照)3.72998780.00%(逐位一致)✅ 流水线干净
h_w512(仅 hash 层)5.17+38.5%❌ 死
l_w512(仅学习层)2.5M爆炸❌ 死
r2_combo(W512 组合)2.5M爆炸❌ 死
l_c64(学习层 64 专家)37.37+902%❌ 死
h_t2p(T2 合并)6.98M爆炸❌ 死
r1_combo(T2+裁剪)2.19e7爆炸❌ 死

双路线总账均 >10% → 按规则停手,转 ktransformers 预案评估。


五、核心经验总结#

  1. 量化权重手术的三条铁律

    • 原版模型只读保护 + 每次手术前验证源完整性
    • 手术输出独立目录,写前断硬链接
    • 识别打包方向:沿打包轴裁剪要重打包,垂直轴可纯字节拷贝
  2. FP4/FP8 格式必须先解包再操作,一切以加载器为准,不能凭 config 猜。

  3. 事前指标真的有用:T2 的簇内/跨簇余弦比值 ≈1.0(预警)、W512 能量保留仅 26%(预示死刑)——都提前暴露了问题,只是门禁还是走了完整流程。

  4. 数据源管理是最大的隐性成本:一次污染导致全部下游重做 + 多次重传(156G),比任何算法 bug 都贵。

  5. 基础设施选型:ModelScope 直连 > HF 镜像 > 代理;rsync 断点续传 > scp;无卡模式做手术/传输、GPU 卡只跑 ppl。

  6. 小样本定数量级是对的:2000 tokens 就看清了爆炸(2.5M vs 3.73),全量 200K 纯属浪费——策划的”小样本定数量级,不许上全量”是这次最省钱的决定。


附:关键数据点#

  • 模型:DeepSeek-V4-Flash-0731,284B,43 层,FP4 量化 ~156G
  • hash 层专家余弦:任意 pair 0.027~0.034(近正交)
  • W512 能量保留:top-512/2048 维 = 26.3%(范数选择 vs 朴素仅 +2% 增益)
  • null 变体逐位一致:0/1565 张量差异
  • 总机时:GPU 卡 ~4 次短租(每次 <1 小时),无卡模式多次

全文完。最大的收获不是”双路线判死”这个结论,而是如何在一堆基础设施坑和格式陷阱里保住数据、跑完门禁——这些经验下次直接复用。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给老登打钱!

打钱
DeepSeek-V4-Flash 剪枝手术门禁全记录:从 T2 合并到 W512,双路线判死复盘
https://blog.meowhead.cn/posts/deepseek-v4-surgery-gate-recap/
作者
小原酱
发布于
2026-08-20
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
小原酱
世界第二可爱的小原酱~
分类
标签
站点统计
文章
40
分类
4
标签
77
总字数
70,147
运行时长
0
最后活动
0 天前

目录