bpu
This commit is contained in:
237
deploy_45dim_rl_gym/bpu_quantization/README.md
Normal file
237
deploy_45dim_rl_gym/bpu_quantization/README.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# RDK X5 BPU 量化流程
|
||||
|
||||
这个目录用于把 `../policy_robotlab_15000.onnx` 转成 RDK X5 可运行的
|
||||
Horizon runtime `.bin`。量化在 Mac 上用 CPU Docker 完成,板端只做离线
|
||||
`hrt_model_exec` 验证,暂时不要直接接入实机控制。
|
||||
|
||||
参考资料:
|
||||
|
||||
- D-Robotics 官方 X5 工具链说明:`https://developer.d-robotics.cc/rdk_x_doc/Advanced_development/toolchain_development/overview?v=3.5.0&p=RDK+X5`
|
||||
- D-Robotics 论坛 WTW/Go2/X5 流程:`https://forum.d-robotics.cc/t/topic/28338`
|
||||
|
||||
官方工具链对 ONNX 的关键限制是:`ir_version <= 7`、`opset10/11`、固定
|
||||
4 维输入,且 N 维只能为 1。因此这里不能直接拿原始 RobotLab ONNX 编译,
|
||||
需要先降级 opset,再把 `[1, 450]` 输入包成固定 4D `NCHW`:
|
||||
`[1, 1, 1, 450]`。
|
||||
|
||||
## 当前状态
|
||||
|
||||
已经完成 `policy_robotlab_15000.onnx` 和 `policy_robotlab_6500.onnx` 的 int16
|
||||
量化。当前 BPU 部署默认使用 6500 版本:
|
||||
|
||||
- 原始模型:`../policy_robotlab_6500.onnx`
|
||||
- 原始输入:`obs [1, 450]`
|
||||
- BPU 编译输入:`obs_4d [1, 1, 1, 450]`
|
||||
- BPU 输出:`actions [1, 12, 1, 1]`
|
||||
- Docker 镜像:`openexplorer/ai_toolchain_ubuntu_20_x5_cpu:v1.2.8`
|
||||
- `hb_mapper`:`1.24.3`
|
||||
- `hbdk`:`3.49.15`
|
||||
- 当前产物:`mapper_output_6500_gemm/policy_robotlab_6500_int16_gemm.bin`
|
||||
|
||||
`mapper_output*/`、`.hb_check/`、校准数据、中间 ONNX、`hb_mapper` 日志都被
|
||||
`.gitignore` 忽略;需要时按下面步骤重新生成。仓库里只保留脚本和 YAML 配置。
|
||||
|
||||
6500 量化使用 `calibration_data_fast64/` 的 64 个真实样本。原因是
|
||||
`hb_mapper` 会先尝试 calibration batch 8,但当前 4D featuremap 包装会被工具链
|
||||
内部改成固定 batch 的 reshape,batch 8 失败后会退回 batch 1;用 64 样本可以把
|
||||
校准时间从 512 次 batch1 显著降下来。
|
||||
|
||||
## 1. 生成校准数据
|
||||
|
||||
在本机 `deploy_go1_pro` 根目录执行:
|
||||
|
||||
```bash
|
||||
/Users/chenyouyuan/miniconda/envs/free_dog_sdk/bin/python3.10 \
|
||||
deploy_45dim_rl_gym/bpu_quantization/make_calibration_data.py \
|
||||
--max-samples 512 \
|
||||
--overwrite
|
||||
```
|
||||
|
||||
脚本会从 `logs/robotlab_go1_deploy_*/steps.jsonl` 中提取 RL 状态下的真实
|
||||
`obs_single`,按部署代码相同的 10 帧历史顺序重建 450 维输入,并写成
|
||||
`float32` feature-map `.bin`。
|
||||
|
||||
本次校准数据:
|
||||
|
||||
- 候选 RL 输入:`62606`
|
||||
- 选中样本:`512`
|
||||
- 单个样本形状:`1x1x1x450`
|
||||
- 元数据:`deploy_45dim_rl_gym/bpu_quantization/calibration_data_metadata.json`
|
||||
|
||||
## 2. 生成 opset11 和 4D ONNX
|
||||
|
||||
启动 Docker Desktop 后,在 `deploy_go1_pro` 根目录执行:
|
||||
|
||||
```bash
|
||||
docker run --rm --platform linux/amd64 \
|
||||
-v "$PWD:/workspace/deploy_go1_pro" \
|
||||
openexplorer/ai_toolchain_ubuntu_20_x5_cpu:v1.2.8 \
|
||||
bash -lc 'cd /workspace/deploy_go1_pro/deploy_45dim_rl_gym/bpu_quantization &&
|
||||
python3 downgrade_policy_to_opset11.py \
|
||||
--input ../policy_robotlab_15000.onnx \
|
||||
--output policy_robotlab_15000_opset11.onnx &&
|
||||
python3 make_bpu_4d_onnx.py \
|
||||
--input policy_robotlab_15000_opset11.onnx \
|
||||
--output policy_robotlab_15000_bpu4d.onnx &&
|
||||
python3 compare_4d_onnx.py \
|
||||
--flat-onnx ../policy_robotlab_15000.onnx \
|
||||
--bpu4d-onnx policy_robotlab_15000_bpu4d.onnx \
|
||||
--limit 256'
|
||||
```
|
||||
|
||||
本次对比结果:256 个真实输入上 `max_abs_diff = 0`,说明降级和 4D 包装没有
|
||||
改变浮点 ONNX 输出。
|
||||
|
||||
## 3. 可选:替换 MoE grouped Conv
|
||||
|
||||
原始导出的 MoE expert 末端有一个 `group=8, kernel=1` 的 `Conv1d`:
|
||||
|
||||
```text
|
||||
[1, 2048] -> Unsqueeze -> Conv(group=8, kernel=1) -> Squeeze -> [1, 256]
|
||||
```
|
||||
|
||||
在 X5 checker 里,这段会切到 CPU float,导致 BPU 子图被拆开。这个 Conv
|
||||
等价于一个块对角 `Gemm`,可以不重训直接改图:
|
||||
|
||||
```bash
|
||||
docker run --rm --platform linux/amd64 \
|
||||
-v "$PWD:/workspace/deploy_go1_pro" \
|
||||
openexplorer/ai_toolchain_ubuntu_20_x5_cpu:v1.2.8 \
|
||||
bash -lc 'cd /workspace/deploy_go1_pro/deploy_45dim_rl_gym/bpu_quantization &&
|
||||
python3 replace_group_conv_with_gemm.py \
|
||||
--input policy_robotlab_15000_bpu4d.onnx \
|
||||
--output policy_robotlab_15000_bpu4d_gemm.onnx &&
|
||||
python3 compare_4d_onnx.py \
|
||||
--flat-onnx ../policy_robotlab_15000.onnx \
|
||||
--bpu4d-onnx policy_robotlab_15000_bpu4d_gemm.onnx \
|
||||
--limit 512'
|
||||
```
|
||||
|
||||
本次浮点对比结果:
|
||||
|
||||
- `max_abs_diff = 1.43e-6`
|
||||
- `max_mean_abs_diff = 3.53e-7`
|
||||
|
||||
这是浮点舍入级误差,可以认为图变换等价。
|
||||
|
||||
注意:这里没有把 `ReduceL2/Pow/Reshape/Sqrt` 这类 norm 算子挪到后处理,
|
||||
因为它们在 actor 之前,属于策略中间计算,不能当成输出后处理裁掉。当前
|
||||
`hb_mapper makertbin` 已经能把这些 norm 节点放到 BPU 上。
|
||||
|
||||
## 4. checker 检查
|
||||
|
||||
```bash
|
||||
docker run --rm --platform linux/amd64 \
|
||||
-v "$PWD:/workspace/deploy_go1_pro" \
|
||||
openexplorer/ai_toolchain_ubuntu_20_x5_cpu:v1.2.8 \
|
||||
bash -lc 'cd /workspace/deploy_go1_pro/deploy_45dim_rl_gym/bpu_quantization &&
|
||||
hb_mapper checker \
|
||||
--model policy_robotlab_15000_bpu4d_gemm.onnx \
|
||||
--model-type onnx \
|
||||
--march bayes-e \
|
||||
--input-shape obs_4d 1x1x1x450'
|
||||
```
|
||||
|
||||
checker 可以通过。原始模型中 MoE expert 的 `Elu/Reshape/Conv` CPU fallback
|
||||
会被消掉;checker 阶段仍可能显示 gating `Softmax` 或输出 reshape 的 CPU
|
||||
适配,正式 int16 编译时 `Softmax` 会被量化拆成 BPU 子算子。
|
||||
|
||||
## 5. 编译 int16 `.bin`
|
||||
|
||||
```bash
|
||||
docker run --rm --platform linux/amd64 \
|
||||
-v "$PWD:/workspace/deploy_go1_pro" \
|
||||
openexplorer/ai_toolchain_ubuntu_20_x5_cpu:v1.2.8 \
|
||||
bash -lc 'cd /workspace/deploy_go1_pro/deploy_45dim_rl_gym/bpu_quantization &&
|
||||
hb_mapper makertbin \
|
||||
--config policy_robotlab_15000_int16_gemm.yaml \
|
||||
--model-type onnx'
|
||||
```
|
||||
|
||||
优化版 `hb_mapper` 输出的量化精度:
|
||||
|
||||
```text
|
||||
Output Cosine Similarity L1 Distance L2 Distance Chebyshev Distance
|
||||
actions 0.999910 0.009500 0.003393 0.024229
|
||||
```
|
||||
|
||||
优化版正式 int16 编译后,日志中列出的策略节点全部在同一个 BPU 子图
|
||||
`id(0)` 上,原始模型的 CPU `Elu/Reshape/Conv` fallback 已消失。
|
||||
|
||||
优化版 BPU 子图编译估计延迟:
|
||||
|
||||
- subgraph0:`424.5 us`
|
||||
|
||||
原始版 BPU 子图估计延迟是 `284.3 us + 80.8 us`,但带 CPU/hybrid 切换。
|
||||
优化版单子图的编译估计延迟略高,实际是否更快要以板端 `hrt_model_exec perf`
|
||||
为准。
|
||||
|
||||
## 6. 板端离线验证
|
||||
|
||||
把 `.bin` 和一个校准输入传到板端,例如:
|
||||
|
||||
```bash
|
||||
ssh root@192.168.150.167 'mkdir -p /root/go1_pro_deploy/bpu_quant_test'
|
||||
scp \
|
||||
deploy_45dim_rl_gym/bpu_quantization/mapper_output_gemm/policy_robotlab_15000_int16_gemm.bin \
|
||||
deploy_45dim_rl_gym/bpu_quantization/calibration_data/00000.bin \
|
||||
root@192.168.150.167:/root/go1_pro_deploy/bpu_quant_test/
|
||||
```
|
||||
|
||||
板端查看模型:
|
||||
|
||||
```bash
|
||||
cd /root/go1_pro_deploy/bpu_quant_test
|
||||
hrt_model_exec model_info --model_file policy_robotlab_15000_int16_gemm.bin
|
||||
```
|
||||
|
||||
板端测速:
|
||||
|
||||
```bash
|
||||
hrt_model_exec perf \
|
||||
--model_file policy_robotlab_15000_int16_gemm.bin \
|
||||
--model_name policy_robotlab_15000_int16_gemm \
|
||||
--input_file 00000.bin \
|
||||
--frame_count 1000 \
|
||||
--thread_num 1
|
||||
```
|
||||
|
||||
原始版板端结果:
|
||||
|
||||
- 平均延迟:`1.498257 ms`
|
||||
- 最大延迟:`2.942 ms`
|
||||
- FPS:`664.77`
|
||||
|
||||
优化版板端结果:
|
||||
|
||||
- 平均延迟:`0.872819 ms`
|
||||
- 最大延迟:`1.627 ms`
|
||||
- 最小延迟:`0.613 ms`
|
||||
- FPS:`1133.28`
|
||||
|
||||
同一板端之前测 CPU ONNX 大约是 `1.63 ms`。原始 BPU hybrid `.bin` 只快了一点;
|
||||
Gemm 优化版移掉 MoE 中间 CPU fallback 后,板端离线平均延迟比 CPU ONNX 快约
|
||||
46%,比原始 BPU hybrid 快约 42%。
|
||||
|
||||
原始版板端单样本输出与本机浮点 ONNX 对比:
|
||||
|
||||
- `max_abs = 0.02545`
|
||||
- `mean_abs = 0.01040`
|
||||
- `l2 = 0.04584`
|
||||
|
||||
优化版板端单样本输出与本机浮点 ONNX 对比:
|
||||
|
||||
- `max_abs = 0.02528`
|
||||
- `mean_abs = 0.00962`
|
||||
- `l2 = 0.04187`
|
||||
|
||||
这个误差对离线验证是可接受的,但还不足以直接上实机。
|
||||
|
||||
## 7. 安全结论
|
||||
|
||||
当前建议只做离线推理验证,不要把 `.bin` 接入真实机器人控制循环。原因:
|
||||
|
||||
- 原始 BPU 端到端速度提升很小,不能解决目前右前腿掉线、力矩保护、上下坡不稳这些核心问题。
|
||||
- Gemm 优化版已经改善离线推理速度,但还没有做部署代码适配和悬空状态机测试。
|
||||
- 输出 shape 从 `[1, 12]` 变成 `[1, 12, 1, 1]`,部署代码需要单独适配。
|
||||
- 接入前至少要做更多 held-out 真实日志对比、悬空状态机测试,再进入地面低速测试。
|
||||
Reference in New Issue
Block a user