gcw_VI6kTYDH/YOLOv10-518
模型介绍文件和版本Pull Requests讨论分析
下载使用量0

YOLOv10s — 昇腾 Ascend NPU 适配版

本文档记录 YOLOv10s 在华为昇腾 NPU 上的全流程适配、推理优化与精度验证。整体适配路径为:

PyTorch (Ultralytics) → ONNX → onnx2torch → torch_npu → NPU

本仓库完成端到端目标检测 NPU 适配,修复了 YOLOv10 导出 ONNX 模型与 onnx2torch 的兼容性问题,精度无损,单模型实现 51.3× 加速(vs CPU 基线),端到端实现 34.1× 加速(vs CPU 基线),满足实时检测场景基线要求(> 10 FPS)。

目录

  1. 昇腾上落地(本仓库重点)
  2. 环境要求
  3. 快速开始
  4. 推理 API
  5. 精度与性能评测
  6. 优化迭代记录
  7. 技术方案详解
  8. 已知限制与后续优化方向
  9. 引用与许可

1. 昇腾上落地(本仓库重点)

维度内容
模型YOLOv10s (Ultralytics 官方导出)
任务实时目标检测
昇腾芯片Atlas 800I A2 (Ascend910B)
推理框架PyTorch 2.9.0 + torch_npu + CANN 8.5.1
输入尺寸640×640 RGB
数据类型FP32
适配路径PyTorch → ONNX → onnx2torch → torch_npu → NPU
验证状态✅ 精度验证通过(8 路输出 relative error < 1e-7,全部 PASS)
✅ 性能基准通过(单模型 51.3× 加速 vs CPU 基线,88.5 FPS,达标 > 10 FPS)
✅ 运行时优化验证(TASK_QUEUE_ENABLE=2 额外提升 16.2%,105.6 FPS)
✅ 预训练权重验证(官方 YOLOv10s 权重导出,真实检测场景可用)
⏳ GPU 基线对比(建议补充 ONNXRuntime GPU / TensorRT GPU 数据)

适配改造清单

改造项说明
ONNX 导出从 Ultralytics YOLOv10 官方导出 ONNX, imgsz=640, opset=12
Constant 节点修复将 Constant 节点转换为 Initializer,解决 onnx2torch 不兼容问题
Identity 包装消除消除 Identity 节点对 Initializer 的包装,使 Conv 等算子直接引用权重
端到端推理脚本统一 inference.py,支持 NPU/CPU 自动 fallback,含预处理 + NMS-free 后处理
精度验证脚本accuracy_eval.py 逐层对比 NPU/CPU 8 路输出,relative error 统计
性能基准脚本benchmark.py 标准化单模型与 E2E 性能测试,支持 warmup 与多轮迭代
TASK_QUEUE_ENABLE开启 NPU Stream 级并行下发,零代码额外收益;host-bound 场景推荐 TASK_QUEUE_ENABLE=2

模型来源:

  • GitCode: https://gitcode.com/GitHub_Trending/yo/yolov10
  • GitHub: https://github.com/THU-MIG/yolov10

2. 环境要求

2.1 硬件

组件规格
NPUAtlas 800I A2, Ascend910B, 2 逻辑卡
Host CPU鲲鹏 920 64核 @ 2.6GHz
Host 内存229GB

2.2 软件

组件版本(已验证)
Python3.11.14
CANN8.5.1
PyTorch2.9.0+cpu
torch_npu2.9.0.post1+gitee7ba04
onnx2torch1.5.15
onnx1.21.0
opencv-python-headlesslatest
numpylatest
pip install torch==2.9.0+cpu torch_npu==2.9.0.post1
pip install onnx2torch==1.5.15 onnx opencv-python-headless numpy

2.3 环境变量(推荐)

export TASK_QUEUE_ENABLE=1   # NPU Stream 级并行,零代码最大收益
export PER_STREAM_QUEUE=1    # 每个 Stream 独立队列

注意: CPU_AFFINITY_CONF 在容器中效果有限,不自动设置。

3. 快速开始

3.1 环境准备与模型导出

pip install torch==2.9.0+cpu torch_npu==2.9.0.post1
pip install onnx2torch==1.5.15 onnx opencv-python-headless numpy

# 克隆 YOLOv10 仓库并导出 ONNX
git clone https://gitcode.com/GitHub_Trending/yo/yolov10.git
cd yolov10
python -c "from ultralytics import YOLOv10; m=YOLOv10('yolov10s.yaml'); m.export(format='onnx', imgsz=640, opset=12, dynamo=False)"

3.2 修复 ONNX 模型

YOLOv10 导出的 ONNX 包含 Constant 节点和 Identity 包装,需先修复:

cd YOLOv10
python fix_onnx_for_npu.py \
  --model yolov10s.onnx \
  --out yolov10s_fixed.onnx

修复内容:

  1. 将 Constant 节点转换为 Initializer
  2. 消除 Identity 节点对 Initializer 的包装,使 Conv 等算子直接引用权重

3.3 一键验证(推荐,无需真实数据)

cd YOLOv10

# 精度验证(合成数据 NPU vs CPU)
python accuracy_eval.py \
  --model models/yolov10s_fixed.onnx \
  --image /path/to/image.jpg

# 性能基准测试 (NPU)
python benchmark.py --device npu

3.4 运行推理

cd YOLOv10

# NPU 推理
python inference.py \
  --device npu \
  --model models/yolov10s_fixed.onnx \
  --image /path/to/image.jpg \
  --conf 0.25

# CPU fallback
python inference.py \
  --device cpu \
  --model models/yolov10s_fixed.onnx \
  --image /path/to/image.jpg \
  --conf 0.25

4. 推理 API

核心推理类为 YOLOv10Ascend,封装于 inference.py:

from inference import YOLOv10Ascend
import torch

model = YOLOv10Ascend(
    model_path="models/yolov10s_fixed.onnx",
    device=torch.device("npu"),   # 或 torch.device("cpu")
    img_size=640,
    conf_thresh=0.25,
)

boxes, scores, classes = model("/path/to/image.jpg")
  • 自动完成图片读取、resize、归一化、模型推理、NMS-free 后处理全流程
  • boxes: 检测框坐标 [N, 4] (x1, y1, x2, y2)
  • scores: 置信度 [N]
  • classes: 类别索引 [N]

5. 精度与性能评测

5.1 性能基线定义

性能基线是衡量 NPU 加速效果的参照标准。本仓库遵循以下基线定义规范:

基线类型平台 / 配置说明
CPU 基线鲲鹏 920 64核 @ 2.6GHz, PyTorch 2.9.0+cpu与 NPU 同主机,排除网络/内存差异,用于衡量 NPU 相对加速比
GPU 基线(建议补充)NVIDIA V100 / A100, ONNXRuntime GPU / TensorRTYOLOv10 原始生态为 PyTorch,建议补充 GPU 基线以完整评估昇腾竞争力
测试条件img_size=640, batch=1, FP32, warmup=10, iter=50统一输入条件,消除随机性;单模型使用 dummy 输入测吞吐

评测原则: 所有性能数据均在相同输入尺寸、相同 batch size、相同精度条件下测得;NPU 测试前执行 torch.npu.synchronize() 确保计时准确。

5.2 性能评测结果

5.2.1 单模型 Benchmark

测试条件:YOLOv10s, img_size=640, batch=1, FP32, 50 iterations (10 warmup + 50 measured).

设备平均时延 (ms)标准差 (ms)FPS加速比
CPU 基线579.42.231.7—
NPU11.300.0888.551.3×
NPU + TASK_QUEUE=29.470.07105.661.2×

基线判定: 目标 FPS > 10,实测 NPU 88.5 FPS,达标 PASS。

5.2.2 端到端 Benchmark

覆盖预处理 + 模型推理 + NMS-free 后处理全流程:

设备E2E 耗时FPS加速比
CPU 基线586.7 ms1.7—
NPU17.2 ms58.034.1×

E2E 加速比与单模型差距分析:

单模型 benchmark 仅测 model.forward() 耗时,而 E2E 包含预处理(resize/pad/normalize)与后处理(解码/过滤/clip)。当前实测数据拆解:

环节CPUNPU加速比
预处理~2.3 ms~4.0 ms0.6×(NPU 含 H2D 传输)
模型推理~579 ms~11.3 ms51.3×
后处理~0.1 ms~0.2 ms0.5×(含 D2H)
E2E 合计~586 ms~17.2 ms34.1×

结论:E2E 加速比低于单模型是预期现象——预处理在 CPU 上已高度优化(OpenCV),host 侧耗时占比从 CPU 的 0.4% 上升到 NPU 的 23%,导致整体加速比被稀释。后处理已优化为 device 端 clip + 单次 D2H,进一步压缩空间极小。若需继续提升 E2E 吞吐,推荐 batch inference 或 异步流水线 摊薄单图 host 开销。

性能结论:

  • 单模型在 NPU 上获得 51.3× 显著加速,11.30 ms/图,满足实时检测基线(> 10 FPS)
  • 开启 TASK_QUEUE_ENABLE=2 后单模型进一步提升至 61.2×(9.47 ms,105.6 FPS),零代码额外收益 16.2%
  • 端到端获得 34.1× 加速(17.2 ms,58 FPS),生产可用

自证截图:

Benchmark Summary

上图在 Atlas 800I A2 (Ascend910B) 实机运行生成,包含单模型与 E2E 的 CPU/NPU 对比数据。原始日志见 YOLOv10/assets/benchmark_cpu.log 与 YOLOv10/assets/benchmark_npu.log。

5.3 精度验证结果

验证方法:相同输入(随机 tensor 1×3×640×640)下,对比 NPU 与 CPU 的 8 路模型输出。

输出索引Max DiffMean DiffRelative Error判定
Output[0]6.104e-055.483e-089.597e-08PASS
Output[1]3.576e-072.486e-083.100e-08PASS
Output[2]5.960e-083.104e-125.872e-09PASS
Output[3]0.000e+000.000e+000.000e+00PASS
Output[4]6.104e-055.483e-089.597e-08PASS
Output[5]3.576e-072.486e-083.100e-08PASS
Output[6]5.960e-083.104e-125.872e-09PASS
Output[7]0.000e+000.000e+000.000e+00PASS

结论: 全部 8 路输出的 relative error < 1e-7,远低于 1% 阈值,精度达标。

精度验证脚本:

cd YOLOv10
python accuracy_eval.py \
  --model models/yolov10s_fixed.onnx \
  --image /path/to/image.jpg

6. 优化迭代记录

轮次优化项收益说明
R1ONNX 导出 + 修复功能性从 Ultralytics 导出 ONNX,修复 Constant/Identity 节点兼容性问题,打通 YOLOv10 → NPU 链路
R2预训练权重验证性能/功能性使用官方 YOLOv10s 预训练权重导出 ONNX,单模型从随机权重的 76.4ms 降至 11.3ms,真实检测场景可用
R3NPU Stream 并行 (TASK_QUEUE_ENABLE=2)单模型 ↓16.2%零代码改动,运行时层优化,host 端算子并行下发,11.30ms → 9.47ms,额外收益 16.2%
R4后处理 device 端优化E2E post ↓~50%将坐标反归一化与 clip 搬至 NPU 执行,减少 D2H 往返与 Python 循环开销,post 处理耗时进一步降低

7. 技术方案详解

7.1 关键技术点

技术说明
ONNX 修复将 Constant 转 Initializer,消除 Identity 包装,确保 onnx2torch 正确识别 Conv 权重
NPU 零拷贝模型通过 torch_npu 在 NPU 上执行,全流程 tensor 留在 NPU 内存,无 D2H/H2D 切换
NMS-free 后处理YOLOv10 原生无 NMS 设计,后处理仅含解码与阈值过滤,host 侧开销可控
TaskQueueTASK_QUEUE_ENABLE=1/2 开启 Stream 级并行,host 一次性下发算子,AI Core 异步执行

7.2 精度保障

  • 合成数据验证: 8 路输出 NPU vs CPU relative error < 1e-7
  • 修复可复现: fix_onnx_for_npu.py 保证所有用户获得一致的修复后模型
  • 阈值判定: 以 1% relative error 为 PASS 阈值,实测误差低于阈值 5 个数量级

8. 已知限制与后续优化方向

已知限制

限制说明
GPU 基线待同条件实测当前仅提供 CPU 基线对比,缺少 ONNXRuntime GPU / TensorRT 标准基线
E2E 加速比低于单模型预处理/后处理在 host 侧执行,端到端加速比(34.1×)低于纯模型加速比(51.3×)。后处理已优化为 device 端 clip + 单次 D2H,进一步压缩空间极小;若需继续提升 E2E 吞吐,推荐 batch inference 或异步流水线

后续优化方向

方向预期收益说明
预训练权重验证✅ 已完成使用官方 YOLOv10s 预训练权重导出 ONNX,单模型 11.30ms,真实检测场景可用
GPU 基线同条件实测评估完整性在 NVIDIA GPU 环境运行 ONNXRuntime / TensorRT 基准,与 NPU 形成公平对比
预处理 NPU 化实测收益为负在小图(640×640)场景下实测 NPU 预处理 36ms > CPU 预处理 4ms,NPU 算子启动开销大于 CPU 预处理收益,当前 workload 不适用
量化部署延迟/吞吐平衡验证 FP16/INT8 量化在 YOLOv10s 上的精度与性能收益

9. 引用与许可

引用

  • YOLOv10 官方仓库: https://github.com/THU-MIG/yolov10
  • torch_npu 性能调优指南: https://www.hiascend.com/document/detail/zh/Pytorch/730/ptmoddevg/trainingmigrguide/performance_tuning_0001.html

许可

本仓库基于 Apache 2.0 License 开源。

目录结构

YOLOv10-518/
├── README.md                    # 本文档
├── YOLOv10/
│   ├── inference.py             # 统一推理入口 (NPU/CPU 自适应)
│   ├── benchmark.py             # 性能基准测试脚本 (CPU/NPU)
│   ├── accuracy_eval.py         # 精度评测脚本 (NPU vs CPU)
│   ├── fix_onnx_for_npu.py      # ONNX 模型修复工具
│   ├── readme.md                # 部署文档
│   ├── SKILL.md                 # Agent Skill 文档
│   └── logs/                    # 评测运行日志
│       ├── benchmark_cpu.log
│       ├── benchmark_npu.log
│       └── accuracy_eval.log
└── .gitattributes