图编译和图执行
本节通过单算子模型执行的样例来介绍图模式下图编译和图执行流程。单算子模型执行是指基于图IR执行算子,先编译算子(例如,使用ATC工具将Ascend IR定义的单算子描述文件编译成算子om模型文件),再调用AscendCL接口加载算子模型,最后调用AscendCL接口执行算子。下文仅提供单算子模型执行的样例和基础内容讲解,详细内容请参考单算子模型执行。
环境要求
- 已参考环境准备,完成CANN驱动和软件的安装,配置CANN软件所需基本环境变量。
安装CANN软件后,使用CANN运行用户进行编译、运行时,需要以CANN运行用户登录环境,执行source ${install_path}/set_env.sh命令设置环境变量。其中${install_path}为CANN软件的安装目录,例如:/usr/local/Ascend/ascend-toolkit。
- 已参考完成算子的开发和部署。
准备验证代码工程
├──input // 存放脚本生成的输入数据目录 ├──output // 存放算子运行输出数据和真值数据的目录 ├── inc // 头文件目录 │ ├── common.h // 声明公共方法类,用于读取二进制文件 │ ├── operator_desc.h // 算子描述声明文件,包含算子输入/输出,算子类型以及输入描述与输出描述 │ ├── op_runner.h // 算子运行相关信息声明文件,包含算子输入/输出个数,输入/输出大小等 ├── src │ ├── CMakeLists.txt // 编译规则文件 │ ├── common.cpp // 公共函数,读取二进制文件函数的实现文件 │ ├── main.cpp // 将单算子编译为om文件并加载om文件执行 │ ├── operator_desc.cpp // 构造算子的输入与输出描述 │ ├── op_runner.cpp // 单算子编译与运行函数实现文件 ├── scripts │ ├── verify_result.py // 真值对比文件 │ ├── gen_data.py // 输入数据和真值数据生成脚本文件 │ ├── acl.json // acl配置文件 │ ├── add_custom_static_shape.json // 算子描述文件,用于构造静态shape单算子模型文件 │ ├── add_custom_dynamic_shape.json // 算子描述文件,用于构造动态shape单算子模型文件
生成单算子离线模型文件
- 构造静态shape单算子描述文件add_custom_static_shape.json,描述算子的输入、输出及属性等信息。AddCustom静态shape算子的描述文件示例如下:
[ { "op": "AddCustom", "input_desc": [ { "name": "x", "param_type": "required", "format": "ND", "shape": [8, 2048], "type": "float16" }, { "name": "y", "param_type": "required", "format":"ND", "shape": [8, 2048], "type": "float16" } ], "output_desc": [ { "name": "z", "param_type": "required", "format": "ND", "shape": [8, 2048], "type": "float16" } ] } ]
AddCustom动态shape算子的描述文件示例如下:[ { "op": "AddCustom", "input_desc": [ { "name": "x", "param_type": "required", "format": "ND", "shape": [-1, -1], "shape_range": [[1,-1],[1,-1]], "type": "float16" }, { "name": "y", "param_type": "required", "format":"ND", "shape": [-1, -1], "shape_range": [[1,-1],[1,-1]], "type": "float16" } ], "output_desc": [ { "name": "z", "param_type": "required", "format": "ND", "shape": [-1, -1], "shape_range": [[1,-1],[1,-1]], "type": "float16" } ] } ]
- 使用ATC工具,将该算子描述文件编译成单算子模型文件(*.om文件)
ATC工具的命令示例如下:
atc --singleop=$HOME/op_verify/run/out/test_data/config/add_custom_static_shape.json --output=op_models/ --soc_version=<soc_version>
关键参数解释如下(详细参数说明,请参见《ATC工具使用指南》。):
- --singleop:单算子描述文件(json格式)的路径。
- --output:存放om模型文件的目录。
- --soc_version:配置为AI处理器的型号,请根据实际环境进行替换。
AI处理器的型号请通过如下方式获取:
- 在安装昇腾AI处理器的服务器执行npu-smi info命令进行查询,获取Chip Name信息。实际配置值为AscendChip Name,例如Chip Name取值为xxxyy,实际配置值为Ascendxxxyy。
以上命令执行后,会在output参数指定路径下生成*.om后缀的离线模型文件。
生成测试数据
在样例工程目录下,执行如下命令:
python3 scripts/gen_data.py
会在input目录下生成两个shape为(8,2048),数据类型为float16的数据文件input_0.bin与input_1.bin,用于进行AddCustom算子的验证。
代码样例如下:
import numpy as np a = np.random.randint(100, size=(8, 2048,)).astype(np.float16) b = np.random.randint(100, size=(8, 2048,)).astype(np.float16) a.tofile('input_0.bin') b.tofile('input_1.bin')
编写验证代码
您可以参考如下样例编写单算子加载、执行的代码逻辑。
以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考,调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。
// 1.AscendCL初始化 aclRet = aclInit("../scripts/acl.json"); // 2.运行管理资源申请 int deviceId = 0; aclRet = aclrtSetDevice(deviceid); // 获取软件栈的运行模式,不同运行模式影响后续的接口调用流程(例如是否进行数据传输等) aclrtRunMode runMode; bool g_isDevice = false; aclError aclRet = aclrtGetRunMode(&runMode); g_isDevice = (runMode == ACL_DEVICE); // 3.加载单算子模型文件(*.om文件) // 该目录相对可执行文件所在的目录,例如,编译出来的可执行文件存放在output目录下,此处就表示工程目录下的op_models目录 aclRet = aclopSetModelDir("../op_models"); // 4.设置算子的输入,申请内存,然后读取输入数据input_0.bin与input_1.bin并保存至申请的内存中 // ...... // 5.创建Stream流 aclrtStream stream = nullptr; aclrtCreateStream(&stream) // 6.执行算子 // opType表示算子类型名称,例如AddCustom // numInputs表示算子输入个数,例如AddCustom算子是2个输入 // inputDesc表示算子输入tensor描述的数组,描述每个输入的format、shape、数据类型 // inputs表示算子输入tensor数据 // numOutputs表示算子输出个数,例如AddCustom算子是1个输出 // outputDesc表示算子输出tensor描述的数组,描述每个输出的format、shape、数据类型 // outputs表示算子输出tensor数据 // attr表示算子属性,如果算子没有属性,也需要调用aclopCreateAttr接口创建aclopAttr类型的数据 // stream用于维护一些异步操作的执行顺序 aclopExecuteV2(opType, numInputs, inputDesc, inputs, numOutputs, outputDesc, outputs, attr, nullptr); // 7.阻塞应用运行,直到指定Stream中的所有任务都完成 aclrtSynchronizeStream(stream); // 8.处理执行算子后的输出数据,例如在屏幕上显示、写入文件等,由用户根据实际情况自行实现,本示例会将结果写入output_z.bin文件中 // ...... // 9.释放stream流 aclrtDestroyStream(stream); // 10.释放运行管理资源 aclRet = aclrtResetDevice(deviceid); aclRet = aclFinalize(); // ....
运行和验证
- 开发环境上,设置环境变量,配置AscendCL单算子验证程序编译依赖的头文件与库文件路径,如下为设置环境变量的示例。${INSTALL_DIR}表示CANN软件安装目录,例如,$HOME/Ascend/ascend-toolkit/latest。{arch-os}为运行环境的架构和操作系统,arch表示操作系统架构,os表示操作系统,例如x86_64-linux。
export DDK_PATH=${INSTALL_DIR} export NPU_HOST_LIB=${INSTALL_DIR}/{arch-os}/devlib
- 编译样例工程,生成单算子验证可执行文件。
- 执行单算子
- 以运行用户(例如HwHiAiUser)拷贝开发环境中样例工程output下的execute_add_op到运行环境任一目录。
说明: 若您的开发环境即为运行环境,此拷贝操作可跳过。
- 在运行环境中,执行execute_add_op文件,验证单算子模型文件。
chmod +x execute_add_op
./execute_add_op
会有如下屏显信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
[INFO] static op will be called [INFO] Set device[0] success [INFO] Get RunMode[1] success [INFO] aclopSetModelDir op model success [INFO] Init resource success [INFO] Set input success [INFO] Copy input[0] success [INFO] Copy input[1] success [INFO] Create stream success [INFO] Execute AddCustom success [INFO] Synchronize stream success [INFO] Copy output[0] success [INFO] Write output success [INFO] Run op success [INFO] Reset Device success [INFO] Destroy resource success
如果有Run op success,表明执行成功,会在outout目录下生成输出文件output_z.bin。
- 以运行用户(例如HwHiAiUser)拷贝开发环境中样例工程output下的execute_add_op到运行环境任一目录。
- 比较真值文件
python3 scripts/verify_result.py output/output_z.bin output/golden.bin
会有如下屏显信息,可见AddCustom算子验证结果正确。1
test pass