1、介绍
B站视频链接:TensorFlow框架AICPU算子开发全流程_哔哩哔哩_bilibilihttps://www.bilibili.com/video/bv1dY411c7sd
本文旨在帮助用户使用CANN架构和MindStudio平台进行AI CPU算子开发指导。
其中CANN(Compute Architecture for Neural Networks)是华为公司针对AI场景推出的异构计算架构,通过提供多层次的编程接口,支持用户快速构建基于昇腾平台的AI应用和业务。
MindStudio提供您在AI开发所需的一站式开发环境,支持模型开发、算子开发以及应用开发三个主流程中的开发任务。依靠模型可视化、算力测试、IDE本地仿真调试等功能,MindStudio能够帮助您在一个工具上就能高效便捷地完成AI应用开发。MindStudio采用了插件化扩展机制,开发者可以通过开发插件来扩展已有功能。
2、安装教程
2.1 CANN软件包
CANN下载链接:昇腾社区-官网丨昇腾万里 让智能无所不及https://www.hiascend.com/software/cann/community
CANN安装指南:
详情可参考CANN文档,例版本5.1.RC1.alpha003:昇腾社区-官网丨昇腾万里 让智能无所不及https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/51RC1alpha003
2.2 MindStudio平台
MindStudio官网:昇腾社区-官网丨昇腾万里 让智能无所不及https://www.hiascend.com/software/mindstudio
MindStudio用户手册:
2.2.1 环境依赖
- Python
MindStudio目前支持Python版本为3.7.0 ~3.9.7
安装相关依赖:
pip install xlrd==1.2.0
pip install absl-py
pip install numpy
- MinGW
请用户到下载最新的MinGW安装包(参考链接)。根据自己的系统选择对应版本,例如64位可以选择x86_64-posix-seh,安装后配置好环境变量
打开系统命令行,输入gcc -v命令。
当界面提示“gcc version x.x.x (x86_64-posix-sjlj-rev0, Built by MinGW-W64 project)”信息时,表示安装成功。
- CMake
名称 | 版本 | 说明 | 获取途径 |
CMake | 3.16.5-win64-x64 | CMake是个一个开源的跨平台自动化建构系统,用来管理软件建置的程序,并不依赖于某特定编译器,并可支持多层目录、多个应用程序与多个库。 | 您可以访问CMake主页下载此软件。 |
2.2.2 安装MindStudio
通过访问官网获取MindStudio安装包,MindStudio官网:昇腾社区-官网丨昇腾万里 让智能无所不及https://www.hiascend.com/software/mindstudio
下载jbr压缩包:
推荐使用11_0_10b1341.35版本的jbr,进入链接:https://cache-redirector.jetbrains.com/intellij-jbr/jbr_dcevm-11_0_10-windows-x64-b1341.35.tar.gz下载压缩包。
3、算子工程实践
3.1 AI CPU算子介绍
AI CPU算子,是运行在昇腾AI处理器中AI CPU计算单元上的表达一个完整计算逻辑的运算,如下情况下,开发者需要自定义AI CPU算子。
- 在NN模型训练或者推理过程中,将第三方开源框架转化为适配昇腾AI处理器的模型时遇到了昇腾AI处理器不支持的算子。此时,为了快速打通模型执行流程,用户可以通过自定义AI CPU算子进行功能调测,提升调测效率。功能调通之后,后续性能调测过程中再将AI CPU自定义算子转换成TBE算子实现。
- 某些场景下,无法实现在AI Core上运行的自定义算子(比如部分算子需要Complex32、Complex64类型,但AI Core指令不支持;再比如包含了大量标量计算的算子,而AI Core不擅长对标量进行处理),此时可以通过开发AI CPU自定义算子实现昇腾AI处理器对此算子的支持。
3.2 算子分析
使用AI CPU方式开发算子前,我们需要确定算子功能、输入、输出、算子类型以及算子实现函数名称等。
步骤1 明确算子的功能以及数学表达式。以top_k算子为例
【功能】返回指定轴的k个最大或最小值
步骤2 明确输入和输出。
【输入】 2个输入
x:tensor,数据类型:float16、float32
k:tensor,数据类型:int64
【输出】 2个输出
Values:top_k的返回值
Indices:top_k的返回值索引
步骤3 明确算子实现文件名称以及算子的类型(OpType)。
- 算子类型需要采用大驼峰的命名方式,即采用大写字符区分不同的语义。
- 算子文件名称,可选用以下任意一种命名规则:
建议将OpType按照如下方式进行转换,得到算子文件名称。
转换规则如下:
- 首字符的大写字符转换为小写字符。
例如:Abc -> abc
- 小写字符后的大写字符转换为下划线+小写字符。
例如:AbcDef -> abc_def
- 紧跟数字以及大写字符后的大写字符,作为同一语义字符串,查找此字符串后的第一个小写字符,并将此小写字符的前一个大写字符转换为下划线+小写字符,其余大写字符转换为小写字符。若此字符串后不存在小写字符,则直接将此字符串中的大写字符转换为小写字符。
例如:ABCDef -> abc_def;Abc2DEf -> abc2d_ef;Abc2DEF -> abc2def; ABC2dEF -> abc2d_ef。
因此本例中,算子类型定义为top_k,算子的实现文件名称为top_k,因此各个交付件的名称建议命名如下:
- 算子的代码实现(即kernel实现)文件命名为top_k_kernel.h与top_k_kernel.cc。
- 插件实现文件命名为top_k_kernel_plugin.cc。
- 原型定义文件命名为:top_k.h与top_k.cc。
- 信息定义文件命名为top_k.ini。
算子类型(OpType) | top_k | ||
算子输入 | name:x | shape:1D or higher | data type: float16、float32、 int32 |
name:k | shape:0D | data type: int32 | |
算子输出 | name: values | shape:all | data type: float16、float32、 int32 |
name: indices | shape: all | data type: int32 | |
算子实现文件名称 | top_k |
3.3 算子工程创建
打开MindStudio, 选择文件 -> 新建 -> 项目
在左边选择Ascend Operator,若是在本机上,CANN version选择本机的CANN版本,若是远程配置 CANN,点击install,点击Remote Connection后的+,配置远程SSH连接,配置好后点击Test Connection,出现 Successfully connected!即配置成功。
配置SSH远程连接:
定位远程服务器CANN软件包所在位置:
点击下一步后在Sample template中选择AICPU算子下TensorFlow框架中的TopK算子,点击完成即可完成算子工程的创建。
3.4 算子工程结构和交付件介绍
3.4.1 算子工程结构
完整的算子包括:算子原型定义、算子适配插件、算子信息库定义、算子实现。MindStudio新建算子工程时生成相应的工程模板,用户无需关注编译脚本实现等内容,只需关注具体的业务实现即可。
3.4.2 交付件介绍
top_k算子的原型为TensorFlow中的tf.math.top_k:
tf.math.top_k(
input, k=1, sorted=True, name=None
)
TensorFlow中top_k API链接:https://www.tensorflow.org/api_docs/python/tf/math/top_k
一个完成算子的开发交付件包括算子实现文件、算子原型文件、算子信息库文件和算子适配插件文件。
3.5 算子代码实现
3.5.1 简介
AI CPU算子的实现包括两部分:
- 头文件:进行算子类的声明,自定义算子类需要继承CpuKernel基类。
- 源文件:重写算子类中的Compute函数,进行算子计算逻辑的实现。
3.5.2 头文件定义
在算子工程中“cpukernel/impl/top_k.h”文件中进行了top_k算子类的声明,声明了top_k函数的一些参数信息,包括输入输出等属性。
3.5.3 算子实现文件
在算子工程中“cpukernel/impl/top_k.cc”文件中进行了top_k算子的计算逻辑实现。
GetValueAndSelect函数将前k个输入的数据转化为数值。
Select函数将第k个输入数据转换为第n个输入数据的值。
ExchangeForTyeOne函数功能为交换父节点和子节点(当右子节点不存在时)。
ExchangeForTypeTwo函数功能为当父节点小于左子节点时,交换父节点和子节点。
ExchangeForTypeThree函数功能为当父节点大于左子节点时,交换父节点和子节点。
ExchangeForTypeFour函数功能为当父节点等于左子节点时,交换父节点和子节点。
此外还要在aicpu命名空间下实现Compute函数,实现对输入数据的合法性效验。
之后在DoCompute函数中实现具体的算子实现逻辑。
3.5.4 算子信息库定义
在“cpukernel/op_info_cfg/aicpu_kernel/top_k.ini”文件中定义了自定义top_k算子的信息文件,主要体现算子在昇腾AI处理器上的具体实现规格,包括算子支持输入输出type、name等信息。网络运行时,根据算子信息库中的算子信息做基本校验,并进行算子匹配。
3.5.5 算子适配插件开发
在“framework/tf_plugin/tensorflow_top_k_plugin.cc”文件中进行了算子适配插件的开发,开发人员完成自定义算子的实现代码后,需要进行适配插件的开发将基于第三方框架的算子映射成适配昇腾AI处理器的算子,将算子信息注册到GE中。基于第三方框架的网络运行时,首先会加载并调用GE中的插件信息,将第三方框架网络中的算子进行解析并映射成昇腾AI处理器中的算子。
- REGISTER_CUSTOM_OP:注册自定义算子,OpType为注册到GE中的算子类型。
- FrameworkType:TENSORFLOW代表原始框架为TensorFlow。
- OriginOpType:算子在原始框架中的类型。
- ParseParamsByOperatorFn:用来注册解析算子属性的函数。
- ImplyType:指定算子的实现方式。ImplyType::AI_CPU表示该算子是AI CPU算子;ImplyType::TVM表示该算子是TBE算子。
3.5.6 算子原型定义
算子原型定义规定了在昇腾AI处理器上可运行算子的约束,主要体现算子的数学含义,包含定义算子输入、输出和属性信息,基本参数的校验和shape的推导,原型定义的信息会被注册到GE的算子原型库中。网络模型生成时,GE会调用算子原型库的校验接口进行基本参数的校验,校验通过后,会根据原型库中的推导函数推导每个节点的输出shape与dtype,进行输出tensor的静态内存的分配。
Graph Engine(GE)提供REG_OP宏,以“.”链接INPUT、OUTPUT、ATTR等接口注册算子的输入、输出和属性信息,最终以OP_END_FACTORY_REG接口结束,完成算子的注册。其中输入输出的描述信息顺序需要与算子实现中定义保持一致,ATTR的顺序可变。
IR实现的cc文件中主要实现如下两个功能:
- 算子参数的校验,实现程序健壮性并提高定位效率。
- 根据算子的输入张量描述、算子逻辑及算子属性,推理出算子的输出张量描述, 包括张量的形状、数据类型及数据排布格式等信息。这样算子构图准备阶段就可以为所有的张量静态分配内存,避免动态内存分配带来的开销。
实现InferShape方法:算子IR中InferShape的定义可以使用如下接口: IMPLEMT_COMMON_INFERFUNC(func_name):自动生成的一个类型为Operator 类的对象op,可直接调用Operator类接口进行InferShape的实现,其中, func_name:用户自定义。
实现Verify方法:算子Verify函数的实现使用如下接口:IMPLEMT_VERIFIER (OpType, func_name) ,传入的OpType为基于Operator类派生出来的子类,会自动生成一个类型为此子类的对象op,可以使用子类的成员函数获取算子的相关属性。
- OpType:自定义算子的类型。
- func_name:自定义的verify函数名称。
注册InferShape方法与Verify方法。 调用InferShape注册宏与Verify注册宏完成InferShape方法与Verify方法的注册,如下所示:
3.6 算子编译
算子交付件开发完成后,需要对算子工程进行编译,生成自定义算子安装包*.run,详细的编译操作包括:
- 将AI CPU算子代码实现文件*.h与*.cc编译成libcust_aicpu_kernels.so。
- 将AI CPU算子信息定义文件*.ini编译成cust_aicpu_kernel.json。
- 将原型定义文件*.h与*.cc编译成libcust_op_proto.so。
- 将算子适配插件实现文件*.cc编译成libcust_tf_parsers.so。
算子工程编译的具体内容为:将算子插件实现文件、算子原型定义文件、算子信息库定义文件分别编译成算子插件、算子原型库、算子信息库。
点击顶部导航栏的构建按钮下的Edit build configuration编辑编译配置。
进入编译配置页面,根据下表进行编译配置:
参数 | 说明 |
Build Configuration | 编译配置名称,默认为Build-Configuration |
Build Mode | 编译方式。
须知:远端编译需要g++版本为7.5.0。
算子工程在MindStudio安装服务器进行编译,方便用户通过编译日志快速定位到MindStudio的实现代码所在位置,从而快速定位问题。此种方式下需要配置交叉编译环境。 |
Deployment | Remote Build模式下显示该配置。deployment功能,可以将指定项目中的文件、文件夹同步到远程指定机器的指定目录。 |
Environment Variables | Remote Build模式下显示该配置。为远程环境配置ASCEND_OPP_PATH、TOOLCHAIN_DIR等相关环境变量。 |
AICPU SoC Version | 配置昇腾AI处理器的类型。 |
若选用远程编译,需要配置Deployment和环境变量,其中环境变量在Environment Variables输入框中输入ASCEND_OPP_PATH、TOOLCHAIN_DIR、ASCEND_TENSOR_COMPILER_INCLUDE、ASCEND_AICPU_PATH环境变量。
ASCEND_OPP_PATH=/usr/local/Ascend/ascend-toolkit/latest/opp
TOOLCHAIN_DIR=/usr/local/Ascend/ascend-toolkit/latest/toolkit/toolchain/hcc
ASCEND_TENSOR_COMPILER_INCLUDE=/usr/local/Ascend/ascend-toolkit/latest/include
ASCEND_AICPU_PATH=/usr/local/Ascend/ascend-toolkit/latest
其中用户将/usr/local换成实际Ascend安装路径。
单击“Build”进行工程编译。并在界面最下方的窗口查看编译结果,编译完成后,显示远程编译完成 Information: build remotely finished,并在算子工程的cmake-build目录下生成自定义算子安装包custom_opp_Target OS_Target Architecture.run。
3.7 UT测试
UT(Unit Test:单元测试)是开发人员进行单算子运行验证的手段之一,主要目的是:
- 测试算子代码的正确性,验证输入输出结果与设计的一致性。
- UT侧重于保证算子程序能够跑通,选取的场景组合应能覆盖算子代码的所有分支(一般来说覆盖率要达到100%),从而降低不同场景下算子代码的编译失败率。
创建的Sample template模板通常会自带UT测试用例,在“testcases\ut\aicpu_test\top_k”文件夹下,会自动生成一个“test_top_k_impl.cc”ut测试文件,用于编写算子实现代码的UT C++测试用例,计算出算子执行结果,并 取回结果和预期结果进行比较,来测试算子逻辑的正确性。
开发人员可以执行当前工程中所有算子的UT测试用例,也可以执行单个算子的UT测试用例。
右键单击“testcases/ut/aicpu_test”文件夹,选择Run AI CPU Operator‘All’UT Impl with coverage,运行整个文件夹下算子实现代码的测试用例。
第一次运行时会弹出运行配置页面,请参考配置,然后单击Run。
参数 | 说明 |
Name | 运行配置名称,用户可以自定义。 |
Test Type | 选择ut_impl。 |
Compute Unit | 选择计算单元
选择不同的计算单元可以实现AI Core/Vector Core和AI CPU UT测试配置界面的切换。 |
Operator Name | 选择运行的测试用例。
|
Case Names | 勾选需要运行的测试用例,即算子实现代码的UT C++测试用例。支持全选和全不选所有测试用例。 |
运行完成后,通过界面下方的“Run”日志打印窗口查看运行结果。在“Run”窗口中单击report index.html的URL(URL中的localhost为MindStudio安装服务器的IP,建议直接单击打开),查看UT测试用例的覆盖率结果。
3.8 ST测试
自定义算子部署到算子库(OPP)后,可进行ST(System Test)测试,在真实的硬件环境中,验证算子功能的正确性。
ST测试的主要功能是:基于算子测试用例定义文件*.json生成单算子的om文件;使用 AscendCL接口加载并执行单算子om文件,验证算子执行结果的正确性。
ST测试会覆盖算子实现文件,算子原型定义与算子信息库,不会对算子适配插件进行测试。
创建的Sample template模板通常会自带UT测试用例,在“testcases\st\aicpu_kernel”文件夹下,会自动生成一个“TopK_case_timestamp.json”的st测试json配置文件,用于构造算子ST测试用例,使其满足ST测试覆盖范围。
其中算子测试用例定义json文件中各参数含义如下:
参数 | 说明 | |
Input (Output) | Name | 可选。 算子为动态多输入(输出)场景时,“name”为必选配置,请配置为算子信息库中“dynamic_inputx.name”参数的名称+编号,编号从“0”开始,根据输入的个数按照0,1,2......,依次递增。 |
- | Format | 必选。 String或者String的一维数组。 输入(输出)tensor数据的排布格式,不允许为空。 支持如下数据排布格式:
支持的其它选项:
|
- | OriginFormat | 可选。 String或者String的一维数组,支持以下两种取值:
|
- |
|
|
- |
| 必选。
输入tensor支持的形状。 – 支持静态shape输入的场景: shape维度以及取值都为固定值,该场景下不需要配置shape_range参数。 – 支持动态shape输入的场景: shape中包含-1,例如:(200, -1)表示第二个轴长度 未知。该场景下需要与shape_range参数配合使用, 用于给出“-1”维度的取值范围。
支持fuzz,使用fuzz测试参数生成脚本自动批量生成值。
如果format和type为UNDEFINED时shape允许为空。 需要注意,配置的shape需要与format相匹配。 |
- | OriginShape | 可选。
|
- | Value | 可选。 String或者tensor数组。 若用户需要指定输入数据时,可通过增加此字段进行配置。有如下两种配置方式:
"value": [1,2,3,4]
"value": "../test.bin" 二进制数据bin文件需用户自己准备。可以输入绝对路 径,也可以输入测试用例定义文件的相对路径。
说明: 若用户添加了“value”字段,“data_distribute”和 “value_range”字段将会被忽略。同时需要保证 “format”,"type","shape"字段的值与“value”数据对应,且每个用例只能测试一种数据类型。 |
- | ValueRange | 必选。
|
- | DataDistribute | 必选。 String或者String的一维数组。 使用哪种数据分布方式生成测试数据,支持的分布方式有
|
- | IsConst | 可选。 bool类型。
|
Attribute | Name | 若配置attr,则为必选。 String类型。 属性的名称,不为空。 |
- | Type | 若配置attr,则为必选。 String类型。 属性支持的类型。bool、int、float、string、list_bool、list_int、list_float、list_string、list_list_int、data_type(如果attr中的value值为数据类型时,type值 必须为data_type) |
- | value | 若配置attr,则为必选。 属性值,根据type的不同,属性值不同。
|
Expected Result Verification | Script Path | 算子期望数据生成函数对应的文件路径 |
- | Script Function | 算子函数名称 |
点击Run便可打开ST测试配置。
参数 | 说明 |
Name | 运行配置名称,用户可以自定义。 |
Test Type | 选择st_cases 。 |
Execute Mode |
说明: Local Execute不支持Windows操作系统。 |
SSH Connection | 当Execute Mode选择Remote Execute时,下拉选择SSH配置信息,若未添加配置信息,请单击 添加。添加SSH配置信息的方法请参见SSH连接管理。 |
CANN Machine | CANN工具所在设备的SSH配置信息。添加SSH配置信息的方法请参见SSH连接管理。 说明: 该参数仅支持Windows操作系统。 |
Environment Variables |
多个环境变量用英文分号隔开。
在Name中输入环境变量名称:PATH_1。 在Value中输入环境变量值:路径1。 勾选Instead system environment variables可以显示系统环境变量。 |
Operator Name | 选择需要运行的算子。 |
SoC Version | 配置 昇腾AI处理器的类型。 |
Product Form | 配置产品形态。若SoC Version配置为Ascend310时显示该配置项。
|
Executable File Name | 下拉选择需要执行的测试用例定义文件。 若对AI CPU算子进行ST测试,测试用例文件前有(AI CPU)标识。 |
Target OS | 针对Ascend EP:选择昇腾AI处理器所在硬件环境的Host侧的操作系统。 针对Ascend RC:选择板端环境的操作系统。 |
Target Architecture | 选择Target OS的操作系统架构。 |
Case Names | 选择运行的Case Name。 说明:默认全选所有用例,可以去除勾选部分不需要运行的用例。 |
在Environment Variables中输入如下环境变量:
ASCEND_DRIVER_PATH=/usr/local/Ascend/driver;
ASCEND_HOME=/usr/local/Ascend/ascend-toolkit/latest;
ASCEND_AICPU_PATH=${ASCEND_HOME}/<target architecture>-linux;
<target architecture>为操作系统架构,例如:x86_64-linux或arm64-linux。
点击运行便可执行ST测试
MindStudio会根据算子测试用例定义文件在“算子工程根目录/testcases/st/out/<operator name>”下生成测试数据和测试代码,并编译出可执行文件,在指定的硬件设备上执行测试用例,并将执行结果和与标杆数据对比报告打印到Output窗口中,同时在 “算子工程根目录/testcases/st/out/<operator name>”下生成st_report.json文件。
st_report.json报表主要字段及含义如下:
字段 | 说明 | |||
run_cmd | - | - | - | 命令行命令。 |
report_list | - | - | - | 报告列表,该列表中可包含多个测试用例的报告。 |
trace_detail | - | - | 运行细节 | |
st_case_info | - | 测试信息。 | ||
expect_data_path | 期望计算结果路径。 | |||
case_name | 测试用例名称。 | |||
input_data_path | 输入数据路径。 | |||
planned_output_data_paths | 实际计算结果输出路径。 | |||
op_params | 算子参数信息。 | |||
stage_result | - | 运行各阶段结果信息。 | ||
case_name | - | - | 测试名称。 | |
status | - | - | 测试结果信息。 |
ST测试成功后在运行部分的输出和输出的文件st_report.json样例如下:
3.9 算子部署
将自定义算子安装包custom_opp_Targert OS_Target Architecture.run部署到昇腾AI处理器所在硬件环境的算子库中,为后续算子在网络中运行构造必要条件。
单击MindStudio工程界面顶部的“Ascend->Operator Deployment”进入算子打包部署界面。
有两种部署方式,这里我们选择远程部署算子,在Environment Variables中填入如下环境变量:
ASCEND_OPP_PATH=/home/xxx/Ascend/ascend-toolkit/latest/opp
Operator Package会自动定位当前工程文件下算子.run文件,当然我们也可以手动选择想要部署的算子。
在Deployment框中选择想要部署的远程服务器地址,点击Operator deploy即可执行算子部署。
算子部署成果示意图如下:
算子部署过程即算子工程编译生成的自定义算子安装包的安装过程,部署完成后,算子被部署在Host侧算子库OPP对应文件夹中,默认路径为/usr/local/Ascend/opp/。
Host侧自定义算子部署完成后目录结构示例如下所示:
4、FAQ
Q:UT测试时报错CMake 3.14 or higher is required. You are running version 3.10.2。
A:在服务器上更新CMake版本,通过CMake官网下载,而不是通过apt-get命令。
Q:执行UT测试时无法输出网页版报告,报错:mindstudio_tmp/mindstudio_134d8786-c88-41da-ad68-84676b6eed78/14021FE-23C-4F18-865-226809200E44.sh: 1ine 1: 1cov: command not found
Ut Impl Execute Finish.
TBE TestRun Finished
Can not find the Ut_Impl report index.html
A:pip install lcov
5、从昇腾社区获得更多帮助
开发者在使用MindStudio或进行算子开发过程中遇到任何问题,都可以来昇腾社区获得更多的帮助。
昇腾官网:昇腾社区-官网丨昇腾万里 让智能无所不及
昇腾社区:华为云社区_大数据社区_AI社区_云计算社区_开发者中心-华为云
昇腾论坛:昇腾论坛_开发者论坛-华为云论坛