File size: 6,873 Bytes
37c4768 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | # Magnetar 任务记录
## 任务目标
将 DiariZen 模型从 GitHub 源码转换为 AX650 NPU3 可交付 AXMODEL 包。
## 输入参数
- SOURCE: https://github.com/BUTSpeechFIT/DiariZen.git
- TARGET_HARDWARE: AX650
- NPU_MODE: NPU3
- MODEL_NAME: diarizen
- SDK_LANG: both
- TASK_DIR: todos/work/20260706-124435-diarizen
- BOARD: 未提供,RUNONBOARD 阶段将跳过并记录未验证
## 阶段状态
| 阶段 | 状态 | 摘要 |
| --- | --- | --- |
| ACQUIRE | DONE | 已 clone 源码到 origin/,未发现内置权重文件 |
| INIT | IN_PROGRESS | 初始化目录和审计文件 |
| EXPORT | PENDING | 等待主模型/权重确认 |
| TOOLCHAIN | PENDING | - |
| COMPILE | PENDING | - |
| SIMULATE | PENDING | - |
| SDK-GEN | PENDING | - |
| RUNONBOARD | PENDING | 未提供 BOARD |
| PACKAGE | PENDING | - |
## 环境摘要
```text
python: Python 3.12.12
pip: pip 26.0.1 from /home/yrz/miniforge3/lib/python3.12/site-packages/pip (python 3.12)
git: git version 2.34.1
docker: Docker version 29.1.3, build 29.1.3-0ubuntu3~22.04.2
cmake: cmake version 3.31.5
pulsar2:
```
## ACQUIRE 补充
- HuggingFace 权重: BUT-FIT/diarizen-wavlm-large-s80-md
- 快照路径: todos/work/20260706-124435-diarizen/cache/hf/models--BUT-FIT--diarizen-wavlm-large-s80-md/snapshots/a9b1b0e7974d96dcfd63af417e9da7ad8714040f
- 文件: config.json, config.toml, pytorch_model.bin, plda/*.npz
## ACQUIRE 补充(修正)
- HuggingFace 权重: BUT-FIT/diarizen-wavlm-large-s80-md
- 快照路径: 见 cache/acquire/hf_model_path.txt
- 文件: config.json, config.toml, pytorch_model.bin, plda/*.npz
## EXPORT
- 状态: DONE
- 导出脚本: export/export-static-onnx.py
- 原模型测试: export/test-source.py
- ONNX: export/model.onnx
- Meta: export/model_meta.json
- 校准数据: export/calib_data/waveform_0.npy(真实示例音频前 16 秒)
- 对分: cosine=0.9999999999981273, MAE=1.4469963e-05, max_abs_diff=8.4877014e-05
- 备注: opset17 LayerNormalization 导出失败,已改用 opset16 并记录到 issues/。
## TOOLCHAIN
- 状态: DONE
- Pulsar2: 使用本地 Docker 镜像 pulsar2:20260520-temp-61099061-lite
- C++ 交叉工具链: 待 SDK 阶段检查
## COMPILE
- 状态: STOP
- 配置: compile/pulsar2_config.json
- 日志: compile/compile_disable_transformation_check.log
- 报告: compile/compile_report.md
- 失败原因: AX650 NPU backend tiling 在 `/layers.0/attention/Gather_1` 失败,attention tensor 为 `(1,16,799,799)`。
- 需要用户确认后续策略: 缩短导出音频窗口 / 拆分模型 / 调整 attention 导出 / 混合 CPU+NPU。
## EXPORT 4s / COMPILE 4s
- EXPORT 4s 状态: DONE
- 4s ONNX: export_4s/model.onnx
- 输入/输出: `[1,1,64000] -> [1,199,11]`
- ONNX 对分: cosine=0.9999999999988147, MAE=1.1889559e-05, max_abs_diff=5.0544739e-05
- COMPILE 4s 状态: STOP
- 编译日志: compile_4s/compile.log
- 编译报告: compile_4s/compile_report.md
- 失败原因: AX650/NPU3 仍在 `/layers.0/attention/Gather_1` tiling 失败,attention tensor 为 `(1,16,199,199)`。
## PULSAR2 SOURCE PATCH 验证
- 源码路径: /home/yrz/Codes/npu-codebase
- 补丁文件: axnn/axnn/backend/ax650npu/oprimpl/gather.py
- 验证日志: compile_4s_srcpatch/compile.log
- 结果: 原 `/layers.0/attention/Gather_1` tiling 报错已越过;当前下一个 STOP 是 `AxQuantizedLayerNorm` 后端构建失败。
## NPU Codebase Patch
- 状态: PARTIAL FIX VERIFIED
- 修改: /home/yrz/Codes/npu-codebase/axnn/axnn/backend/ax650npu/oprimpl/gather.py
- 测试: `python -m pytest axnn/axnn/backend/pytests/gather_test.py -k large_stride_payload_slice -q` 通过
- 源码版 Pulsar2: 使用 `USE_PULSAR2` 对应环境验证,原 Gather tiling 报错已消失;当前阻塞转移到 `AxQuantizedLayerNorm`。
## COMPILE 无输入 LayerNorm(source Pulsar2 + gather fix)
- 状态: COMPILED (with critical quality issue)
- ONNX: export_4s/model_no_input_ln.onnx(已去除输入 LayerNorm)
- 配置: compile_no_ln/pulsar2_config.json
- AXMODEL: compile_no_ln/model.axmodel (77MB)
- 输入: waveform (1, 1, 64000) float32, 需 CPU 预做 LayerNorm
- 输出: log_probs (1, 199, 11) float32
- MACs: 16.6G
- NPU 子图: 1 个全 NPU 子图,1115 ops
### 关键发现
- Docker Pulsar2 (5.1/6.0): 无法编译,AxGather tiling 失败
- Source Pulsar2 + gather patch: 编译通过但 NPU 后端输出恒值
- per-op FP32 仿真精度 >0.999(量化参数正确)
- INT8 Reference 模式 cosine=0.76(量化可用但精度下降)
- NPUBackend/compiled 模式输出恒值 -16.0319 → NPU 后端 bug
### Pulsar2 补丁
- 文件: /home/yrz/Codes/npu-codebase/axnn/axnn/backend/ax650npu/oprimpl/gather.py
- 修改:
1. `tx[:, i*sub_elems:...]` → `tx[..., i*sub_elems:...]` (修复 3D tensor 索引)
2. `sub_elems` capped 到 `tx.shape[-1]`(防止越界切片)
### 根因判断
WavLM 24 层 Transformer + Conformer 的组合对 AX650 NPU INT8 计算路径过于复杂,
NPU 后端的某个(或多个)算子实现在 INT8 精度下产生数值错误,导致模型输出完全崩溃。
per-op FP32 仿真表明各算子单独工作正常,问题出在全链路 INT8 执行时的误差累积或控制流错误。
### 建议后续方向
1. 拆分模型:WavLM CNN 前端 → NPU,Transformer + Conformer → CPU
2. 尝试更大校准数据集提升 Reference 精度
3. 等待 Pulsar2 更新修复 NPU 后端 bug
4. 联系爱芯技术支持排查具体算子问题
## 模型拆分方案
因完整模型无法在 AX650 NPU 上正确编译(NPU 后端 INT8 bug),采用 CPU+NPU 混合方案:
| 组件 | 硬件 | 精度 | 大小 |
|------|------|------|------|
| WavLM CNN 前端 (7 conv layers) | AX650 NPU | U16 | 1.3MB axmodel |
| WavLM Transformer (24L) + Conformer (4L) + Classifier | CPU (ONNX Runtime) | FP32 | 273MB ONNX |
## 拆分编译
### CNN 前端
- Docker Pulsar2: 6.0-lite
- 配置: compile_cnn/pulsar2_config_u16.json (全图 U16)
- AXMODEL: compile_cnn_u16_full/cnn_features.axmodel
- 输入: waveform_ln (1, 64000) float32(CPU 预做 LayerNorm)
- 输出: cnn_features (1, 199, 211) float32
- SIMULATE: cosine=0.9914 vs ONNX
### 后端 (CPU)
- ONNX: export_backend/backend.onnx (2709 ops, 273MB)
- 输入: cnn_features (1, 199, 211) float32
- 输出: log_probs (1, 199, 11) float32
- 验证: cosine=1.0 vs PyTorch
### 端到端
- cosine=0.9997 vs 完整 FP32 ONNX
- 所有 11 个 class cosine > 0.998
## 最终状态
| 阶段 | 状态 | 摘要 |
| --- | --- | --- |
| ACQUIRE | DONE | 源码 + HuggingFace 权重 |
| INIT | DONE | 目录初始化 |
| EXPORT | DONE | CNN 前端 + 后端 ONNX,cosine=1.0 |
| TOOLCHAIN | DONE | Docker Pulsar2 6.0-lite |
| COMPILE | DONE | CNN U16,Docker Pulsar2 |
| SIMULATE | DONE | E2E cosine=0.9997 |
| SDK-GEN | DONE | Python + C++ SDK |
| RUNONBOARD | SKIPPED | 无板端 |
| PACKAGE | DONE | package/ 264MB,GitHub-ready |
|