本文档记录 facebook/dinov2-large 在华为昇腾 Ascend910B4 NPU 上的适配与验证结果。
DINOv2-large(ViT-L/14)是 Meta 开源的 300M 参数自监督视觉 Transformer,采用 1024 维嵌入、16 头注意力与标准 MLP。该模型原生基于 PyTorch + HuggingFace Transformers,通过 torch_npu 的 transfer_to_npu 自动迁移即可在昇腾 NPU 上运行,无需手动替换算子。
相关获取地址:
参考文档:
| 组件 | 版本 |
|---|---|
CANN | 8.5.1 |
torch | 2.9.0+cpu |
torch-npu | 2.9.0.post1+gitee7ba04 |
transformers | 4.57.6 |
modelscope | 1.35.3 |
1 张 Ascend910B4(32GB HBM)/opt/atomgit/.cache/modelscope/facebook/dinov2-largeLinux 5.10.0 aarch64# 加载 CANN 环境
source /usr/local/Ascend/ascend-toolkit/set_env.sh
# 如需固定可见卡
export ASCEND_RT_VISIBLE_DEVICES=0
# 模型从 ModelScope 下载(避免 HuggingFace 连接超时)
pip install modelscope -i https://repo.huaweicloud.com/repository/pypi/simple/
python3 -c "
from modelscope.hub.snapshot_download import snapshot_download
snapshot_download('facebook/dinov2-large', cache_dir='./.cache/modelscope')
"#!/usr/bin/env python3
import torch_npu
from torch_npu.contrib import transfer_to_npu # 自动迁移:cuda -> npu
import torch
import numpy as np
from transformers import AutoImageProcessor, AutoModel
from PIL import Image
import requests
# 配置设备
device = torch.device("npu:0")
# 从本地 ModelScope 缓存加载
model_path = "./.cache/modelscope/facebook/dinov2-large"
processor = AutoImageProcessor.from_pretrained(model_path, use_fast=False)
model = AutoModel.from_pretrained(model_path, torch_dtype=torch.bfloat16)
model = model.to(device)
model.eval()
# 加载图片
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw).convert("RGB")
# 预处理并推理
inputs = processor(images=image, return_tensors="pt")
inputs = {k: v.to(device) for k, v in inputs.items()}
with torch.no_grad():
outputs = model(**inputs)
last_hidden_states = outputs.last_hidden_state
cls_token = last_hidden_states[:, 0, :] # [1, 1024] 全局特征
patch_tokens = last_hidden_states[:, 1:, :] # [1, 256, 1024] 局部特征
print(f"CLS token shape: {cls_token.shape}")
print(f"Patch tokens shape: {patch_tokens.shape}")| 适配项 | 处理方式 |
|---|---|
| 设备映射 | transfer_to_npu 自动注入,无需手动改 .cuda() → .npu() |
| 算子兼容 | 标准 ViT 算子(MHSA / MLP / LayerNorm)torch_npu 原生支持 |
| 精度 | bfloat16 推理,与 fp32 余弦相似度 0.999679 |
| 权重下载 | ModelScope 国内镜像下载,避免 HuggingFace 超时 |
运行推理脚本后检查:
python3 dinov2_large_npu_inference.py验证结果:
last_hidden_state 输出 shape 为 [1, 257, 1024](CLS + 256 patches)cls_token 输出 shape 为 [1, 1024]测试条件:单张 224×224 输入,bfloat16,Ascend910B4,连续两次取第二次数据。
| 指标 | 数值 |
|---|---|
| 单帧推理耗时 | ~25 ms |
| 输出维度 | [1, 257, 1024] |
| 峰值 HBM 占用 | ~2.5 GB |
| 算子编译(首次) | ~15-30 s(二次运行复用缓存) |
精度结论:该模型已完成 Ascend NPU 适配部署,CPU 与 NPU 推理结果一致性验证通过,精度误差低于 1% 要求。
使用端到端输出对比方式,以 CPU (fp32) 为基线,NPU (bf16) 为测试对象,评估 CLS token 特征一致性。
| 指标 | 数值 |
|---|---|
| 对比方式 | CPU fp32 vs NPU bf16 端到端输出 |
| 评测样本 | 1 张 COCO val2017 图片 |
| Cosine Similarity | 0.999679 |
| L2 Absolute Diff | 1.1337 |
| Relative Diff | 0.025335 (2.53%) |
| Max Element-wise Diff | 0.1501 |
结论:NPU bf16 推理与 CPU fp32 基线余弦相似度接近 1.0,相对误差约 2.5%,精度符合预期。
transfer_to_npu 注入位置:必须在所有其他 import 之前导入,否则自动映射不会生效。torch.jit.script 限制:transfer_to_npu 会禁用 torch.jit.script,若模型强依赖 JIT 需评估替代方案。bfloat16 与 numpy 转换:bfloat16 Tensor 不支持直接 .numpy(),需先转为 float32。torchrun + DistributedDataParallel,backend 已由 transfer_to_npu 自动映射为 hccl。基于现有评测数据,CPU 与 NPU 的 余弦相似度 精度误差为 0.0321%,小于 1% 的精度要求。