ACL 基于昇腾CANN的ACL推理应用开发原理(Python) ex_1

本文档详细介绍了如何在华为昇腾AI处理器上使用ACL(Ascend Computing Language)进行模型推理。从ACL和ATC工具的基础知识,到初始化、资源管理、模型加载、数据处理、推理执行、后处理等步骤,一步步展示了在昇腾平台上进行深度学习模型推理的完整流程。此外,还涵盖了DVPP模块在图像预处理中的作用,以及数据在Host与Device之间的交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Learn From:
https://www.hiascend.com/zh/college/onlineExperiment/codeLabAcl/acl

ACL应用案例部署
在这里插入图片描述
课程目标
学完本课程,您应该能够:

1.了解ACL的基本概念,清楚ACL具备哪些能力,能为我们做什么

2.了解ACL定义的编程模型,理解各类运行资源的概念及其相互关系

3.能够区分Host和Device的概念,并学会管理这两者各自的内存

4.加载一个离线模型进行推理,并为推理准备输入输出数据结构
在这里插入图片描述
2. 基础知识
2.1 ATC介绍
ATC(Ascend Tensor Compiler)是华为昇腾软件栈提供的一个编译工具,它的主要功能是将基于开源框架的网络模型(如Caffe、TensorFlow等)以及单算子Json文件,转换成昇腾AI处理器支持的离线模型Offline-Model文件(简称OM文件)。在编译过程中,可以实现算子调度的优化、权值数据重排、内存使用优化等,并且可以脱离设备完成模型的预处理。更详细的ATC介绍,可参看官方文档

ATC工具架构图
在这里插入图片描述
2.2 ACL介绍
对已训练好的权重文件,比如caffe框架下的caffemodel, tensorflow框架下得到的checkpoint或者pb文件,再经过ATC工具转换后得到的离线模型文件,ACL(Ascend Computing Language,昇腾计算语言)提供了一套用于在昇腾系列处理器上进行加速计算的API。基于这套API,您能够管理和使用昇腾软硬件计算资源,并进行机器学习相关计算。更详细的ACL介绍,可参看官方文档

当前ACL为您提供了C/C++和Python编程接口,能够很方便的帮助您达成包括但不限于如下这些目标:

1.加载深度学习模型进行推理

2.加载单算子进行计算

3.图像、视频数据的预处理
在这里插入图片描述
3. 准备工作¶
本实验的最终结果是使用Resnet50对3张图片进行分类推理。为了达成这个结果,首先我们准备了如下两个素材:

三张待推理分类的图片数据,如:
在这里插入图片描述
使用ATC工具,将tensorflow的googlenet.pb模型转换成昇腾支持的om(offine-model)文件。
推理后我们将打印每张图片置信度排前5位的标签及其置信度。

  1. 开启征途
    4.1 初始化
    在开始调用ACL的任何接口之前,首先要做ACL的初始化。初始化的代码很简单,只有一行:
acl.init(config_path)

这个接口调用会帮您准备好ACL的运行时环境。其中调用时传入的参数是一个配置文件在磁盘上的路径,这里我们暂时不必关注。

有初始化就有去初始化,在确定完成了ACL的所有调用之后,或者进程退出之前,要做去初始化操作,接口调用也十分简单:

acl.finalize()

导入Python包:

import argparse
import numpy as np
import struct
import acl
import os
from PIL import Image

接口介绍:
在这里插入图片描述
函数示例:

def init():
    ret = acl.init()
    check_ret("acl.init", ret)

4.2申请计算资源
想要使用昇腾处理器提供的加速计算能力,需要对运行管理资源申请,包括Device、Context、Stream。且需要按顺序申请,主要涉及以下三个接口:

acl.rt.set_device(device_id)

这个接口指定计算设备,告诉运行时环境我们想要用哪个设备,或者更具体一点,哪个芯片。但是要注意,芯片和我们在这里传入的编号之间并没有物理上的一一对应关系。

acl.rt.create_context(device_id)

Context作为一个容器,管理了所有对象(包括Stream、Event、设备内存等)的生命周期。不同Context的Stream、不同Context的Event是完全隔离的,无法建立同步等待关系。

acl.rt.create_stream()

Stream用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序在Device上执行。基于Stream的kernel执行和数据传输能够实现Host运算操作、Host与Device间的数据传输、Device内的运算并行。
接口介绍:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
函数示例:

import sys
import os
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all" 

home_path = !echo ${
   
   HOME}
sys.path.append(os.path.join(home_path[0] , "jupyter-notebook/"))
print('System init success.')

# atlas_utils是本团队基于pyACL封装好的一套工具库,如果您也想引用的话,请首先将
# https://gitee.com/ascend/samples/tree/master/python/common/atlas_utils
# 这个路径下的代码引入您的工程中
from atlas_utils.acl_resource import AclResource
from constants import *

#创建一个AclResource类的实例
acl_resource = AclResource()
#AscendCL资源初始化(封装版本)
acl_resource.init()

# 上方“init”方法具体实现(仅供参考)
# 请阅读“init(self)”方法,观察初始化和运行时资源申请的详细操作步骤
def init(self):
    """
    Init resource
    """
    print("init resource stage:")
    ret = acl.init()
    utils.check_ret("acl.init", ret)
    #指定用于运算的Device
    ret = acl.rt.set_device(self.device_id)
    utils.check_ret("acl.rt.set_device", ret)
    print("Set device n success.")

    #显式创建一个Context
    self.context, ret = acl.rt.create_context(self.device_id)
    utils.check_ret("acl.rt.create_context", ret)

    #创建一个Stream
    self.stream, ret = acl.rt.create_stream()
    utils.check_ret("acl.rt.create_stream", ret)

    #获取当前昇腾AI软件栈的运行模式
    #0:ACL_DEVICE,表示运行在Device的Control CPU上或开发者版上
    #1:ACL_HOST,表示运行在Host CPU上
    self.run_mode, ret = acl.rt.get_run_mode()
    utils.check_ret("acl.rt.get_run_mode", ret)

    print("Init resource success")

4.3 加载模型
既然要调用模型进行推理,首先当然是要把模型加载进来。ACL提供了多种模型加载和内存管理方式,这里我们只选取其中相对简单的一种,即从磁盘上加载离线模型,并且加载后的模型内存由ACL自动管理:

model_path = "./model/resnet50.om";  #模型文件在磁盘上的路径
 model_id, ret = acl.mdl.load_from_file(model_path)  #加载模型

其中,model_id是系统完成模型加载后生成的模型ID对应的指针对象 加载后生成的modelId,全局唯一

记得这个“model_id”,后边我们使用模型进行推理,以及卸载模型的时候还要用到。

有加载自然就有卸载,模型卸载的接口比较简单:

acl.mdl.unload(model_id)

至此,您脑海中应该有这样一个概念,即使用了任何的资源,加载了任何的素材,都要记得用完后销毁和卸载。
接口介绍:在这里插入图片描述
函数示例:

def load_model(model_path):
    model_path = "./model/googlenet_yuv.om"
    model_id, ret = acl.mdl.load_from_file(model_path)
    check_ret("acl.mdl.load_from_file", ret)
    return model_id

4.4 获取模型信息
模型描述需要特殊的数据类型,使用以下函数来创建并获取该数据类型。

acl.mdl.create_desc()

acl.mdl.get_desc(model_desc, model_id)

获取到模型类型后,还需要根据该类型来获取模型的输入输出个数,调用函数如下:

acl.mdl.get_num_inputs(model_desc)

acl.mdl.get_num_outputs(model_desc)

接口介绍:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
函数示例:

def get_model_data(model_id):
    global model_desc
    model_desc = acl.mdl.create_desc()
    ret = acl.mdl.get_desc(model_desc, model_id)
    check_ret("acl.mdl.get_desc", ret)

    input_size = acl.mdl.get_num_inputs(model_desc)
    output_size = acl.mdl.get_num_outputs(model_desc)
    return input_size, output_size

4.5 申请device内存
要使用NPU进行加速计算,首先要申请能够被NPU直接访问到的专用内存。在讲解内存申请之前,首先我们要区分如下两个概念:

Host:Host指与Device相连接的X86服务器、ARM服务器,会利用Device提供的NN(Neural-Network )计算能力,完成业务。 Device:Device指安装了芯片的硬件设备,利用PCIe接口与Host侧连接,为Host提供NN计算能力。

简而言之,我们的数据需要先从Host侧进行加载,即读进Host侧内存,随后将其拷贝到Device侧内存,才能进行计算。计算后的结果还要传回Host侧才能进行使用。

申请Device侧内存:

dev_ptr, ret = acl.rt.malloc(size, policy)   #申请device侧内存

dev_ptr; //device侧内存指针

size; //device侧内存大小

这里我们分配了跟Host侧同样大小的内存,准备用于在Device侧存放推理数据。本接口最后一个参数policy是内存分配规则。

ACL_MEM_MALLOC_HUGE_FIRST ----- 优先申请大页内存,如果大页内存不够,则使用普通页的内存。

ACL_MEM_MALLOC_HUGE_ONLY ----- 仅申请大页,如果大页内存不够,则返回错误。

ACL_MEM_MALLOC_NORMAL_ONLY ----- 仅申请普通页。

使用完别忘了释放申请过的内存:

 `acl.rt.malloc-> acl.rt.free`

接口介绍:
在这里插入图片描述
函数示例:

def gen_data_buffer(size, des):
    global model_desc
    func = buffer_method[des]
    for i in range(size):
        temp_buffer_size  = acl.mdl.get_output_size_by_index(model_desc, i)
        temp_buffer, ret = acl.rt.malloc(temp_buffer_size,
                                         const.ACL_MEM_MALLOC_NORMAL_ONLY)
        check_ret("acl.rt.malloc", ret)
        if des == "in":
            input_data.append({
   
   "buffer": temp_buffer,
                                    "size": temp_buffer_size})
        elif des == "out":
            output_data.append({
   
   "buffer": temp_buffer,
                                     "size": temp_buffer_size})

def malloc_device(input_num
### 基于CANN的无人机应用开发训练实验介绍 #### 实验目的 为了探索和验证昇腾AI基础软硬件平台的能力,特别是CANN(Compute Architecture for Neural Networks)在实际应用场景中的表现,设计并实施了一项针对无人机应用的开发训练实验。该实验旨在评估CANN如何支持从模型训练到部署整个过程中的各个环节,确保能够实现高效、精准的任务执行[^3]。 #### 平台与环境配置 本实验采用华为提供的昇腾系列处理器作为计算核心,并利用CANN所提供的优化库来加速神经网络运算。通过集成MindStudio全流程工具链,可以方便快捷地完成从数据准备、算法调试直至最终产品化的全部工作流程[^1]。 #### 数据集选取 考虑到无人机通常用于复杂多变的真实世界环境中,因此选择了涵盖多种场景的数据集来进行测试。这些数据不仅包含了不同天气条件下的图像样本,还包括了各种地形地貌特征以及动态物体的信息,以此全面检验所构建模型的泛化能力和适应性。 #### 模型选择与调整 根据具体需求选用了适合处理视觉识别任务的目标检测框架YOLOv5,并对其进行了必要的参数微调以更好地适配当前硬件资源特性及特定业务逻辑要求。借助CANN的强大功能,实现了对原始版本的有效改进,在保持较高精度的同时显著提升了推理速度[^2]。 #### 训练过程概述 在整个训练过程中充分利用了分布式训练的优势,使得大规模数据集上的迭代变得更加迅速而稳定;与此同时还引入了一些先进的正则化方法防止过拟合现象发生。经过多次试验对比分析发现,在相同条件下基于CANN运行效率明显优于其他同类方案。 #### 应用效果展示 成功完成了多个典型飞行任务模拟演练,包括但不限于自动避障、路径规划等功能模块演示。结果显示经由此次专项培训后的系统能够在更短时间内做出更加准确可靠的决策判断,极大地提高了作业安全性和工作效率。 ```python import torch from yolov5 import YOLOv5 model = YOLOv5('yolov5s.pt', device='cuda') results = model(image_data, size=640) for result in results.xyxy[0]: print(f'Detected {result}') ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风尘23187

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值