first commit

This commit is contained in:
2026-10-30 17:29:26 +08:00
commit d566b300f2
17 changed files with 1408 additions and 0 deletions

112
README.md Normal file
View File

@@ -0,0 +1,112 @@
# DeepSeek-R1 昆仑芯 INT8 转换
针对完整 DeepSeek-R1/V3 架构检查点。
依据已安装的 `vllm==0.25.1`、`vllm-kunlun==0.25.1.dev0` 实现
## 输出策略
| 权重 | 输出类型 | 原因 |
|---|---|---|
| MLA q_a/q_b/kv_a/o 投影 | 逐输出通道 INT8 | 对接 KunlunScaledMMLinearKernel |
| 58 层 MoE 的 256 个路由专家 gate/up/down | 逐输出通道 INT8 | 对接 KunlunCompressedTensorsW8A8Int8MoEMethod |
| MLA kv_b_proj | 反量化 BF16 | 对接 MLA 的 BF16 W_UK_T/W_UV 拆分路径 |
| 前三层 Dense MLP | 反量化 BF16 | 真实样本逐通道 INT8 误差较大 |
| 共享专家 gate/up/down | 反量化 BF16 | 真实样本逐通道 INT8 误差较大 |
| Embedding、lm_head、norm、router、routing bias | 原样保留 | 保持源类型和值 |
| 第 62 层 MTP,即 model.layers.61 | 不包含 | 本脚本输出普通推理版本,num_nextn_predict_layers=0 |
输出 `compressed-tensors / int-quantized`,权重逐通道静态对称 INT8,激活逐 token 动态对称 INT8;无需校准集。BF16 例外通过量化配置的 ignore 明确声明,包括 vLLM 融合后的 gate_up_proj 名称。保持源张量名称,由 vLLM 完成 Q/KV A 投影、gate/up 的融合与专家权重切分。
```text
W[i,j] = W_fp8[i,j] * weight_scale_inv[i//128,j//128]
s[i,0] = max(abs(W[i,:])) / 127
W_int8[i,j] = clamp(round(W[i,j]/s[i,0]), -127, 127)
```
`weight_scale_inv` 保存的值用于乘法反量化,不能取倒数。
输出 INT8 scale 为 `weight_scale`,FP32,形状 `[out_features,1]`。
磁盘存 `absmax/127`,插件加载后自行乘 127,转换时不能提前乘。
BF16 例外输出 `BF16(FP8 * block_scale)`,删除原 block scale,不产生 INT8 scale。
全零 INT8 行使用 `q=0,s=1`。
脚本按源索引定位跨分片的 scale,逐分片、逐矩阵、分行处理;不加载整个模型,不分配 XPU,不修改原始模型。
预检逐项验证前 61 层的全部 MLA/Dense/共享及路由专家投影、矩阵形状、FP8 格式和 scale 网格。
## 使用
脚本已部署到:
```text
/mnt/data1/quant_tools/deepseek_r1_kunlun_int8/
```
预检不创建输出目录、不转换权重:
```bash
/opt/vllm_kunlun/bin/python \
/mnt/data1/quant_tools/deepseek_r1_kunlun_int8/convert_deepseek_fp8_to_int8.py \
--source /mnt/data1/deepseek-r1 \
--output /mnt/data1/deepseek-r1-INT8 \
--dry-run
```
开始全量转换:
```bash
/opt/vllm_kunlun/bin/python \
/mnt/data1/quant_tools/deepseek_r1_kunlun_int8/convert_deepseek_fp8_to_int8.py \
--source /mnt/data1/deepseek-r1 \
--output /mnt/data1/deepseek-r1-INT8 \
--threads 8
```
中断后在相同命令末尾添加 `--resume`。输出目录必须是独立空目录,或具有匹配的 `conversion_state.json`。默认 `--chunk-rows 1024`,恢复时必须与首次运行一致。每片先写临时文件,检查成功后重命名,再记录完成状态。完成时打印 `Complete` 并生成新配置、索引和 `conversion_report.json`,之后才可部署。
恢复时核实源配置和索引、源分片大小与时间戳;核实已完成输出分片大小、张量名称、类型、形状及 safetensors 文件结构。恢复检查不计算完整权重文件校验和。
2026-10-29 预检结果:45,032 个 FP8 矩阵,其中 44,788 个转 INT8,244 个转 BF16;160 个输出分片,预计张量数据 **631.84 GiB**。原始目录按真实张量计算为 641.29 GiB(含 MTP);源索引的 total_size 元数据偏大,脚本不使用该值估算转换空间。
## 首次部署参数
转换后可运行提供的启动示例:
```bash
bash /mnt/data1/quant_tools/deepseek_r1_kunlun_int8/serve_int8.sh
```
示例使用 TP=8、BF16、eager 模式、4096 上下文、单并发,每卡 KV cache 显式分配 4 GiB。
`VLLM_KUNLUN_ENABLE_INT8_BMM=0` 与 BF16 kv_b_proj 一致,不能设置为 1。
首测使用 TP,不沿用原命令中的 `--enable-expert-parallel`;当前 INT8 单体 MoE 路径的 EP 路由和专家重映射未验证。
这是准备好的初始参数,尚未完成完整模型启动或生成测试。
## 已完成的验证与范围
```bash
cd /mnt/data1/quant_tools/deepseek_r1_kunlun_int8
/opt/vllm_kunlun/bin/python test_conversion.py
/opt/vllm_kunlun/bin/python validate_kunlun_contract.py
/opt/vllm_kunlun/bin/python validate_sample_weights.py \
--source /mnt/data1/deepseek-r1 \
--report sample_validation_mixed.json
```
- CPU 数值测试与合成检查点转换通过:包括跨分片 scale、非整块维度、全零行、BF16 例外、MTP 排除、配置/索引、断点恢复、源文件保护、拒绝覆盖和缺失投影检查。
- 当前插件的 CPU 配置/参数约定检查通过:MLA 融合投影的 INT8 内核、路由专家 INT8 MoE、scale 乘 127、BF16 ignore 配置和 MLA BF16 权重拆分。测试模拟 TP rank/size,不是完整引擎启动或 XPU 算子执行。
- 九个真实矩阵抽样通过:覆盖五类 MLA 投影、Dense MLP、共享专家、路由专家 gate/down。
初始 absmax INT8 基线中,Dense gate 样本 relative RMSE 为 10.10%,共享专家 gate 为 7.18%。将这两类投影改为 BF16 后,对应样本误差为 0.142% 和 0.152%;最终 INT8 样本误差约为 0.94%–1.99%,满足半个逐行量化步长的舍入误差界。相对误差均以 FP8 乘 block scale 后的 FP32 权重为参考;这些指标不代表任务准确率。
服务器上的 `sample_validation.json` 保存初始基线,`sample_validation_mixed.json` 保存最终策略结果。
这是从已量化 FP8 再转换的基线方案;全量转换、P800 推理及实际任务质量仍需分别验证。
## 2026-10-29 MLA 初始化问题及绕过
完整部署发现当前 FlashMLAImpl 缺少 vLLM 所要求的 forward_mha/forward_mqa,无法实例化。此前 CPU 权重准备检查未覆盖这个实例化步骤。权重无需重新转换。
新增 serve_int8_no_mla.sh,通过 VLLM_MLA_DISABLE=1 选择 DeepseekV2Attention 和昆仑芯普通 Attention,绕过不完整的 FlashMLA 接口;保持 TP=8、不启用 EP、eager、单并发、4096 上下文和每卡 4 GiB KV cache。关闭 MLA 增加 KV cache 开销,可能降低吞吐。该路径尚未经过完整模型启动和输出验证。
在容器内运行:
```bash
bash /mnt/data1/quant_tools/deepseek_r1_kunlun_int8/serve_int8_no_mla.sh
```