SAM2 (Segment Anything Model 2) 在华为昇腾 NPU 上的使能方案,支持图像分割推理和训练流程。
| 项目 | 值 |
|---|---|
| 模型名称 | SAM2 (Segment Anything Model 2) |
| 模型 ID | facebook/sam2.1-hiera-large |
| 参数量 | ~1.8 GB |
| 任务 | 图像/视频分割 |
| License | Apache-2.0 |
Sam2VideoModel
├── Sam2VisionModel (Hiera Backbone)
│ ├── Stage 0: embed_dim=144, blocks=2
│ ├── Stage 1: embed_dim=288, blocks=6
│ ├── Stage 2: embed_dim=576, blocks=36
│ └── Stage 3: embed_dim=1152, blocks=4
├── Sam2PromptEncoder
│ └── 点嵌入 + Mask 嵌入
├── Sam2MaskDecoder
│ └── Cross Attention + MLP
└── Memory Attention (视频帧间记忆)| 型号 | 说明 |
|---|---|
| Ascend910 | 已验证 (16 卡) |
| Ascend910B | 兼容 |
| 驱动版本 | 25.5.0 (C23) |
| 软件名 | 版本 |
|---|---|
| CANN | 8.5.1 |
| Python | 3.12.3 |
| torch | 2.11.0 |
| torch-npu | 2.11.0rc1 |
| torchvision | 0.26.0 |
| transformers | 5.5.0 |
| accelerate | 1.13.0 |
| Pillow | 12.2.0 |
在 Ascend NPU 宿主机执行:
# 创建数据目录
mkdir -p /data/npu_adapter/sam2-adapt
# 创建容器
docker run -d \
--name sam2-npu-adapt \
--privileged \
--pid=host \
--device /dev/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
--device /dev/davinci0 \
-v /usr/local/dcmi:/usr/local/dcmi:ro \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi:ro \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/:ro \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info:ro \
-v /etc/ascend_install.info:/etc/ascend_install.info:ro \
-v /data/npu_adapter/sam2-adapt:/data \
--shm-size=16g \
-p 2222:22 \
swr.cn-north-4.myhuaweicloud.com/ascend-sact/ascend-a3-ubuntu:v3.3 \
sleep infinity
# 配置 SSH
docker exec sam2-npu-adapt bash -c "sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config"
docker exec sam2-npu-adapt bash -c "service ssh start"
docker exec sam2-npu-adapt bash -c "echo 'root:<your_password>' | chpasswd"权限说明:
--privileged: 开发测试环境推荐,配置简单- 生产环境可使用
--cap-add=SYS_PTRACE --cap-add=IPC_LOCK --cap-add=SYS_ADMIN替代
进入容器后执行:
# 进入容器
docker exec -it sam2-npu-adapt bash
# 设置环境变量
source /usr/local/Ascend/ascend-toolkit/set_env.sh
export OPENBLAS_NUM_THREADS=1
# 安装 pip
apt-get update && apt-get install -y python3-pip
# 安装依赖
pip3 install torch==2.11.0 torchvision==0.26.0 torch-npu==2.11.0rc1 \
transformers accelerate Pillow requests scipy opencv-python \
--break-system-packages -i https://pypi.tuna.tsinghua.edu.cn/simplesource /usr/local/Ascend/ascend-toolkit/set_env.sh
export OPENBLAS_NUM_THREADS=1
python3 -c "import torch; import torch_npu; print('NPU available:', torch_npu.npu.is_available()); print('NPU count:', torch_npu.npu.device_count())"cd /data
python run_inference_npu.py --image https://huggingface.co/datasets/hf-internal-testing/sam2-fixtures/resolve/main/truck.jpg --output mask.png预期输出:
Loading SAM2 model: facebook/sam2.1-hiera-large
Device: npu:0
NPU available: True
NPU count: 16
Model loaded successfully
Loading image: https://...
Image size: (1800, 1200)
Running single-point segmentation...
Results:
Inference time: 0.494s
Output masks shape: torch.Size([1, 3, 1200, 1800])
Number of predictions: 3
Mask saved to: mask.png
=== SAM2 NPU inference completed ===准备训练数据集,目录结构如下:
data/
├── images/ # 图像文件 (*.jpg, *.png)
│ ├── image_001.jpg
│ ├── image_002.jpg
│ └── ...
├── masks/ # 对应的分割 mask (*.png)
│ ├── image_001.png
│ ├── image_002.png
│ └── ...
└── annotations.json # 点/框标注(可选)说明: mask 文件应为二值图像(白色=目标区域,黑色=背景),尺寸与对应图像一致。
cd /data
python run_train_npu.py --data_dir /data/dataset --epochs 10 --batch_size 4 --lr 1e-5预期输出:
=== SAM2 NPU Training ===
Device: npu:0
NPU available: True
NPU count: 16
Loading dataset from: /data/dataset
Loaded 100 images for train
Starting training for 10 epochs...
==================================================
Epoch 1/10
------------------------------
Batch 0/25, Loss: 3.4145
Batch 10/25, Loss: 2.8934
Batch 20/25, Loss: 2.4567
Epoch 1 - Average Loss: 2.7234
Epoch time: 45.2s
Checkpoint saved: ./output/checkpoint_epoch_5.pt
...
Epoch 10/10
------------------------------
Average Loss: 0.8765
Checkpoint saved: ./output/checkpoint_epoch_10.pt
==================================================
Training completed!
Final checkpoint saved to: ./output
==================================================| 参数 | 说明 | 默认值 |
|---|---|---|
--model | 模型 ID 或路径 | facebook/sam2.1-hiera-large |
--device | 训练设备 | npu:0 |
--data_dir | 数据集目录 | 必需 |
--output_dir | 输出目录 | ./output |
--epochs | 训练轮数 | 10 |
--batch_size | 批大小 | 4 |
--lr | 学习率 | 1e-5 |
--gradient_checkpointing | 启用梯度检查点(节省显存) | False |
# 使用 torchrun 启动分布式训练
source /usr/local/Ascend/ascend-toolkit/set_env.sh
export OPENBLAS_NUM_THREADS=1
torchrun --nproc_per_node=8 \
run_train_npu.py \
--data_dir /data/dataset \
--epochs 10 \
--batch_size 2 \
--lr 1e-5说明:
--nproc_per_node=8: 使用 8 张 NPU 卡- 分布式训练会自动使用 HCCL backend
- 批大小为每卡的批大小,总批大小 = batch_size × nproc
大图像训练(1024x1024)可能显存不足,推荐:
# 启用梯度检查点
python run_train_npu.py --data_dir /data/dataset --gradient_checkpointing
# 或减小批大小
python run_train_npu.py --data_dir /data/dataset --batch_size 1# 从 checkpoint 恢复
python run_train_npu.py --data_dir /data/dataset --resume ./output/checkpoint_epoch_5.pt本模型需要加载兼容层脚本 npu_compat.py,主要修复:
NPU 的 GELU 算子要求输入 tensor 是 contiguous 的:
# 使用兼容层
from npu_compat import apply_npu_compat
apply_npu_compat()
# 或者手动修复
import torch.nn.functional as F
_original_gelu = F.gelu
def gelu_contiguous(input, approximate="none"):
if input.device.type == "npu":
input = input.contiguous()
return _original_gelu(input, approximate=approximate)
F.gelu = gelu_contiguous| 组件 | 推荐版本 | 说明 |
|---|---|---|
| torch | 2.11.0 | 与 torch-npu 2.11.0rc1 配套 |
| torch-npu | 2.11.0rc1 | 支持 CANN 8.5.x |
| transformers | 5.5.0 | SAM2 原生支持 |
NPU 访问需要特权操作,原因:
| 操作 | 说明 |
|---|---|
| 内核级系统调用 | ioctl、内存映射等 |
| 硬件管理接口 | 与 NPU 固件通信 |
| 共享内存操作 | NPU 与主机内存交互 |
--device 只提供设备文件访问权限,不包含驱动初始化所需的内核能力。
错误表现(权限不足时):
drvErr=87 (driver internal error)
EL0005: Resource_Busy| 指标 | 值 |
|---|---|
| 平均延迟 | 92.50 ms |
| P50 | 92.46 ms |
| P95 | 92.89 ms |
| P99 | 93.03 ms |
| FPS | 10.81 |
| 指标 | 值 |
|---|---|
| Peak Allocated | 1.64 GB |
| Peak Reserved | 2.45 GB |
| Batch Size | 延迟 (ms) | 吞吐量 (img/s) |
|---|---|---|
| 1 | 92.19 | 10.85 |
| 2 | 168.37 | 11.88 |
| 4 | 310.78 | 12.87 |
NPU 输出与 CPU 参考输出对比:
| 测试点 | IoU | 像素准确率 | 状态 |
|---|---|---|---|
| 中心点 | 0.9880 | 99.95% | ✅ |
| 左上点 | 0.9959 | 99.98% | ✅ |
| 右下点 | 0.9997 | 99.99% | ✅ |
| 步骤 | 状态 |
|---|---|
| 前向传播 | ✅ |
| 损失计算 | ✅ |
| 反向传播 | ✅ |
| 梯度计算 | ✅ |
| 优化器步骤 | ✅ |
原因: 容器缺少必要的权限参数
解决: 确保容器启动时添加 --privileged --pid=host 参数
原因: NPU 算子要求 contiguous tensor
解决: 使用 npu_compat.py 兼容层,或在推理脚本开头调用 apply_npu_compat()
原因: torchvision 可能拉入不兼容的 torch 版本
解决: 先安装 torch-npu,再安装 torchvision,或使用推荐的版本组合
原因: 容器无法访问 NPU 驱动(权限不足)
解决:
npu-smi info)--privileged 参数sam2-npu-adapt/
├── README.md # 本文档
├── run_inference_npu.py # 推理脚本
├── npu_compat.py # NPU 兼容层
├── run_train_npu.py # 训练脚本(可选)
└── create_container.sh # 容器创建脚本使能完成时间: 2026-04-07
验证完成时间: 2026-04-10
使能状态: ✅ 推理、训练、精度、性能验证全部通过