加载hbm模型报错

:cross_mark: 核心结论

RDK S100 的 BPU 不支持 FP16 加速,强制使用 FP16 会导致模型回退到 CPU 运行,速度极慢。

S100 的 BPU(Nash 架构)是专为 INT8 定点计算 优化的加速器,FP16 并非其原生支持的高效精度。当你将模型量化为 float16 时,BPU 无法有效加速,推理任务会降级到 ARM CPU 执行,导致性能远低于 INT8 模型。


:magnifying_glass_tilted_left: 原因分析

1. BPU 架构特性

  • S100 BPU (Nash-E):专为 INT8 优化,硬件电路针对定点运算设计
  • FP16 支持:部分算子可能支持,但效率远低于 INT8,甚至完全不支持
  • 降级机制:当模型精度不匹配时,系统自动回退到 CPU 执行

2. 性能对比

精度 BPU 加速 典型耗时 (YOLOv8n) 说明
INT8 :white_check_mark: 完全加速 5-10ms 推荐使用
FP16 :cross_mark: 无加速/部分加速 50-200ms 回退到 CPU
FP32 :cross_mark: 无加速 100-500ms 纯 CPU 运行

:white_check_mark: 正确做法:使用 INT8 量化

步骤一:准备校准数据

# 准备 100 张代表性图片(与你的实际应用场景相似)
python3 prepare_calibration.py --input_dir ./dataset --output_dir ./calibration_data --max_images 100

步骤二:配置量化 YAML

model_parameters:
  onnx_model: 'yolov8n.onnx'
  march: nash-e  # S100 必须用 nash-e
  working_dir: 'output_int8'
  output_model_file_prefix: 'yolov8n_int8'

input_parameters:
  input_type_rt: 'nv12'  # 板端输入格式
  input_type_train: 'rgb'
  input_layout_train: 'NCHW'
  scale_value: 0.003921568627451

calibration_parameters:
  cal_data_dir: './calibration_data'
  cal_data_type: 'float32'
  calibration_type: 'default'  # 默认 PTQ 量化

quant_config:
  quantize_mode: 'w8a8'  # 权重和激活都量化为 INT8
  op_config:
    softmax:
      qtype: 'int8'

compiler_parameters:
  optimize_level: 'O2'  # 优化级别
  compile_mode: 'latency'  # 延迟优先

步骤三:执行量化编译

# 在工具链 Docker 中运行
hb_compile -c convert_int8.yaml

步骤四:验证模型精度

# 使用 hb_mapper 检查模型信息
hb_mapper check_model --model yolov8n_int8.hbm

# 确认量化类型为 INT8
# 输出应包含:quantiType: SCALE (表示已量化)

:bar_chart: INT8 vs FP16 性能测试代码

// 在板端测试不同模型的性能
#include <chrono>
#include <iostream>

void benchmark_model(const char* model_path, int iterations = 100) {
    hbDNNPackedHandle_t packed_handle;
    const char* model_file = model_path;
    
    // 加载模型
    hbDNNInitializeFromFiles(&packed_handle, &model_file, 1);
    
    // ... 准备输入输出张量 ...
    
    // 性能测试
    auto start = std::chrono::system_clock::now();
    for (int i = 0; i < iterations; i++) {
        hbUCPTaskHandle_t task = nullptr;
        hbDNNInferV2(&task, outputs, inputs, dnn_handle);
        hbUCPSubmitTask(task, &ctrl_param);
        hbUCPWaitTaskDone(task, 10000);
    }
    auto end = std::chrono::system_clock::now();
    
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    std::cout << "Model: " << model_path << std::endl;
    std::cout << "Average inference time: " << (float)duration / iterations << " ms" << std::endl;
}

int main() {
    std::cout << "=== INT8 Model ===" << std::endl;
    benchmark_model("yolov8n_int8.hbm");
    
    std::cout << "\n=== FP16 Model ===" << std::endl;
    benchmark_model("yolov8n_fp16.hbm");
    
    return 0;
}

:warning: 常见问题

Q1: 为什么我的 INT8 模型精度下降严重?

解决

  • 增加校准数据数量(建议 100-500 张)
  • 确保校准数据覆盖实际场景
  • 对敏感层使用混合精度(在 quant_config.op_config 中指定)
quant_config:
  op_config:
    "model.24.cv2.0.0":
      qtype: "fp16"  # 对特定层使用 FP16
    "model.24.cv3.0.0":
      qtype: "fp16"

Q2: 如何检查模型是否在 BPU 上运行?

# 查看 BPU 利用率
top  # 查看 bpu_monitor 进程

# 或使用官方工具
hb_sys_info

Q3: FP16 模型完全不能用吗?

  • 可以运行,但性能差
  • 适用场景:仅用于快速验证算法逻辑,不用于实际部署
  • 建议:开发阶段用 ONNX 验证,部署必须用 INT8

:books: 参考资源

  1. 完整量化教程RDKS100 模型量化及部署
  2. 工具链文档OpenExplorer 量化指南
  3. Model Zoo 示例rdk_model_zoo_s

:bullseye: 行动建议

  1. 立即重新量化为 INT8:使用 hb_compile 配合校准数据
  2. 验证性能:对比 INT8 和 FP16 的推理耗时
  3. 优化精度:如果 INT8 精度不达标,使用混合精度策略

预期效果:INT8 模型相比 FP16 应有 5-20 倍 的性能提升!