小模型在昇腾NPU上的推理部署:【小模型算力切分实践案例】
作者:昇腾实战派
知识地图:https://blog.csdn.net/Lumos_Lovegood/article/details/161601003
背景概述
随着小模型在特定任务上展现出接近甚至超越大模型的推理能力,“专而精”的小模型在资源受限场景下优势明显。与此同时,华为Ascend系列算力卡进入市场后,用户对算力资源隔离与整体利用率提升的需求日益迫切。通过资源虚拟化技术,将物理NPU切分为多个vNPU挂载到容器中,可实现统一资源分配与回收,满足多用户频繁申请/释放资源的操作需求。本文以静态虚拟化方式,在昇腾推理服务器裸机上提供小模型RECCE的切分案例及理论指导。
1 解决方案
1.1 方案介绍
当前划分vNPU主要有静态虚拟化和动态虚拟化两种方式。本文以静态虚拟化为主,采用Docker部署方式。
- 静态虚拟化:通过npu-smi工具手动创建多个vNPU,支持物理机和虚拟机场景。
- 动态虚拟化:通过软件配置,在收到虚拟化任务请求后动态创建vNPU、挂载任务并回收资源。
将vNPU挂载到容器有以下方案:
-
原生Docker:仅支持静态虚拟化,通过Docker拉起容器时将vNPU挂载到容器。注意:不支持通过原生Containerd拉起容器时挂载vNPU。安装Docker及挂载vNPU的指导请参考:多容器场景下安装 - Atlas 中心训练服务器 25.2.0 NPU驱动和固件安装指南 02 - 华为
-
结合MindCluster组件:
- 静态虚拟化:通过npu-smi工具提前创建多个vNPU,基于Ascend Device Plugin实现设备发现、分配与健康状态上报,Volcano组件为可选。
- Ascend Docker Runtime:单独使用,支持静态和动态虚拟化,通过容器引擎插件拉起容器时挂载vNPU。
- Kubernetes:结合MindCluster组件(Ascend Device Plugin、Volcano),通过Kubernetes拉起容器时挂载vNPU,支持静态和动态虚拟化。
1.2 vNPU切分特性操作说明
虚拟化实例功能通过资源虚拟化将物理机或虚拟机配置的NPU切分成若干份vNPU挂载到容器中使用,实现统一资源分配与回收,满足多用户反复申请/释放资源的操作需求。
参考文档:创建vNPU-MindCluster7.0.RC1-昇腾社区
约束说明:
- 若涉及平台管理,切分操作由平台根据模板下发,具体操作见参考文档。
- 物理NPU虚拟化出vNPU后,不支持再将该物理NPU挂载到容器或直通到虚拟机使用。
- 一个vNPU只能被一个任务容器使用,不支持多个容器共用。
1.2.1 虚拟化模式查询
在物理机执行以下命令设置虚拟化模式(虚拟机内划分vNPU无需执行):
npu-smi set -t vnpu-mode -d mode
| 类型 | 描述 |
|---|---|
| mode | 虚拟化实例模式,取值为0或1:0为容器模式,1为虚拟机模式 |
更多npu-smi命令参考:Atlas A2 中心推理和训练硬件 24.1.0 npu-smi 命令参考 05 - 华为
1.2.2 查询算力切分模板信息
npu-smi info -t template-info
不同设备切分模板略有区别。以某款设备为例,支持两种模板,显存分别为32G/16G,最大支持1切4。

说明:vir后的数字表示AI Core数量,c前的数字表示AI CPU数量,32/16G表示显存资源分配。AI Core主要用于矩阵乘等计算,AI CPU负责执行CPU类算子(包括控制算子、标量和向量等通用计算)。
1.2.3 创建vNPU
命令格式:
npu-smi set -t create-vnpu -i id -c chip_id -f vnpu_config [-v vnpu_id] [-g vgroup_id]
| 类型 | 描述 |
|---|---|
| id | 设备id,通过npu-smi info -l命令获取 |
| chip_id | 芯片id,通过npu-smi info -m命令获取 |
2 实操:RECCE模型算力切分验证
2.1 模型介绍
当前鉴别人脸图像是否伪造存在两方面技术难题:一是如何鉴别未知方法伪造的人脸图像,二是人脸伪造本质上是利用深度学习进行信息篡改,现有方法未考虑对鉴别方法自身的攻击。为此,杨小康教授团队提出RECCE(侦查)鉴别方法,利用图像重建技术放大伪造痕迹,即使面对未知伪造方法也能准确识别伪造区域。同时,团队设计了Hybrid Attack攻击方法,对人眼不可见的微量修改即可欺骗鉴别算法。相关论文已被CVPR 2022收录。
模型源码:https://github.com/VISION-SJTU/RECCE
2.2 部署环境说明
- 硬件:Atlas 800I A2服务器
- 驱动:安装后默认包含npu-smi工具,位于
/usr/local/sbin/和/usr/local/bin/路径下 - CANN版本:8.1.RC1
- HDK版本:25.2.0
2.3 算力切分
2.3.1 设置虚拟化模式
使用Docker容器部署服务,设置为容器模式:
npu-smi set -t vnpu-mode -d 0
2.3.2 创建vNPU
查看当前设备支持的切分模板:
npu-smi info -t template-info
设备支持两种模板,分别可切分出16G和32G显存:

模型权重不足1G,可直接切成4份,每份16G显存,指定对应模板创建vNPU:
npu-smi set -t create-vnpu -i 6 -c 0 -f vir05_1c_16g
2.3.3 查询vNPU创建结果
npu-smi info -t info-vnpu -i 6 -c 0
原NPU被切成四个vNPU,ID为196~199:

/dev目录下也可看到对应信息:

2.3.4 销毁vNPU(验证完成后执行)
npu-smi set -t destroy-vnpu -i 6 -c 0 -v 196
npu-smi set -t destroy-vnpu -i 6 -c 0 -v 197
npu-smi set -t destroy-vnpu -i 6 -c 0 -v 198
npu-smi set -t destroy-vnpu -i 6 -c 0 -v 199
2.3.5 挂载容器(基于原生Docker)
docker run -it -d --net=host --shm-size=1g \
--name <容器名> \
--device=/dev/davinci_manager \
--device=/dev/hisi_hdc \
--device=/dev/devmm_svm \
--device=/dev/vdavinci196:/dev/davinci0 \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver:ro \
-v /usr/local/sbin:/usr/local/sbin:ro \
-v /home:/home \
<镜像名> bash
注意:不要使用--privileged=true特权模式。容器内执行npu-smi info可查看NPU信息,后续使用方式与普通NPU一致。
2.4 推理模型测试
2.4.1 精度测试
精度测试可使用开源数据集或业务相关数据集进行验证。RECCE模型通过现有数据集进行精度测试,主要流程如下:

- 将未切分的NPU挂载到容器中。
- 执行推理脚本,得到图片数据集中每张图片的伪造可能性。
- 将切分后的vNPU挂载到容器中,重复步骤2。
- 比较两次结果,计算每张图片伪造可能性的差异并取平均,得到最终精度差异。
核心代码:
device = torch.device(args.device)
model = eval("Recce")(num_classes=1)
if args.weight and args.bin:
raise ValueError("Only one of '--weight' or '--bin' can be set.")
elif args.weight:
weights = torch.load(args.weight, map_location="cpu")
elif args.bin:
weights = torch.load(args.bin, map_location="cpu")["model"]
else:
raise ValueError("Neither of '--weight' nor '--bin' is set. ")
model.load_state_dict(weights)
model = model.to(device)
freeze_weights(model)
model.eval()
paths, images = prepare_data()
inference(model, images=images, paths=paths, device=device)
最终精度测试结果:切分前后误差在可接受范围内,符合预期。
2.4.2 性能测试
精度验证完成后进行性能测试,主要流程如下:

- 启动4个Docker容器,挂载到同一张NPU上。
- 客户端持续向每个容器中的推理服务发送请求,逐步提高并发数量,记录单张图片处理耗时。
- 启动4个Docker容器,分别挂载到4个vNPU上,重复步骤2。
- 对比两次结果,评估性能提升程度。
最终性能测试结果:切分前后性能几乎持平。
2.5 FAQ
2.5.1 容器启动失败
问题现象:执行docker run报错:docker: Error response from daemon: OCI runtime create failed: container_linux.go:329 starting container process caused "permission denied": unknown.
根因分析:某些镜像需要调用的系统调用被seccomp profile限制,导致权限拒绝。
解决方案:在docker run命令中添加参数--security-opt seccomp=unconfined --security-opt apparmor=unconfined。
2.5.2 拉起模型服务报错
问题现象:执行npu-smi info报错:dcmi module initialize failed. ret is -8005。
根因分析:检查docker run启动脚本,发现--device参数中设备名称拼写错误。
解决方案:修正设备名称拼写,重新执行docker run后服务正常启动。
2.5.3 算力切分后如何统计单个NPU的AICore利用率
问题现象:切分后在宿主机上使用npu-smi info查看AICore利用率一直上不去。
根因分析:切分后该命令查看的是原始NPU的利用率,不准确,需进入容器查看vNPU的利用率。
解决方案:在每个容器中实现脚本定时执行npu-smi info获取AICore利用率,写入宿主机可访问的日志文件中,然后在宿主机上读取所有vNPU的利用率信息,求和取平均。
3 价值与效果
通过本实践案例,验证了昇腾Atlas 800I A2服务器对RECCE小模型进行部署切分的可行性,并验证了精度和性能方面几乎无损失。在部分业务场景中,单个容器要求只部署管理一个模型,通过vNPU切分可实现算力资源隔离,满足业务部署诉求,同时提高NPU卡整体利用率。
更多推荐



所有评论(0)