This section uses the single-operator model as an example to describe the build and execution processes in graph mode. Single-operator model execution means that operators are executed based on graph IR. First, build operators (for example, use the ATC tool to compile the single-operator description file defined by Ascend IR into an .om model file). Then, call an ACL API to load the operator model. Finally, call an ACL API to execute the operator.
After the CANN software is installed, log in to the environment as the CANN operating user and run the source ${INSTALL_DIR}/set_env.sh command to set environment variables. Replace ${INSTALL_DIR} with the CANN component directory. For example, if the installation is performed by the root user, the default file storage path is /usr/local/Ascend/cann.
├── aclop_invocation │ ├── add_custom.json // Operator description file, used to construct a single-operator model file │ ├── CMakeLists.txt │ ├── main.cpp // File used to compile a single-operator into an .om file and load the .om file for execution
[
{
"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"
}
]
}
]
The following is a command example of the ATC tool:
atc --singleop=../add_custom_static_shape.json --output=. --soc_version=<soc_version>
The key command-line options are described as follows. For details, see ATC. :
The AI processor model can be obtained in the following ways:
id indicates the device ID, which is the NPU ID obtained by running the npu-smi info -l command.
After the preceding command is executed, an offline model file with the suffix *.om is generated in the path specified by the --output option.
Compile the code logic for loading and executing a single operator by referring to the following example.
The following is a code snippet of key steps only, which is not ready to be built or run. After APIs are called, you need to add exception handling branches and record error logs and info logs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | // 1. Perform initialization. CHECK_ACL(aclInit(nullptr)); // 2. Allocate runtime resources. const int32_t deviceId = 0; CHECK_ACL(aclrtSetDevice(deviceId)); // 3. Load the single-operator model file (*.om file). CHECK_ACL(aclopSetModelDir(".")); // 4. Set the operator input, allocate memory, read the input data, and save them to the allocated memory. // ...... // 5. Create a stream. aclrtStream stream = nullptr; aclrtCreateStream(&stream); // 6. Execute the single-operator. // opType indicates the operator type name, for example, AddCustom. // inputDesc.size() indicates the number of operator inputs. For example, the AddCustom operator has two inputs. // inputDesc.data() indicates the array of the operator input tensor descriptions, describing the format, shape, and data type of each input. // inputBuffers.data() indicates the input tensor data of the operator. // outputDesc.size() indicates the number of operator outputs. For example, the AddCustom operator has one output. // outputDesc.data() indicates the array of the operator output tensor descriptions, describing the format, shape, and data type of each output. // outputBuffers.data() indicates the output tensor data of the operator. // opAttr indicates the operator attributes. If the operator does not have attributes, call aclopCreateAttr to create data of the aclopAttr type. // stream is used to maintain the execution sequence of some asynchronous operations. CHECK_ACL(aclopExecuteV2(opType, inputDesc.size(), inputDesc.data(), inputBuffers.data(), outputDesc.size(), outputDesc.data(), outputBuffers.data(), opAttr, stream)); // 7. Block the app until all tasks in the specified stream are complete. aclrtSynchronizeStream(stream); // 8. Process the output data after the operator is executed, for example, printing data to the screen or writing the data to a file. You can implement this function as required. // ...... // 9. Destroy the stream. aclrtDestroyStream(stream); // 10. Destroy runtime allocations. aclRet = aclrtResetDevice(deviceId); aclRet = aclFinalize(); // .... |
export DDK_PATH=${INSTALL_DIR} export NPU_HOST_LIB=${INSTALL_DIR}/{arch-os}/devlib
mkdir -p build
Command example:
cd build
cmake ../src -DCMAKE_SKIP_RPATH=TRUE
The executable file execute_add_op is generated in the output directory of the project.
Note: If your development environment is the operating environment, skip this step.
chmod +x execute_add_op
./execute_add_op
If "test pass" is displayed, the execution is successful.