Files
go1_pro_deploy/deploy_45dim_rl_gym/bpu_quantization
2026-07-28 16:36:33 +08:00
..
bpu
2026-07-27 23:17:55 +08:00
2026-07-28 16:36:33 +08:00
bpu
2026-07-27 23:17:55 +08:00
bpu
2026-07-27 23:17:55 +08:00
2026-07-28 16:36:33 +08:00
bpu
2026-07-27 23:17:55 +08:00
2026-07-28 16:36:33 +08:00
bpu
2026-07-27 23:17:55 +08:00
bpu
2026-07-27 23:17:55 +08:00
bpu
2026-07-27 23:17:55 +08:00
2026-07-28 16:36:33 +08:00
2026-07-28 16:36:33 +08:00

RDK X5 BPU 量化流程

这个目录用于把 Gym/RobotLab 的 ONNX 策略转成 RDK X5 可运行的 Horizon runtime .bin。量化在 Mac 上用 CPU Docker 完成,板端可以做离线测速和实机 部署测试。

参考资料:

  • 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 <= 7opset10/11、固定 4 维输入,且 N 维只能为 1。因此这里不能直接拿原始 ONNX 编译,需要先裁剪 actions-only 输出、降级 opset再把 [1, D] 输入包成固定 4D NCHW Gym 5 帧是 [1, 1, 1, 225]RobotLab 10 帧是 [1, 1, 1, 450]

当前状态

新增 Gym 5 帧策略的一键量化入口,默认目标是:

  • 原始模型:../policy_35k.onnx
  • 原始输入:obs [1, 225]
  • BPU 编译输入:obs_4d [1, 1, 1, 225]
  • BPU 输出:actions [1, 12, 1, 1]
  • 默认输出:mapper_output_35k_gemm/policy_35k_int16_gemm.bin
  • 默认校准数据:calibration_data_35k_gym_fast64/

本机 Docker 已完成一次默认量化:

  • 浮点 4D/Gemm 图等价对比64 个真实样本上 max_abs_diff = 7.15e-7
  • hb_mapper makertbin 输出:actions cosine 0.998524L1 0.014313L2 0.005103Chebyshev 0.040004
  • 编译估计延迟:463.9 us
  • 产物大小:2.0M
  • 产物路径:deploy_45dim_rl_gym/bpu_quantization/mapper_output_35k_gemm/policy_35k_int16_gemm.bin

一键量化命令:

cd /Users/chenyouyuan/cyy_ws/deploy_go1_pro/deploy_45dim_rl_gym/bpu_quantization
./quantize_policy_x5.sh

切换其他 Gym 轮次时直接指定模型和 round

./quantize_policy_x5.sh --policy ../policy_30k.onnx --round 30k
./quantize_policy_x5.sh --policy ../policy_25k.onnx --round 25k
./quantize_policy_x5.sh --policy ../policy_15k.onnx --round 15k

脚本默认只抽 64 个真实 RL 样本做校准和最多 64 个样本做浮点等价对比,避免 之前 512 样本和 batch 回退导致的量化流程过慢。需要更稳的校准时再手动加大:

./quantize_policy_x5.sh --samples 128 --compare-limit 128

Gym BPU 部署入口支持快速切换轮次:

cd /root/go1_pro_deploy
PYTHONPATH=/root/go1_pro_deploy python3 deploy_45dim_rl_gym/deploy_go1_rlgym_bpu_x5_fastcpp.py \
  --bpu-round 35k \
  --kill-sport \
  --enable-rl \
  --log-dir logs \
  --kp 32 --kd 1.0 \
  --kp-cal 20 --kd-cal 1.0 \
  --power-factor 9 \
  --position-protect-limit 0.0 \
  --action-clip 6.5 \
  --action-trip-limit 8.0 \
  --action-hard-trip-limit 16.0 \
  --max-target-step 0.0 \
  --max-roll-deg 50 \
  --max-pitch-deg 50 \
  --swap-vy-yaw \
  --rc-vx-scale 0.5 \
  --rc-vy-scale 0.5 \
  --rc-wz-scale 1.0 \
  --log-timing

也可以直接指定 bin

PYTHONPATH=/root/go1_pro_deploy python3 deploy_45dim_rl_gym/deploy_go1_rlgym_bpu_x5_fastcpp.py \
  --bpu-model deploy_45dim_rl_gym/bpu_quantization/mapper_output_35k_gemm/policy_35k_int16_gemm.bin \
  --infer-check --max-steps 1000 --log-timing

板端离线测速:

cd /root/go1_pro_deploy
PYTHONPATH=/root/go1_pro_deploy python3 deploy_45dim_rl_gym/bpu_deploy_x5/test_bpu_policy.py \
  --bpu-model deploy_45dim_rl_gym/bpu_quantization/mapper_output_35k_gemm/policy_35k_int16_gemm.bin \
  --input-bin deploy_45dim_rl_gym/bpu_quantization/calibration_data_35k_gym_fast64/00000.bin \
  --repeat 1000

cd /root/go1_pro_deploy/deploy_45dim_rl_gym/bpu_deploy_x5/cpp
./bpu_dnn_bench \
  /root/go1_pro_deploy/deploy_45dim_rl_gym/bpu_quantization/mapper_output_35k_gemm/policy_35k_int16_gemm.bin \
  /root/go1_pro_deploy/deploy_45dim_rl_gym/bpu_quantization/calibration_data_35k_gym_fast64/00000.bin \
  1000

已经完成 policy_robotlab_15000.onnxpolicy_robotlab_6500.onnx 的 int16 量化。RobotLab 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_mapper1.24.3
  • hbdk3.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 的 reshapebatch 8 失败后会退回 batch 1用 64 样本可以把 校准时间从 512 次 batch1 显著降下来。

1. 生成校准数据

在本机 deploy_go1_pro 根目录执行:

/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 根目录执行:

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=1Conv1d

[1, 2048] -> Unsqueeze -> Conv(group=8, kernel=1) -> Squeeze -> [1, 256]

在 X5 checker 里,这段会切到 CPU float导致 BPU 子图被拆开。这个 Conv 等价于一个块对角 Gemm,可以不重训直接改图:

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 检查

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

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 输出的量化精度:

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 子图编译估计延迟:

  • subgraph0424.5 us

原始版 BPU 子图估计延迟是 284.3 us + 80.8 us,但带 CPU/hybrid 切换。 优化版单子图的编译估计延迟略高,实际是否更快要以板端 hrt_model_exec perf 为准。

6. 板端离线验证

.bin 和一个校准输入传到板端,例如:

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/

板端查看模型:

cd /root/go1_pro_deploy/bpu_quant_test
hrt_model_exec model_info --model_file policy_robotlab_15000_int16_gemm.bin

板端测速:

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
  • FPS664.77

优化版板端结果:

  • 平均延迟:0.872819 ms
  • 最大延迟:1.627 ms
  • 最小延迟:0.613 ms
  • FPS1133.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 真实日志对比、悬空状态机测试,再进入地面低速测试。