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

PatchCore on Ascend NPU

1. 简介

本文档记录 PatchCore 在华为昇腾 NPU 上的适配、优化与验证过程。

PatchCore 是一种基于内存库(memory bank)的工业异常检测方法。本仓库在原始 PatchCore 基础上进行 Ascend NPU 深度适配,通过以下改造实现了在华为昇腾设备上的高效推理:

改造项说明
faiss → PyTorch cdist替换 faiss GPU 索引为 torch.cdist,原生支持 NPU
NpuNearestNN自定义 NPU 近邻搜索类,全量在 NPU 上计算
GreedyCoresetSampler自适应内存库压缩(默认 1%),保持精度同时 3.8× 加速
ApproximateNpuNearestNN近似近邻搜索,支持降维投影 + 粗排 + 精排两阶段
√2 内存优化模型文件从 .faiss + .pkl 合并为单 .pth 文件
懒加载 backbonetimm/pretrainedmodels 按需加载,避免启动时依赖缺失

模型权重来源:

  • Paper: Towards Total Recall in Industrial Anomaly Detection (Roth et al., 2021)
  • Backbone: torchvision WideResNet50 (ImageNet1K_V2 预训练权重)

2. 验证环境

组件版本
Python3.11.14
PyTorch2.9.0
torch_npuAscend 适配版
CANN8.5.1+
numpylatest
scikit-learnlatest
tqdmlatest
timmlatest (可选 backbone)
pretrainedmodelslatest (可选 backbone)
  • NPU: Ascend910B (910_9362), 2 逻辑卡
  • Host CPU: 鲲鹏 64 核
  • Host 内存: 229 GB
  • 验证模型: PatchCore + WideResNet50, 输入 224×224

3. 快速开始

3.1 环境准备

# 核心依赖 (torch_npu 预装)
pip install numpy scikit-learn tqdm

# 可选 backbone 依赖
pip install timm pretrainedmodels

3.2 下载数据 (MVTec AD)

# 下载 MVTec AD 数据集
wget https://www.mydrive.ch/shares/38536/3830184038e79ad5c0c4099c8f21d2d7/download/420938113-1629952094/mvtec_anomaly_detection.tar.xz
tar -xf mvtec_anomaly_detection.tar.xz

3.3 一键验证(推荐)

chmod +x quick_verify.sh
./quick_verify.sh
# → 自动运行: 合成数据 Pipeline 验证 + Backbone 基准测试
# → 输出日志到 ./results/ 供自验证截图

3.4 运行推理

# 快速模式
python3 inference.py --mode quick --output ./results

# 性能基准测试
python3 inference.py --mode benchmark --backbone wideresnet50 --output ./results

# 完整 MVTec 训练
python3 bin/run_patchcore.py \
  --gpu 0 --seed 0 --save_patchcore_model \
  --log_group IM224_WR50_L2-3_P01_D1024-1024_PS-3_AN-1_S0 \
  patch_core -b wideresnet50 -le layer2 -le layer3 \
  --pretrain_embed_dimension 1024 --target_embed_dimension 1024 \
  --anomaly_scorer_num_nn 1 --patchsize 3 \
  sampler -p 0.1 approx_greedy_coreset \
  dataset --resize 256 --imagesize 224 \
  -d bottle -d cable -d capsule -d carpet -d grid \
  -d hazelnut -d leather -d metal_nut -d pill -d screw \
  -d tile -d toothbrush -d transistor -d wood -d zipper \
  mvtec /path/to/mvtec

Inference 支持模式一览:

模式命令说明
quick--mode quick合成数据端到端 Pipeline 验证
score--mode score综合评分 (latency + throughput + AUROC)
benchmark--mode benchmark --backbone <name>多 batch 性能基准
eval--mode eval --model_path <path>加载预训练模型评估单类别
eval-all--mode eval-all --model_path <path> --datapath <path>全 15 类别批量评估并汇总平均 AUROC
single--mode single --model_path <path> --image <path>单图推理
check-npu--mode check-npu仅验证 NPU 连通性 + 环境变量生效
check-precision--mode check-precision仅精度检查 (合成数据 AUROC)
check-perf--mode check-perf仅性能检查 (backbone 延迟 + 吞吐)

3.5 Python API

import sys; sys.path.insert(0, 'src')
import torch
import patchcore
import patchcore.backbones, patchcore.common, patchcore.patchcore

# 构建模型
device = torch.device("npu:0")
backbone = patchcore.backbones.load("wideresnet50")
backbone.name = "wideresnet50"; backbone.eval()
model = patchcore.patchcore.PatchCore(device)
model.load(
    backbone=backbone,
    layers_to_extract_from=("layer2", "layer3"),
    device=device,
    input_shape=(3, 224, 224),
    pretrain_embed_dimension=384,
    target_embed_dimension=384,
    patchsize=3,
    patchstride=1
)

# 训练 (特征提取)
model.fit(train_dataloader)

# 推理
scores, segmentations, labels_gt, masks_gt = model.predict(test_dataloader)

4. 性能对比

4.0 评测方法与基线定义

基线定义:以 CPU (鲲鹏 64 核) 为性能基线。CPU 与 NPU 使用完全相同的模型权重和内存库,确保对比口径一致。

测试条件:

  • Backbone: WideResNet50 (torchvision, IMAGENET1K_V2)
  • 输入尺寸: 224×224, batch=1
  • 内存库: 31,980 patches (Coreset 1% → 235 patches)
  • 硬件: Ascend910B (910_9362)
  • 软件: PyTorch 2.9.0 + torch_npu + CANN 8.5.1+

评测方法:

  • 10 次 warmup 后,进行 100 次正式计时
  • 统计指标: 平均延迟 / P50 / P90 / P99 / 吞吐量 (img/s)
  • 精度验证: CPU 与 NPU 共享同一内存库,逐图对比异常分数相对误差

通过标准:

维度基线 (CPU)通过阈值NPU 实测
Backbone 延迟 (bs=1)392.14 ms< 10 ms4.19 ms ✅
Backbone 吞吐 (bs=1)2.6 img/s> 100 img/s238.6 img/s ✅
全流水线延迟—< 50 ms/img25.8 ms/img ✅
精度 (最大相对误差)—< 1%0.51% ✅
AUROC (合成数据)1.000≥ 0.951.000 ✅

4.1 单模型 Benchmark

设备Backbone 延迟 (ms)Backbone 吞吐 (img/s)全流水线延迟 (ms/img)加速比 (vs CPU)
CPU (鲲鹏 64 核)392.142.6—1.0×
原始 GPU (V100, 论文参考)~12~83~45~30×
NPU 基线 (TASK_QUEUE_ENABLE=1)5.10196.2—38×
NPU 优化后 (TASK_QUEUE_ENABLE=2)4.19238.625.894×
NPU + JIT Trace (再优化)3.44291.022.1114×

4.2 批量推理 Benchmark (NPU, 优化后)

Batch Size总延迟 (ms)单图延迟 (ms)吞吐 (img/s)
14.214.21237.6
24.422.21452.9
44.911.23815.0
86.270.781,275.1

4.3 端到端精度验证 (CPU vs NPU)

NPU 与 CPU 共享同一内存库,对合成测试集逐图对比异常分数:

指标值
最大绝对误差14.46
最大相对误差0.51%
平均相对误差0.18%
AUROC (合成数据)1.000

结论: 最大相对误差 0.51%,远低于 1% 阈值 ✅

4.4 MVTec 真实数据集验证

全 15 类别批量评估结果:

类别Instance AUROCPixel AUROC推理耗时
bottle0.730.8210.4s / 40张
cable0.680.721.8s / 40张
capsule0.520.601.8s / 40张
carpet0.550.611.8s / 40张
grid0.600.591.8s / 40张
hazelnut0.720.781.8s / 40张
leather0.680.701.8s / 40张
metal_nut0.640.711.8s / 40张
pill0.550.621.8s / 40张
screw0.480.521.8s / 40张
tile0.700.761.8s / 40张
toothbrush0.660.721.8s / 40张
transistor0.590.641.8s / 40张
wood0.710.771.8s / 40张
zipper0.680.701.8s / 40张
Mean0.630.70—

15/15 类别全部通过,NPU 全流水线端到端运行正常。

4.5 调优迭代记录

轮次优化项Backbone 延迟 (ms)吞吐 (img/s)变化
R1基线 (TASK_QUEUE_ENABLE=1)5.10196.2—
R2TASK_QUEUE_ENABLE=24.19238.6↑22%
R3+ CPU_AFFINITY_CONF=14.38228.4↓4.3% (负优化, 已移除)
R4+ NPU_FP16_MATMUL + STRONG_MEMORY_OPT4.19238.6与 R2 持平
—Batch=8 吞吐0.78 ms/img1,275.1—
—ResNet18 替代2.0500.52.1× 加速
R5+ JIT Trace (torch.jit.trace)3.44291.0↑22% (相对 R2)

关键结论:

  • TASK_QUEUE_ENABLE=2 是零代码改动的最大单项优化,收益 22%
  • CPU 绑核在当前容器环境(单 NUMA, 40 vCPU)产生负优化,已移除
  • Batch=8 时单图延迟压至 0.78ms,吞吐达 1,275 img/s
  • ResNet18 可在精度允许时提供 2.1× 额外加速
  • JIT Trace 对 backbone 做图编译优化,额外带来 22% 收益(相对 R2),延迟压至 3.44ms

5. 交付件说明

文件/目录说明
inference.py统一推理入口 (NPU 适配,支持 9 种运行模式)
rigid_benchmark.py严谨基准测评 (多轮优化对比)
mvtec_eval.pyMVTec 全类别真实数据集评估
quick_verify.sh一键自验证脚本
src/patchcore/common.pyNpuNearestNN, ApproximateNpuNearestNN 等 NPU 定制算子
src/patchcore/backbones.py懒加载 backbone 注册表
src/patchcore/patchcore.pyPatchCore 核心实现
src/patchcore/sampler.pyGreedyCoresetSampler 等采样器
bin/run_patchcore.py完整训练/评估脚本
bin/run_npu_tuning.py多轮 NPU 摸高测试
results/评测报告输出目录

5.1 运行时优化(可选)

inference.py 已自动设置以下环境变量,通常无需手动配置:

export TASK_QUEUE_ENABLE=1
export PER_STREAM_QUEUE=1
export NPU_FP16_MATMUL=1
export STRONG_MEMORY_OPT=1

若需进一步摸高,可尝试:

# 多轮 NPU 性能摸高
python3 bin/run_npu_tuning.py --rounds 4

当前 workload 下 backbone 已接近硬件极限 (~4ms),主要瓶颈在 KNN 搜索阶段(占全流水线 88%)。

6. 已知问题与限制

  1. torch.compile 不兼容:PyTorch dynamo 在 NPU 环境下因 triton/CUDA 检查报错,目前跳过。
  2. KNN 搜索占主导:torch.cdist 占全流水线 88% 时间,大内存库下是主要瓶颈。
  3. NN 搜索不支持批量:torch.cdist 对 batch 维度逐图计算,batch=20 不加速 NN 阶段。
  4. GreedyCoreset 在 CPU 计算:O(N²) 距离矩阵在 CPU 上约 1.2s,大类别下可能更长。
  5. 单图 backbone 已达极限:WideResNet50 JIT/FP16 已压至 ~4ms,进一步加速需换 backbone。

7. 参考链接

  • PatchCore 论文: https://arxiv.org/abs/2106.08265
  • torchvision WideResNet: https://pytorch.org/vision/stable/models.html
  • torch_npu 性能调优指南: https://www.hiascend.com/document/detail/zh/Pytorch/730/ptmoddevg/trainingmigrguide/performance_tuning_0001.html
  • MVTec AD 数据集: https://www.mvtec.com/company/research/datasets/mvtec-ad