竞赛提交: BlendMask 实例分割模型在华为昇腾 800I A2 NPU 上的适配与性能优化
提交日期: 2025-05-19
提交者: v50_
原始权重: AdelaiDet
调优仓库: blendmask-opt
将 BlendMask (CVPR 2021) 实例分割模型适配到 华为昇腾 800I A2 NPU (910B4),实现推理性能优化。
| 项目 | 说明 |
|---|---|
| 模型 | BlendMask (R_50_1x) — CVPR 2021,基于 AdelaiDet 框架的实例分割模型 |
| 骨干网络 | ResNet-50 + FPN |
| 输入尺寸 | 800 × 1333(固定,batch size = 1) |
| 数据类型 | FP32 全精度推理 |
| 数据集 | COCO2017 val(验证集,5000 张图片,80 个类别) |
| 评估指标 | bbox AP / segm AP(COCO API 标准评估) |
| 硬件 | 华为昇腾 800I A2 NPU (910B4) × 1 |
| 指标 | Baseline (原生推理) | Optimized (亲和算子+TQE=2+CPU绑核) | 对比 |
|---|---|---|---|
| 推理延迟 (bs=1) | 95.52 ms | 81.05 ms | +17.7% ✅ |
| FPS | 10.48 | 12.34 | +17.7% ✅ |
| bbox AP | 40.3003% | 40.3003% | +0.00007% ✅ |
| segm AP | 35.7979% | 35.7980% | +0.0002% ✅ |
Baseline 定义: 原生无优化的 NPU 推理(零补丁、零 TQE 配置、零调度优化)
| 要求项 | 数值 | 测量条件 |
|---|---|---|
| Baseline FPS | 10.48 | NPU 热态,连续推理 ≥50 轮预热后取均值,无任何补丁/TQE 配置 |
| Baseline 延迟 | 95.52 ms | 同上 |
| 目标加速比 | ≥ 1.00x | 相对原生无优化 Baseline(实际 +17.7%,亲和算子替换 + TQE=2 + CPU 绑核) |
| 精度差异 | bbox/segm AP < 1% | COCO2017 val 全量 5000 张 |
| 输入尺寸 | 800 × 1333 (固定) | Batch size = 1 |
| 数据类型 | FP32 | 全精度推理 |
基线完全不启用 TASK_QUEUE_ENABLE、不加载任何 NPU 亲和算子补丁、不修改任何模型代码。所有优化手段(TQE=2、算子替换、绑核等)均在 Opt1 优化后 中启用,并作为加速比计算的分母。
| 文件 | 说明 |
|---|---|
opt1_npu_patches/npu_patch.py | NPU 亲和算子补丁(核心交付) |
setup_env.sh | 环境一键配置脚本 |
requirements.txt | Python 依赖 |
run_all.sh | 一键验证所有步骤 |
adet_patches/ | P0-P5 全优化管线代码(研究用,含全部尝试记录) |
optimization_plan.md | 完整调优计划(含 10 维度模型分析) |
SKILL.md | 可复用的调优技能文档 |
scripts/ | 统一工具脚本(benchmark/accuracy/profiler/logger) |
baseline_benchmark.json | Baseline 性能数据 |
optimized_benchmark_final.json | 最终优化结果 |
results_screenshots/ | 评测截图、Profiling 数据 |
experiments/
├── 00_baseline/ # ✅ Baseline 基准
│ ├── run.sh, results.json, README.md
├── 01_profiling/ # ✅ Profiling 分析
│ ├── analysis.md, profiling_summary.txt
├── 02_roi_align_npu/ # ✅ ROIAlign NPU 替换
│ ├── run.sh
├── 03_nms_npu/ # ✅ NMS NPU 替换
│ ├── run.sh
├── 04_task_queue/ # ✅ TQE 扫参
│ ├── run.sh (TQE=0/1/2)
├── 05_cpu_binding/ # ✅ CPU 绑核扫参
│ ├── run.sh (7种绑核策略)
├── 06_amp/ # ❌ FP16 AMP(已排除留档)
│ ├── conclusion.md
└── 07_graph_mode/ # ❌ 图模式(已排除留档)
└── conclusion.md每个实验目录遵循统一规范:run.sh(运行入口)、results.json(性能数据)、README.md(实验说明)。
| 组件 | 版本 |
|---|---|
| 硬件 | Ascend 800I A2 (910B4) NPU × 1 |
| CANN | 24.1.rc3 |
| Python | 3.10 |
| PyTorch | 2.7.1+cpu |
| torch_npu | 2.7.1 |
| AdelaiDet | main (FORCE_CUDA=0 编译) |
# 激活环境
conda activate blendmask-npu
# 安装依赖
pip install opencv-python-headless pycocotools numba
# 或一键配置
bash setup_env.sh关键编译参数: FORCE_CUDA=0 — 跳过所有 CUDAExtension,只编译 CppExtension。
| 版本 | 优化项 | 延迟 | FPS | 加速比 | 状态 |
|---|---|---|---|---|---|
| Baseline | 原生 NPU 推理 (热态) | 95.52ms | 10.48 | 1.00x | 🏁 竞赛基线 |
| 🏆 Optimized | npu_roi_align + npu_nms_with_mask + TQE=2 + CPU绑核(0-7) | 81.05ms | 12.34 | 1.177x ✅ | 🏆 最终提交 |
| 🏆 Opt1+TQE=2+CPU绑核(4-7) | 同上,绑核4-7 | 80.39ms | 12.44 | 1.187x ✅ | 🏆 备选 |
| P0 | 亲和算子替换 (npu_roi_align + npu_nms_with_mask) | 96.50ms | 10.36 | 0.99x | ⚠️ 单算子替换 |
| torch.compile + npugraph_ex | 146.50ms | 6.82 | 0.77x | ❌ 不兼容 |
数据集: COCO2017 val 全量 5000 张
评估工具: COCO API (evaluate img_ids 精确过滤)
| 指标 | Baseline (原生) | Opt1 (优化后) | 差异 |
|---|---|---|---|
| bbox AP | 40.3003 | 40.3003 | +0.00007% ✅ |
| bbox AP50 | 59.2343 | 59.2343 | +0.0000% ✅ |
| bbox AP75 | 43.6866 | 43.6866 | +0.0000% ✅ |
| segm AP | 35.7979 | 35.7980 | +0.0002% ✅ |
| segm AP50 | 56.3463 | 56.3464 | +0.0002% ✅ |
| segm AP75 | 38.1398 | 38.1398 | +0.0000% ✅ |
全量 COCO val 精度评估截图(5000 张)— Baseline vs Opt1 修复版所有指标完全一致
✅ 结论: 精度差异仅 +0.00007%~0.0002%,远小于 1% 赛道要求,合规通过。
torch_npu.npu_nms_with_mask 要求输入已按分数降序排列,添加排序逻辑后精度与 GPU 完全对齐# 1. 激活 conda 环境
conda activate blendmask-npu
# 2. 确保 AdelaiDet 已安装
cd /path/to/AdelaiDet
export FORCE_CUDA=0
python setup.py build develop# Baseline(热态,匹配竞赛条件)
cd baseline
bash run_baseline.sh
# Opt1
cd opt1_npu_patches
export TASK_QUEUE_ENABLE=2
python3 benchmark_opt1.py \
--config-file configs/BlendMask/R_50_1x.yaml \
--input /path/to/coco/val2017 \
--output opt1_benchmark.json \
--min-size-test 800 --max-size-test 1333 \
--max-images 10 \
MODEL.WEIGHTS /path/to/R_50_1x.pth \
MODEL.DEVICE npu:0# 全量 COCO val 精度验证(5000 张)
python3 coco_map_eval.py \
--config-file configs/BlendMask/R_50_1x.yaml \
--weights /path/to/R_50_1x.pth \
--device npu:2bash run_all.sh| 文件 | 内容 |
|---|---|
results_screenshots/npu_smi_info.txt | NPU 设备信息(8×910B4) |
results_screenshots/eval_report_terminal.txt | 终端运行记录(Baseline/Opt1/精度) |
results_screenshots/profiling_summary.txt | MSprof Profiling 总结(Top 算子耗时) |
results_screenshots/eval_accuracy_opt1_full.png | 全量COCO val精度评估截图 — Baseline vs Opt1 完全一致 ✅ |
| 原生算子 | 替换算子 | 加速效果 | 位置 |
|---|---|---|---|
torchvision.ops.roi_align | torch_npu.npu_roi_align | 5.79x | Blender 模块 (TopLayer) |
detectron2.layers.batched_nms | torch_npu.npu_nms_with_mask (per-class) | 3.24x | 后处理 (BlendNMS) |
环境适配: 在 torch_npu 2.7.1 上实测,
npu_roi_align可正常使用(warm-up 零值 bug 已修复)。npu_nms_with_mask已废弃但功能正常(输出正确),抑制废弃警告不影响结果。
export TASK_QUEUE_ENABLE=2 # 启用 TaskQueue 双缓冲调度将推理进程绑定到指定 CPU 核,减少 NPU 驱动调度时的 NUMA 跨节点开销:
taskset -c 0-7 python3 benchmark_opt1.py ... # CPU 0-7 (+19%)
taskset -c 4-7 python3 benchmark_opt1.py ... # CPU 4-7 (+20%)NPU NMS 内核要求输入已排序(按分数降序),需要添加排序逻辑:
scores, sorted_indices = scores.sort(descending=True)
boxes = boxes[sorted_indices]
keep = npu_nms_with_mask(boxes, scores, iou_threshold)首次调用 NPU kernel 编译时返回全零,使用 CPU fallback 规避:
if not _warmup_done:
roi_align_cpu(...) # 首次 CPU 推理
_warmup_done = True| 方向 | 原因 |
|---|---|
| 图模式 (torch.compile) | bottom_up 编译成功(24→12ms),但需 TQE=1,丢失全局调度收益 |
| 图模式 + TQE=2 | 运行时崩溃,不兼容 |
| npu_batch_nms | API 签名复杂(padding mask 等输入格式),适配成本高 |
| Conv+BN 融合 | detectron2 加载 checkpoint 时已自动完成 |
| FP16 AMP | Conv2D 要求输入类型与权重类型一致,NPU 不兼容混精度 |
| tcmalloc | AdelaiDet 为单进程推理,多线程竞争不显著 |
torchvision::nms 回退警告: 不影响结果,可通过日志等级抑制@torch.no_grad() 废弃警告: MEInst 模块中类装饰器用法,无功能影响npu_roi_align 路径正常。npu_nms_with_mask 已废弃但输出正确,已抑制废弃警告。