锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

华为Ascend昇腾CANN详细教程

时间:2022-08-14 20:30:00 tdt1对射型光电开关传感器tdt2对射电眼传感器

一、参考资料

基于昇腾CANN推理应用开发快速体验(C )

基于昇腾CANN推理应用开发-图片分类应用(C&C )

二、重要说明

  1. CANN软件提供过程级环境变量设置脚本,供用户在过程中引用,自动完成环境变量设置。

    # 例如 /home/ma-user/Ascend/ascend-toolkit/set_env.sh 
  2. 物理机场景,一个Device最多只能支持64个用户流程,Host最多只能支持Device个数64个进程;虚拟机场景,一个Device最多只能支持32个用户流程,Host最多只能支持Device个数32个过程。不支持使用fork函数创建多个过程并在过程中调用AscendCL接口场景,否则过程运行时会报错或卡死 。

    使用约束

  3. 查找错误码
    在这里插入图片描述

三、相关概念

术语/缩略语

3.1 Davinci

华为开发的新型芯片架构达芬奇架构。

3.2 EulerOS

基于华为自主研发的欧拉操作系统Linux标准内核的操作系统。

3.3 FE

Fusion Engine整合引擎,负责对接GE和TBE算子具有加载和管理算子信息库、整合规则管理等能力。图优化,图形编译实现接口; 实现算子接入管理;算子融合优化

3.4 GE

Graph Engine,MindSpore计算图执行引擎,主要负责硬件相关优化(算子集成、内存再利用等)。)根据前端计算图完成,device启动侧任务Graph/Operator IR用户可以调用这些接口作为安全易用的构图接口集合构建网络模型,模型中包含的图、图中的算子、模型和算子的属性。

3.5 TBE

Tensor Boost Engine,华为自研的NPU算子开发工具,在TVM( Tensor Virtual Machine )在框架扩展的基础上,提供了一套Python API实施自定义算子开发活动。

环境变量

# TBE operator implementation tool path export TBE_IMPL_PATH=/home/ma-user/Ascend/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe  # TBE operator compilation tool path export PATH=/home/ma-user/Ascend/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin/:${ 
        PATH}  # Python library that TBE implementation depends on export PYTHONPATH=${TBE_IMPL_PATH}:${PYTHONPATH} 

3.6 OPP

环境变量

# OPP path export ASCEND_OPP_PATH=/home/ma-user/Ascend/ascend-toolkit/latest/opp 

四、相关介绍

4.1 数据布局格式(format)

关键概念
极智AI | 谈为什么卷积加速更喜欢 NHWC Layout

Format对数据的物理的维度,如1D,2D,3D,4D,5D等。

NCHW和NHWC

在深度学习框架中,多维数据通过多维数组存储,如卷积神经网络的特征图(Feature Map)通常用四维数组保存,即4D,4D格式解释如下:

  • N:Batch比如图像的数量。
  • H:Height,特征图高度,即垂直高度方向的像素数。
  • W:Width,特征图宽度,即水平宽度方向的像素数。
  • C:Channels,特征图通道,如彩色RGB图像的Channels为3。

这四个维度有相应的顺序,因为数据只能线性存储。不同的深度学习框架将按不同的顺序存储特征图数据,如:

  • Caffe,排列顺序为[Batch, Channels, Height, Width],即NCHW。
  • TensorFlow,排列顺序为[Batch, Height, Width, Channels],即NHWC。

如上图所示,一张格式为RGB以图片为例,NCHW中,C排列在外层,每个通道,像素紧挨着,实际存储在RRRRRRGGGGGGBBBBBB同一通道的所有像素值顺序存储在一起;NHWC中C排列在最内层,像素间隔在每个通道中,实际存储是实际存储RGBRGBRGBRGBRGBRGB同一位置的像素值顺序存储在多个通道中。

NC1HWC0

昇腾AI为了改进通用矩阵乘法(GEMM)计算数据块的访问效率,统一使用所有张量数据NC1HWC0的 五维数据格式,如下图所示:

其中C0与微架构强相关,等于AI Core中矩阵计算单元的尺寸,对于FP16类型为16,对于16类型INT8类为32,这部分数据需要连续存储;C一是按C维度C0拆分后的数量,即C1=C/C0.如果结果不整除,最后一个数据需要补零对齐C0。

NHWC -> NC1HWC0的转换过程

  1. 将NHWC数据在C维度上分割成C1份NHWC0。
  2. 将C1份NHWC0在内存中连续排列,从而变成NC1HWC0。

NHWC->NC1HWC0转换场景示例

  1. 首层RGB图像通过AIPP转换为NC1HWC0格式。
  2. 中间层Feature Map每层输出为NC1HWC0格式,在搬运过程中需要重排。

4.2 Conext/Stream/Even

昇腾CANN系列教程-AscendCL特性之运行资源管理(C++)

资源申请与释放

资源申请顺序:SetDevice->CreateContext->CreateStream->CreateEvent

资源释放顺序:DestroyEvent->DestroyStream->DestroyContext->ResetDevice

同步与异步

同步、异步是站在调用者和执行者的角度,在当前场景下,若在Host调用接口后不等待Device执行完成再返回,则表示Host的调度是异步的;若在Host调用接口后需等待Device执行完成再返回,则表示Host的调度是同步的。

Context

Context作为一个容器,管理了所有对象(包括Stream、Event、设备内存等)的生命周期。不同Context的Stream、不同Context的Event是完全隔离的,无法建立同步等待关系。多线程编程场景下,每切换一个线程,都要为该线程指定当前Context,否则无法获取任何其他运行资源。

Context分为两种

  • 默认Context:调用aclrtSetDevice接口指定用于运算的Device时,系统会自动隐式创建一个默认Context,一个Device对应一个默认Context,默认Context不能通过aclrtDestroyContext接口来释放。
  • (推荐)显式创建的Context:在进程或线程中调用aclrtCreateContext接口显式创建一个Context。

Context接口调用流程

Stream(异步操作)

与 NVIDIA GPU的Stream类似,可参考资料:CUDA随笔之Stream的使用

Stream用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序在Device上执行。可以将Stream简单理解为一个异步任务的队列,主线程在调用异步接口时,指定了某个stream,本质上就是把异步任务送进了这个任务队列中。队列中任务的执行是保序的,即运行时环境会根据任务下发的顺序来依次执行,不会出现乱序执行的情况。在AscendCL的后台,运行时环境会自动从stream中依次取出一个个任务来执行。kernel执行和数据传输都显示或者隐式地运行在Stream中。

异步且基于stream的kernel执行数据传输能够实现以下几种类型的并行:

  • Host运算操作和device运算操作并行;
  • Host运算操作和host到device的数据传输并行;
  • Host到device的数据传输和device运算操作并行;
  • Device内的运算并行;

说明:基于Stream的kernel执行和数据传输,能够实现Host运算操作、Host与Device间的数据传输、Device内的运算并行。在许多情况下,花费在执行kernel上的时间要比传输数据多得多,所以很容易想到将Host与Devide之间的交互时间隐藏在其他kernel执行过程中,我们可以将数据传输和kernel执行放在不同的stream中来实现此功能。

Stream分两种:

  • 默认Stream:调用aclrtSetDevice接口指定用于运算的Device时,系统会自动隐式创建一个默认Stream,一个Device对应一个默认Stream,默认Stream不能通过aclrtDestroyStream接口来释放。
  • 显式创建的Stream:**推荐,**在进程或线程中调用aclrtCreateStream接口显式创建一个Stream。

Stream加速

Event(同步操作)

问题引入

上图中“Stream1->任务4”的执行依赖“Stream2->任务6”执行完毕,而如果还按照之前的方式,任务4执行前等待整个Stream2全部执行完毕,其实是多等了“任务7”、“任务8”的执行时间的。为了对Stream间任务依赖进行精细化管理,我们需要一个新的运行资源:Event。

Event通常用于在Stream之间执行事件同步操作,在两个Stream之间存在任务级别的依赖时尤其有用,如下图所示:

“Stream1->任务4”的确是依赖“Stream2->任务6”的完成,但这两个任务之间是无法直接产生依赖关系的,要使用Event机制来同步:

  • Stream2->任务6:在执行完毕后,声明“event1”这一事件已发生;
  • Stream1->任务4:在执行之前,等待“event1”这一事件的发生;

两个无法产生直接依赖关系的任务,通过Event实现了依赖机制。

// 在stream上声明event已经发生
aclError aclrtRecordEvent(aclrtEvent event, aclrtStream stream);

// 让stream等待event的发生
aclError aclrtStreamWaitEvent(aclrtStream stream, aclrtEvent event);

相关概念

支持调用AscendCL接口同步Stream之间的任务,包括同步Host与Device之间的任务、Device与Device间的任务。

Events标记了stream执行过程中的一个点,我们就可以检查正在执行的stream中的操作是否到达该点,我们可以把event当成一个操作插入到stream中的众多操作中,当执行到该操作时,所做工作就是设置CPU的一个flag来标记表示完成。

例如,若stream2的任务依赖stream1的任务,想保证stream1中的任务先完成,这时可创建一个Event,并将Event插入到stream1,在执行stream2的任务前,先同步等待Event完成。

Device、Context、Stream之间的关系

  • 默认Context、默认Stream一般适用于简单应用,用户仅仅需要一个Device的计算场景下。多线程应用程序建议全部使用显式创建的Context和Stream。

  • 线程中创建的多个Context,线程缺省使用最后一次创建的Context。

线程、Context、Stream之间的关系

  • 一个用户线程一定会绑定一个Context,所有Device的资源使用或调度,都必须基于Context。

  • 一个进程中可以创建多个Context,但一个线程同一时刻只能使用一个Contex,Context中已经关联了本线程要使用的Device。

  • 一个线程中可以创建多个Stream,不同的Stream上计算任务是可以并行执行;多线程场景下,也可以每个线程分别创建一个Stream,且线程之间的Stream在Device上相互独立,每个Stream内部的任务是按照Stream下发的顺序执行。

  • 多线程的调度依赖于运行应用的 操作系统调度 \textcolor{Red}{操作系统调度} 操作系统调度,多Stream在Device侧的调度,由Device的 调度组件 \textcolor{Red}{调度组件} 调度组件 进行调度。

多线程、多stream的性能说明

  • 线程调度依赖运行的操作系统,Stream上下发了任务后,Stream的调度Device的调度单元调度,但如果一个进程内的多Stream上的任务在Device存在资源争抢的时候,性能可能会比单Stream低。
  • 当前昇腾AI处理器有不同的执行部件,如AI CoreAI CPUVector Core等,对应使用不同执行部件的任务,建议多Stream的创建按照算子执行引擎划分
  • 单线程多Stream与多线程多Stream(一个进程中可以包含多个线程,每个线程中一个Stream)性能上哪个更优,具体取决于应用本身的逻辑实现,一般来说单线程多Stream性能略好,原因是应用层少了线程调度开销
  • 从同步场景,到Stream场景,再到Callback场景,我们见证了主线程一步一步被释放。在同步场景,所有场景都在主线程完成;在Stream场景,推理送到了Stream来做,而后处理还要主线程完成;而在Callback场景下,推理和后处理就都放到Stream中了

4.3 内存管理

昇腾CANN系列教程-AscendCL特性之内存管理(C++)

如果进程运行在Host上,就申请Host内存,如果是运行在Device上,申请的就是Device内存。

Host-Device

aclrtMallocHost->aclrtMalloc->aclrtMemcpy(host-device)

模型输入与输出

模型输入

一个模型有且只有1个“输入DataSet”(数据集对象),里边包含所有的输入;而如果有多个输入的话,每个输入用一个“DataBuffer”来承载。

  • 一个模型的所有输入抽象为一个“DataSet”对象;
  • 每一个输入抽象为一个“DataBuffer”对象;

如上图所示,一个模型有2个输入,其中第一个输入是若干张图片,第二个输入是每张图片的元数据等信息,那么在编程中我们需要这样做:

  1. 用第一个输入,所有图片,创建一个DataBuffer对象;
  2. 用第二个输入,图片的信息,创建另一个DataBuffer对象;
  3. 创建一个DataSet对象;
  4. 把第1/2步中创建的2个DataBuffer对象放到DataSet对象中;

核心代码

// 创建DataBuffer
aclDataBuffer *aclCreateDataBuffer(void *data, size_t size);

// 创建DataSet
aclmdlDataset *aclmdlCreateDataset();

// 向DataSet中添加DataBuffer
aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataset, aclDataBuffer *dataBuffer);

模型输出

模型输出数据结构,也是一个DataSet,1-N个DataBuffer,但是问题来了,我还没推理,没有数据呢,怎么会有DataBuffer? 其实在模型确定下来之后,基本上输出的个数和占用内存大小就已经完全确定了。比如一个有1000个类别的分类网络的输出,结果就是1000组数据,每组包含一个标签和一个置信度,共2000个数值。那么这个输出所占用的内存大小就很容易计算出来,并在推理之前先申请好内存。没错,AscendCL不支持推理过程中自动申请输出内存,一定要在调用推理接口之前先把输出内存、DataBuffer、DataSet准备好

核心代码

// 创建一个“模型描述信息”对象,用于收集模型的描述信息,也就是模型的元数据
aclError aclmdlGetDesc(aclmdlDesc *modelDesc, uint32_t modelId);

// 获取模型描述信息
// 可以根据模型的modelId来获取模型描述信息,并将描述信息填充进modelDesc对象中
aclError aclmdlGetDesc(aclmdlDesc *modelDesc, uint32_t modelId);

4.4 npu-smi 命令

npu-smi命令

4.5 设置环境变量

如果昇腾AI处理器配套软件包没有安装在默认路径,安装好MindSpore之后,需要导出Runtime相关环境变量,下述命令中LOCAL_ASCEND=/usr/local/Ascend/usr/local/Ascend表示配套软件包的安装路径,需注意将其改为配套软件包的实际安装路径。

# 安装nnae包时配置
. /usr/local/Ascend/nnae/set_env.sh    

# 安装tfplugin包时配置
. /usr/local/Ascend/tfplugin/set_env.sh

# 安装toolbox包时配置
. /usr/local/Ascend/toolbox/set_env.sh
# control log level. 0-DEBUG, 1-INFO, 2-WARNING, 3-ERROR, 4-CRITICAL, default level is WARNING.
export GLOG_v=2

# Conda environmental options
export LOCAL_ASCEND=/usr/local/Ascend # the root directory of run package

# lib libraries that the run package depends on
export LD_LIBRARY_PATH=${LOCAL_ASCEND}/ascend-toolkit/latest/fwkacllib/lib64:${LOCAL_ASCEND}/driver/lib64:${LOCAL_ASCEND}/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe/op_tiling:${LD_LIBRARY_PATH}

/usr/local/Ascend/driver/lib64/driver

# Environment variables that must be configured
## TBE operator implementation tool path
export TBE_IMPL_PATH=${LOCAL_ASCEND}/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe
## OPP path
export ASCEND_OPP_PATH=${LOCAL_ASCEND}/ascend-toolkit/latest/opp
## AICPU path
export ASCEND_AICPU_PATH=${ASCEND_OPP_PATH}/..
## TBE operator compilation tool path
export PATH=${LOCAL_ASCEND}/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin/:${ 
        PATH}
## Python library that TBE implementation depends on
export PYTHONPATH=${TBE_IMPL_PATH}:${PYTHONPATH}

4.6 CANN信息

# CANN安装路径
/usr/local/Ascend/nnae

# CANN安装信息
cat /usr/local/Ascend/toolkit/ascend_install.info

输出:
Install_Type=full
Feature_Type=all
UserName=root
UserGroup=root
Install_Path_Param=/usr/local/Ascend
Docker_Root_Path_Param=

4.7 ascend_nnae信息

cat /usr/local/Ascend/nnae/latest/ascend_nnae_install.info

输出:
package_name=Ascend-cann-nnae
version=5.0.3
innerversion=V100R001C79B220SPC1011
arch=aarch64
os=linux
path=/usr/local/Ascend/nnae/5.0.3

4.8 ascend-toolkit信息

# ascend-toolkit版本信息
cat /usr/local/Ascend/toolkit/version.info

输出:
Version=1.79.22.4.220
/usr/local/Ascend/nnae/5.0.3/fwkacllib/lib64
auto_tune-0.1.0-py3-none-any.whl  libauto_tiling.so          libge_executor.so         libregister.a
hccl-0.1.0-py3-none-any.whl       lib_caffe_parser.so        libge_runner.so           libregister.so
hccl_reduce_op_ascend710.o        libcce_aicore.so           libgraph.so               libresource.so
hccl_reduce_op_ascend910.o        libcce_aicpudev_online.so  libhccl.so                librs.so
libacl_cblas.so                   libcce.so                  libhcom_graph_adaptor.so  libruntime.so
libacl_dvpp_mpi.so                libcce_tools.so            libindextransform.so      libte_fusion.so
libacl_dvpp.so                    libcompress.so             libmmpa.a                 libtiling.so
libacl_op_compiler.so             libcompressweight.so       libmmpa.so                libtsdclient.so
libacl_retr.so                    libc_sec.so                libmsprofiler.so          libtvm_runtime.so
libacl_tdt_channel.so             libdatatransfer.so         libopskernel.so           libtvm.so
libaicore_utils.so                liberror_manager.a         libopt_feature.so         libtvm_topi.so
libaicpu_engine_common.so         liberror_manager.so        libparser_common.so       plugin
libalog.so                        libfmk_onnx_parser.so      libplatform.so            schedule_search-0.1.0-py3-none-any.whl
libascendcl.a                     libfmk_parser.so           libra_hdc.so              stub
libascendcl.so                    libge_common.so            libra_peer.so             te-0.4.0-py3-none-any.whl
libascend_protobuf.so.3.13.0.0    libge_compiler.so          libra.so                  topi-0.4.0-py3-none-any.whl

4.9 安装昇腾AI处理器配套软件包

昇腾软件包提供商用版和社区版两种下载途径:

  • 商用版下载需要申请权限,下载链接与安装方式请参考Ascend Data Center Solution 22.0.RC1安装指引文档。
  • 社区版下载不受限制,下载链接请前往CANN社区版,选择5.1.RC1.alpha005版本,以及在固件与驱动链接中获取对应的固件和驱动安装包,安装包的选择与安装方式请参照上述的 商用版 安装指引文档

表1-1 昇腾软件介绍

软件类型 软件介绍
固件 固件包含昇腾AI处理器自带的OS 、电源器件和功耗管理器件控制软件,分别用于后续加载到AI处理器的模型计算、芯片启动控制和功耗控制。
驱动 部署在昇腾服务器,功能类似英伟达驱动,管理查询昇腾AI处理器,同时为上层CANN软件提供芯片控制、资源分配等接口。
CANN 部署在昇腾服务器,功能类似英伟达CUDA,包含Runtime、算子库、图引擎、媒体数据处理等组件,通过AscendCL(Ascend Computing Language)对外提供Device管理、Context管理、Stream管理、内存管理、模型加载与执行、算子加载与执行、媒体数据处理等API,帮助开发者实现在昇腾CANN平台上进行深度学习推理计算、图像预处理、单算子加速计算。

重要说明:如果是首次安装请按照“驱动 > 固件”的顺序,分别安装驱动和固件包;覆盖安装请按照“固件 > 驱动”的顺序,分别安装固件和驱动包,**{vision}**表示软件版本号。

五、Ascend-cann-toolkit 开发套件

第三方依赖安装指导(C++样例)

昇腾AI设备安装开发环境

非昇腾AI设备安装开发环境

Ascend-cann-toolkit 开发套件包。

5.1 环境变量

# 以安装用户在开发环境任意目录下执行以下命令,打开.bashrc文件。
vi ~/.bashrc 

# 在文件最后一行后面添加如下内容。CPU_ARCH环境变量请根据运行环境cpu架构填写,如export CPU_ARCH=aarch64
export CPU_ARCH=[aarch64/x86_64]

# THIRDPART_PATH需要按照运行环境安装路径设置,如运行环境为arm,指定安装路径为Ascend-arm,则需要设置为export THIRDPART_PATH=${HOME}/Ascend-arm/thirdpart/${CPU_ARCH}
export THIRDPART_PATH=${ 
        HOME}/Ascend/thirdpart/${CPU_ARCH}  #代码编译时链接第三方库

# CANN软件安装后文件存储路径,最后一级目录请根据运行环境设置,运行环境为arm,这里填arm64-linux;运行环境为x86,则这里填x86_64-linux,以下以arm环境为例
export INSTALL_DIR=${ 
        HOME}/Ascend/ascend-toolkit/latest/arm64-linux

# 执行命令保存文件并退出。
:wq!  
# 执行命令使其立即生效。 
source ~/.bashrc 

# 创建第三方依赖文件夹
mkdir -p ${THIRDPART_PATH}
# 拷贝公共文件到第三方依赖文件夹
cd $HOME
git clone https://gitee.com/ascend/samples.git
cp -r ${ 
        HOME}/samples/common ${THIRDPART_PATH}

5.2 常用指令

# AscendCL头文件路径
/home/ma-user/Ascend/ascend-toolkit/latest/include/acl

# AscendCL库文件路径
/home/ma-user/Ascend/ascend-toolkit/latest/lib64

# 查看device设备
ls /dev/davinci*

# 驱动安装路径
/usr/local/Ascend/driver/

# 查看 Ascend-cann-toolkit 版本
cd /home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux
cat ascend_toolkit_install.info

查看NPU资源

# 查看npu资源
npu-smi info

watch -n 1 npu-smi info

npu-smi info watch -i 0 -c 0

查看 Ascend-cann-toolkit 版本

cd /home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux
cat ascend_toolkit_install.info
[ma-user@notebook-87136e07-6a9a-4138-beec-742972f7b62f arm64-linux]$ cat ascend_toolkit_install.info 
package_name=Ascend-cann-toolkit
version=5.0.3
innerversion=V100R001C79B220SPC1011
arch=aarch64
os=linux
path=/home/ma-user/Ascend/ascend-toolkit/5.0.3/arm64-linux

5.3 设置环境变量

昇腾 AI 处理器各工作模式的差异

第三方依赖安装指导(C++样例)

设置 INC_PATH、LIB_PATH路径

Linux环境变量设置(临时+永久)

说明 路径 变量1 变量2 变量3
Ascend安装路径 ${HOME}/Ascend/ascend-toolkit/latest INSTALL_DIR DDK_PATH INC_PATH
Ascend库文件路径 ${INSTALL_DIR}/acllib/lib64/stub NPU_HOST_LIB LIB_PATH

设置INC_PATH、LIB_PATH路径有三种方式:

  • 临时性设置

    ${INSTALL_DIR} 表示CANN软件安装目录,例如,$HOME/Ascend/ascend-toolkit/latest/{arch-os},arch表示操作系统架构(需根据运行环境的架构选择),{os}表示操作系统(需根据运行环境的操作系统选择)。

    旧版本(默认)

    export INSTALL_DIR=${ 
              HOME}/Ascend/ascend-toolkit/latest
    export DDK_PATH=${INSTALL_DIR}
    export NPU_HOST_LIB=${INSTALL_DIR}/acllib/lib64/stub
    

    新版本(未来)

    export INSTALL_DIR=${ 
              HOME}/Ascend/ascend-toolkit/latest
    export DDK_PATH=${INSTALL_DIR}
    export NPU_HOST_LIB=${INSTALL_DIR}/{ 
              arch-os}/devlib
    
  • 永久性设置

    vi ~/.bashrc
    
    # 末尾添加环境变量
    export DDK_PATH=${INSTALL_DIR}
    export NPU_HOST_LIB=${INSTALL_DIR}/acllib/lib64/stub
    
    # 更新环境变量
    source ~/.bashrc
    
  • 在CMakeLists.txt文件中修改路径

    DDK_PATH也即INC_PATH,表示AscendCL头文件路径;NPU_HOST_LIB也即LIB_PATH,表示AscendCL库文件路径。

    CMakeLists.txt 文件中会指定 INC_PATHLIB_PATH,根据真实路径修改。

    CMakeLists.txt

    # CMake lowest version requirement
    cmake_minimum_required(VERSION 3.5.1)
    
    # project information
    project(AME)
    
    # Compile options
    add_compile_options(-std=c++11)
    
    add_definitions(-DENABLE_DVPP_INTERFACE)
    
    # Specify target generation path
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY  "../../../out")
    set(CMAKE_CXX_FLAGS_DEBUG "-fPIC -O0 -g -Wall")
    set(CMAKE_CXX_FLAGS_RELEASE "-fPIC -O2 -Wall")
    
    # 设置环境变量,DDK_PATH即为INC_PATH
    set(INC_PATH $ENV{DDK_PATH})
    
    if (NOT DEFINED ENV{DDK_PATH})
    	# set(INC_PATH "/usr/local/Ascend")
        set(INC_PATH "/home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux")
        message(STATUS "set default INC_PATH: ${INC_PATH}")
    else ()
        message(STATUS "env INC_PATH: ${INC_PATH}")
    endif()
    
    # 设置环境变量,NPU_HOST_LIB即为LIB_PATH
    set(LIB_PATH $ENV{NPU_HOST_LIB})
    
    if (NOT DEFINED ENV{NPU_HOST_LIB})
    	# set(LIB_PATH "/usr/local/Ascend/acllib/lib64/stub/")
        set(LIB_PATH "/home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64/stub/")
        message(STATUS "set default LIB_PATH: ${LIB_PATH}")
    else ()
        message(STATUS "env LIB_PATH: ${LIB_PATH}")
    endif()
    
    # Header path
    include_directories(
        ${INC_PATH}/acllib/include/
        ../inc/
    )
    
    # add host lib path
    link_directories(
        ${LIB_PATH}
    )
    
    add_executable(main
            utils.cpp
           # dvpp_process.cpp
            model_process.cpp
           # singleOp_process.cpp
            sample_process.cpp
            main.cpp)
    
    target_link_libraries(main
            ascendcl acl_cblas acl_dvpp stdc++)
    
    install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
    

示例:

set(INC_PATH "/usr/local/Ascend")
set(LIB_PATH "/usr/local/Ascend/acllib/lib64/stub/")
修改为
set(INC_PATH "/home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux")
set(LIB_PATH "/home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64/stub/")

配置 ascend-toolkit 环境变量

如果不设置环境变量,很多工具无法使用,例如:ATC模型转换工具。

# 设置环境变量
cd /home/ma-user/Ascend/ascend-toolkit

source set_env.sh

set_env.sh

export LD_LIBRARY_PATH=/home/ma-user/Ascend/ascend-toolkit/latest/lib64:/home/ma-user/Ascend/ascend-toolkit/latest/compiler/lib64/plugin/opskernel:/home/ma-user/Ascend/ascend-toolkit/latest/compiler/lib64/plugin/nnengine:$LD_LIBRARY_PATH
export PYTHONPATH=/home/ma-user/Ascend/ascend-toolkit/latest/python/site-packages:/home/ma-user/Ascend/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe:$PYTHONPATH
export PATH=/home/ma-user/Ascend/ascend-toolkit/latest/bin:/home/ma-user/Ascend/ascend-toolkit/latest/compiler/ccec_compiler/bin:$PATH
export ASCEND_AICPU_PATH=/home/ma-user/Ascend/ascend-toolkit/latest
export ASCEND_OPP_PATH=/home/ma-user/Ascend/ascend-toolkit/latest/opp
export TOOLCHAIN_HOME=/home/ma-user/Ascend/ascend-toolkit/latest/toolkit
export ASCEND_AUTOML_PATH=/home/ma-user/Ascend/ascend-toolkit/latest/tools

配置 atc 环境变量

# 设置环境变量
cd /home/ma-user/Ascend/ascend-toolkit

source set_env.sh

配置 tfplugin 环境变量

/home/ma-user/Ascend/tfplugin/set_env.sh

set_env.sh

export PYTHONPATH=/home/ma-user/Ascend/tfplugin/latest/python/site-packages:$PYTHONPATH

六、开发工具链

6.1 ATC 模型转换工具

工具介绍

昇腾张量编译器(Ascend Tensor Compiler,简称ATC)是昇腾CANN架构体系下的模型转换工具。ATC工具安装在 ascend-toolkit/latest/bin 目录下。

单算子描述文件场景下

Ascend IR定义的单算子描述文件(json格式)通过ATC工具进行单算子编译后,转成适配昇腾AI处理器的单算子离线模型,然后上传到板端环境,通过AscendCL接口加载单算子模型文件用于验证单算子功能。

功能特性

  • 将开源框架的网络模型(如Caffe、TensorFlow等)以及Ascend IR定义的单算子描述文件(json格式)转换为昇腾AI处理器支持的.om格式离线模型
  • 模型转换过程中,ATC会进行算子调度优化权重数据重排内存使用优化等具体操作,对原始的深度学习模型进行进一步的调优,从而满足部署场景下的高性能需求,使其能够高效执行在昇腾AI处理器上。
  • 通过ATC,可以进行算子编译

昇腾AI处理器中,为了提高通用矩阵乘法(GEMM)运算数据块的访问效率,所有张量数据统一采用NC1HWC0的五维数据格式,如下图所示。

ATC安装路径

/home/ma-user/Ascend/ascend-toolkit/5.0.3/arm64-linux/aarch64-linux/bin

模型转换

atc --model=model/resnet50.prototxt --weight=model/resnet50.caffemodel --framework=0 --output=model/resnet50 --soc_version=Ascend310
  • –model:ResNet-50网络的模型文件(*.prototxt)的路径。

  • –weight:ResNet-50网络的预训练模型文件(*.caffemodel)的路径。

  • –framework:原始框架类型。0表示Caffe。

  • –output:resnet50.om模型文件的路径。请注意,记录保存该om模型文件的路径,后续开发应用时需要使用。

  • –soc_version:

    昇腾AI处理器

    的版本。

    • 昇腾310 AI处理器,此处配置为Ascend310。
    • 昇腾310P AI处理器,此处配置为Ascend310P。
    • 昇腾910 AI处理器,此处配置为Ascend910A或Ascend910B或Ascend910ProA或Ascend910ProB或Ascend910PremiumA,其中,Pro或Premium表示芯片性能提升等级、A或B表示PartialGood等级,请根据实际情况选择。

6.2 Ascend-DMI工具

“Ascend-DMI”工具主要为Atlas产品的标卡、板卡及模组类产品提供带宽测试算力测试功耗测试等功能。工具的功能介绍如表1-1所示。本系统通过调用底层DCMI(设备控制管理接口)/DSMI(设备系统管理接口)以及ACL(Ascend Computing Language,昇腾计算语言)相关接口完成相关检测功能,对于系统级别的信息查询通过调用系统提供的通用库来实现,用户使用工具时通过配置参数来实现不同的测试功能。

表1-1 工具功能介绍

功能名称 功能介绍
带宽测试 测试总线带宽、内存带宽和时延。
算力测试 测试芯片中AI Core的算力值和满算力下芯片的平均功率。
功耗测试 检测整卡或芯片的功耗信息。
设备实时状态查询 检测设备在运行过程中的状态信息。
故障诊断 分别对软件类和硬件类进行诊断,并输出诊断结果,各检查类包含的项目如下:软件类:驱动与硬件的兼容性,驱动与固件版本兼容性,CANN各层软件的兼容性,CANN与驱动的兼容性。硬件类:Device健康状态,ROCE网口健康状态,本地带宽,算力,内存和HBM。
软硬件版本兼容性测试 获取硬件信息、架构、驱动版本、固件版本以及软件版本,并检测软硬件间的兼容性。
设备拓扑检测 查询单机内多卡间的拓扑结构。

6.3 msame工具

msame工具为模型推理工具

yolov3

功能:对ATC模型转换工具转换后的om离线模型文件进行推理。

msame是模型推理工具,输入.om模型和模型所需要的输入bin文件,输出模型的输出数据文件,支持多次推理(指对同一输入数据进行推理)。模型必须是通过atc工具转换的om模型,输入bin文件需要符合模型的输入要求(支持模型多输入)。

设置环境变量

export DDK_PATH=/home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux
export NPU_HOST_LIB=/home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64/stub

编译

cd $HOME/AscendProjects/tools/msame/

./build.sh g++ $HOME/work/MyDocuments/tools/msame/out/
[ma-user@notebook-87136e07-6a9a-4138-beec-742972f7b62f msame]$ ./build.sh g++ $HOME/work/MyDocuments/tools/msame/out/
g++
/home/ma-user/work/MyDocuments/tools/msame/out/
-- The C compiler identification is GNU 7.3.0
-- The CXX compiler identification is GNU 7.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/g++
-- Check for working CXX compiler: /usr/bin/g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- env INC_PATH: /home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux
-- env LIB_PATH: /home/ma-user/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64/stub
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ma-user/work/MyDocuments/tools/msame/build/intermediates/host
Scanning dependencies of target main
[ 20%] Building CXX object CMakeFiles/main.dir/utils.cpp.o
[ 40%] Building CXX object CMakeFiles/main.dir/model_process.cpp.o
[ 60%] Building CXX object CMakeFiles/main.dir/sample_process.cpp.o
[ 80%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[100%] Linking CXX executable /home/ma-user/work/MyDocuments/tools/msame/out/main
[100%] Built target main

运行

类型一 不加input参数

cd ./out

./msame --model "../../../ResNet-50/resnet50.om" --output "../out" --outfmt TXT --loop 1
[ma-user@notebook-87136e07-6a9a-4138-beec-742972f7b62f out]$ ./msame --model "../../../ResNet-50/resnet50.om" --output "../out" --outfmt TXT --loop 1
[INFO] acl init success
[INFO] open device 0 success
[INFO] create context success
[INFO] create stream success
[INFO] get run mode success
[INFO] load model ../../../ResNet-50/resnet50.om success
[INFO] create model description success
[INFO] get input dynamic gear count success
[INFO] create model output success
../out//2022627_17_16_22_844232
[INFO] model execute success
Inference time: 0.564ms
[INFO] get max dynamic batch size success
[INFO] output data success
Inference average time: 0.564000 ms
[INFO] destroy model input success
[INFO] unload model success, model Id is 1
[INFO] Execute sample success
[INFO] end to destroy stream
[INFO] end to destroy context
[INFO] end to reset device is 0
[INFO] end to finalize acl

七、AI CPU

7.1 问题引入

什么场景适合使用AI CPU呢?针对IO密集型场景(程序),推荐使用AI CPU,避免数据传输耗时的问题;针对计算密集型场景(程序),推荐使用NPU(Ascend910),NPU计算性能强悍,可降低计算耗时。

AI CPU负责执行昇腾AI处理器的CPU类算子(包括控制算子、标量和向量等通用计算),其在Ascend解决方案系统架构中的位置如下所示:

AI CPU算子编译执行所涉及组件如下:

  • GE(Graph Engine):Graph Engine是基于昇腾AI软件栈对不同的机器学习框架提供统一的IR接口,对接上层网络模型框架,例如Tensorflow、PyTorch等,GE的主要功能包括图准备、图拆分、图优化、图编译、图加载、图执行和图管理等(此处图指网络模型拓扑图)。
  • AI CPU Engine:AI CPU子图编译引擎,负责对接GE,提供AI CPU算子信息库,进行算子注册、算子内存需求计算、子图优化和task生成的能力。
  • AI CPU Schedule:AI CPU的模型调度器,与Task Schedule配合完成NN模型的调度和执行。
  • AI CPU Processor:AI CPU的Task执行器,完成算子运算。AI CPU Processor包含算子实现库,算子实现库完成AI CPU算子的执行实现。
  • Data Processor:训练场景下,用于进行训练样本的数据预处理。

八、关键API

aclInit()

功能:acl初始化。

原型:
aclError aclInit(const char *configPath);

参数解释

configPath这个参数指的是在初始化时加载的配置文件的路径,可以通过这个配置文件来配置参数DUMP功能用于比对精度、配置profiling信息用于调试性能以及配置算子缓存信息老化功能,从而节约内存和平衡调用性能。

去初始化

功能:acl去初始化。

原型:
aclError aclFinalize();

不建议在析构函数中调用aclFinalize接口,否则在进程退出时可能由于单例析构顺序未知而导致进程异常退出等问题。

aclrtSetDevice()

功能:指定接下来的计算要分配哪个Device。

原型:
aclError aclrtSetDevice(int32_t deviceId);

deviceId是逻辑ID,通过以下方式获取:

aclError aclrtGetDeviceCount(uint32_t *count);

“count”指明了当前环境下一共有多少个逻辑设备可用,而上文中的“deviceId”只需要从[0, (count-1)]中任取1个即可。例如,我们的机器上只插了1个Atlas300I推理卡,上边有4个昇腾310AI处理器,但是软件栈经过检查发现只有3个芯片可用,于是在调用 aclrtGetDeviceCount() 之后,系统返回的“count”值是3,能用的deviceId就是0/1/2中任意一个。

aclrtSetDevice() 这个接口调用完毕后,除了指定了计算设备之外,还会同时创建1个默认的Context;而这个默认的Context还附赠了2个Stream,1个默认Stream和1个用于执行内部同步的Stream。这也意味着:如果是编写非常简单的单线程同步推理应用,在运行资源这里我们只需要调用aclrtSetDevice就够了

aclrtResetDevice()

功能:复位当前运算的Device,释放Device上的资源。

原型:
aclError aclrtResetDevice(int32_t deviceId);

调用 aclrtResetDevice() 接口复位“deviceId”所指代的设备,释放其上的运行资源,包括默认Context、默认Stream以及默认Context下创建的所有Stream。若Context或Stream下还有未完成的任务,系统会等待任务完成后再对设备进行释放。建议 aclrtSetDevice() 接口和 aclrtResetDevice() 接口配对使用,在不使用Device上资源时,通过调用aclrtResetDevice接口及时释放本进程使用的Device资源。

复位Device接口调用顺序

1. 调用aclrtDestroyEvent接口释放Event
2. 调用aclrtDestroyStream接口释放显式创建的Stream
3. 调用aclrtDestroyContext释放显式创建的Context
4. 调用aclrtResetDevice接口释放Device

aclrtGetDevice()

功能:获取当前正在使用的DeviceID。

原型:
aclError aclrtGetDevice(int32_t *deviceId);

问题引入

既然可以多次调用aclrtSetDevice来为当前进程设置不同的设

相关文章