基于昇腾计算语言 AscendCL 开发 AI 推理应用
本文分享自华为云社区《基于昇腾计算语言AscendCL开发AI推理应用》,作者:昇腾 CANN。
初始 AscendCL
AscendCL(Ascend Computing Language,昇腾计算语言)是昇腾计算开放编程框架,是对底层昇腾计算服务接口的封装,它提供运行时资源(例如设备、内存等)管理、模型加载与执行、算子加载与执行、图片数据编解码/裁剪/缩放处理等 API 库,实现在昇腾 CANN 平台上进行深度学习推理计算、图形图像预处理、单算子加速计算等能力。简单来说,就是统一的 API 框架,实现对所有资源的调用。
如何基于 AscendCL 开发推理应用
首先,我们得先了解下,使用 AscendCL 时,经常会提到的“数据类型的操作接口” ,这是什么呢?为啥会存在?
在 C/C++中,对用户开放的数据类型通常以 Struct 结构体方式定义、以声明变量的方式使用,但这种方式一旦结构体要增加成员参数,用户的代码就涉及兼容性问题,不便于维护,因此 AscendCL 对用户开放的数据类型,均以接口的方式操作该数据类型,例如,调用某个数据类型的 Create 接口创建该数据类型、调用 Get 接口获取数据类型内参数值、调用 Set 接口设置数据类型内的参数值、调用 Destroy 接口销毁该数据类型,用户无需关注定义数据类型的结构体长什么样,这样即使后续数据类型需扩展,只需增加该数据类型的操作接口即可,也不会引起兼容性问题。
所以,总结下,“数据类型的操作接口”就是创建数据类型、Get/Set 数据类型中的参数值、销毁数据类型的一系列接口,存在的最大好处就是减少兼容性问题。
接下来,进入我们今天的主题,怎么用 AscendCL 的接口开发网络模型推理场景下的应用。看完本文介绍的关键知识点,也可以到 “昇腾文档中心[1]”查阅详细的文档介绍。
AscendCL 初始化与去初始化
使用 AscendCL 接口开发应用时,必须先初始化 AscendCL ,否则可能会导致后续系统内部资源初始化出错,进而导致其它业务异常。在初始化时,还支持以下跟推理相关的配置项(例如,性能相关的采集信息配置),以 json 格式的配置文件传入 AscendCL 初始化接口。如果当前的默认配置已满足需求(例如,默认不开启性能相关的采集信息配置),无需修改,可向 AscendCL 初始化接口中传入 NULL,或者可将配置文件配置为空 json 串(即配置文件中只有{})。
有初始化就有去初始化,在确定完成了 AscendCL 的所有调用之后,或者进程退出之前,需调用 AscendCL 接口实现 AscendCL 去初始化。
运行管理资源申请与释放
运行管理资源包括 Device、Context、Stream、Event 等,此处重点介绍 Device、Context、Stream,其基本概念如下图所示 。
您需要按顺序依次申请如下运行管理资源:Device、Context、Stream,确保可以使用这些资源执行运算、管理任务。所有数据处理都结束后,需要按顺序依次释放运行管理资源:Stream、Context、Device。
在申请运行管理资源时,Context、Stream 支持隐式创建和显式创建两种申请方式。
媒体数据处理
如果模型对输入图片的宽高要求与用户提供的源图不一致,AscendCL 提供了媒体数据处理的接口,可实现抠图、缩放、格式转换、视频或图片的编解码等,将源图裁剪成符合模型的要求。后续期刊中会展开说明这个功能,本期着重介绍模型推理的部分,以输入图片满足模型的要求为例。
模型加载
模型推理场景下,必须要有适配昇腾 AI 处理器的离线模型(*.om 文件),我们可以使用 ATC(Ascend Tensor Compiler)来构建模型。如果模型推理涉及动态 Batch、动态分辨率等特性,需在构建模型增加相关配置。关于如何使用 ATC 来构建模型,请参见“昇腾文档中心[1]”。
有了模型,就可以开始加载了,当前 AscendCL 支持以下几种方式加载模型:
从*.om 文件中加载模型数据,由 AscendCL 管理内存
从*.om 文件中加载模型数据,由用户自行管理内存
从内存中加载模型数据,由 AscendCL 管理内存
从内存中加载模型数据,由用户自行管理内存
由用户自行管理内存时,需关注工作内存、权值内存。工作内存用于存放模型执行过程中的临时数据,权值内存用于存放权值数据。这个时候,是不是有疑问了,我怎么知道工作内存、权值内存需要多大?不用担心,AscendCL 不仅提供了加载模型的接口,同时也提供了“根据模型文件获取模型执行时所需的工作内存和权值内存大小”的接口,方便用户使用 。
模型执行
在调用 AscendCL 接口进行模型推理时,模型推理有输入、输出数据,输入、输出数据需要按照 AscendCL 规定的数据类型存放。相关数据类型如下:
使用 aclmdlDesc 类型的数据描述模型基本信息(例如输入/输出的个数、名称、数据类型、Format、维度信息等)。
模型加载成功后,用户可根据模型的 ID,调用该数据类型下的操作接口获取该模型的描述信息,进而从模型的描述信息中获取模型输入/输出的个数、内存大小、维度信息、Format、数据类型等信息。
使用 aclDataBuffer 类型的数据来描述每个输入/输出的内存地址、内存大小。
调用 aclDataBuffer 类型下的操作接口获取内存地址、内存大小等,便于向内存中存放输入数据、获取输出数据。
使用 aclmdlDataset 类型的数据描述模型的输入/输出数据。
模型可能存在多个输入、多个输出,调用 aclmdlDataset 类型的操作接口添加多个 aclDataBuffer 类型的数据。
准备好模型执行所需的输入和输出数据类型、且存放好模型执行的输入数据后,可以执行模型推理了,如果模型的输入涉及动态 Batch、动态分辨率等特性,则在模型执行前,还需要调用 AscendCL 接口告诉模型本次执行时需要用的 Batch 数、分辨率等。
当前 AscendCL 支持同步模型执行、异步模型执行两种方式,这里说的同步、异步是站在调用者和执行者的角度。
若调用模型执行的接口后需等待推理完成再返回,则表示模型执行是同步的。当用户调用同步模型执行接口后,可直接从该接口的输出参数中获取模型执行的结果数据,如果需要推理的输入数据量很大,同步模型执行时,需要等所有数据都处理完成后,才能获取推理的结果数据。
若调用模型执行的接口后不等待推理完成完成再返回,则表示模型执行是异步的。当用户调用异步模型执行接口时,需指定 Stream(Stream 用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序在 Device 上执行),另外,还需调用 aclrtSynchronizeStream 接口阻塞程序运行,直到指定 Stream 中的所有任务都完成,才可以获取推理的结果数据。如果需要推理的输入数据量很大,异步模型执行时,AscendCL 提供了 Callback 机制,触发回调函数,在指定时间内一旦有推理的结果数据,就获取出来,达到分批获取推理结果数据的目的,提高效率。
推理结束后,如果需要获取并进一步处理推理结果数据,则由用户自行编码实现。最后,别忘了,我们还要销毁 aclmdlDataset、aclDataBuffer 等数据类型,释放相关内存,防止内存泄露。
模型卸载
在模型推理结束后,还需要通过 aclmdlUnload 接口卸载模型,并销毁 aclmdlDesc 类型的模型描述信息、释放模型运行的工作内存和权值内存。
以上就是基于 AscendCL 开发基础推理应用的相关知识点,您也可以在“昇腾社区在线课程[2]”板块学习视频课程,学习过程中的任何疑问,都可以在“昇腾论坛[3]”互动交流!
编译及运行应用
此处我们以一个“基于 Caffe ResNet-50 网络实现图片分类”的应用为例,来说明编译运行应用的基本步骤以及运行应用后如何查看图片所属分类。编译运行应用依赖 CANN 软件,因此您需要先根据对应版本的安装指南安装 CANN 软件。
接下来我们就可以通过下面这个小视频 3 分钟体验下编译运行。
体验完了,是不是意犹未尽,想自己操作一把呢,来吧!您可以从昇腾CANN样例仓获取该样例以及详细的使用说明。
更多介绍
[1]昇腾文档中心:https://www.hiascend.com/zh/document
[2]昇腾社区在线课程:https://www.hiascend.com/zh/edu/courses
[3]昇腾论坛:https://www.hiascend.com/forum
版权声明: 本文为 InfoQ 作者【华为云开发者联盟】的原创文章。
原文链接:【http://xie.infoq.cn/article/ec2103622bba77f840aa970c4】。文章转载请联系作者。
评论