已合并
modify quick_op_invocation #2641
chenjiao创建于 5月8日
modify quick_op_invocation #2641
已合并
共 2 个文件变更+226-309
| @@ -94,110 +94,9 @@ | |||
| 94 | 1. 查阅现有文档:模板或规范有问题,请先查阅项目已有的指南、API文档或README等。 | 94 | 1. 查阅现有文档:模板或规范有问题,请先查阅项目已有的指南、API文档或README等。 |
| 95 | 2. 发起讨论:您可以新建Issue或直接在相关Issue或PR中留言。 | 95 | 2. 发起讨论:您可以新建Issue或直接在相关Issue或PR中留言。 |
| 96 | 96 | ||
| 97 | -## 算子README模板 | 97 | +## 文档模板 |
| 98 | 98 | ||
| 99 | -针对`experimental`新贡献算子,算子README是必备文档交付件,您可以参考本节提供的**简单模板**,也支持您基于本模板进行内容拓展。 | 99 | +算子交付件中涉及的关键文档主要包括如下,具体写作格式、内容要求请参考模板。 |
| 100 | 100 | ||
| 101 | -- 文档格式:推荐Markdown文件格式,支持使用原生或Html语法,请确保所有语法须符合官方规范。 | 101 | +- [算子RAEDME文档模板](https://gitcode.com/cann/ops-math/wiki/%E7%AE%97%E5%AD%90README%E6%96%87%E6%A1%A3%E6%A8%A1%E6%9D%BF) |
| 102 | -- 文档作用:阐述清楚算子功能、实现原理、参数规格以及算子调用方式等。 | 102 | +- [aclnn API文档模板](https://gitcode.com/cann/ops-math/wiki/aclnn%20API%E6%96%87%E6%A1%A3%E6%A8%A1%E6%9D%BF) |
| 103 | -- 章节标题:优先使用模板章节名(如功能说明、参数说明等),标题层级为##,如有特殊情况层级请按序增加。支持章节自定义拓展,可选章节视情况呈现。 | ||
| 104 | -- 内容要求:每章内容写作目标、写作规范请参考下文详细描述,为方便理解,将以[AddExample](../examples/add_example/README.md)算子README为例。 | ||
| 105 | - | ||
| 106 | -### 产品支持情况 | ||
| 107 | - | ||
| 108 | -> **写作规范**:推荐表格形式,罗列支持的产品型号,并打√,产品形态介绍请参见[昇腾产品形态说明](https://www.hiascend.com/document/redirect/CannCommunityProductForm)。 | ||
| 109 | - | ||
| 110 | -| 产品 | 是否支持 | | ||
| 111 | -| :----------------------------------------- | :------:| | ||
| 112 | -| Atlas A3 训练系列产品/Atlas A3 推理系列产品 | √ | | ||
| 113 | -| Atlas A2 训练系列产品/Atlas A2 推理系列产品 | √ | | ||
| 114 | - | ||
| 115 | -### 功能说明 | ||
| 116 | - | ||
| 117 | -> [!NOTE] | ||
| 118 | -> | ||
| 119 | -> **写作目标**:阐明算子功能、计算原理、参数规格、调用方式、使用场景等。 | ||
| 120 | -> | ||
| 121 | -> **写作规范**:推荐无序列表形式,一般包括如下维度 | ||
| 122 | -> | ||
| 123 | -> - 算子功能(必选):请以一句话形式简洁明了阐述功能。 | ||
| 124 | -> - 计算公式(可选):复杂功能可借助公式介绍算子实现原理或不同场景下的计算过程。 | ||
| 125 | -> - 其他维度(可选):支持无序列表拓展,请根据实际情况自定义,比如计算示例、流程图等。 | ||
| 126 | - | ||
| 127 | -- 算子功能:完成张量加法计算。 | ||
| 128 | -- 计算公式: | ||
| 129 | - $$ | ||
| 130 | - y = x1 + x2 | ||
| 131 | - $$ | ||
| 132 | - | ||
| 133 | -### 参数说明 | ||
| 134 | - | ||
| 135 | -> [!NOTE] | ||
| 136 | -> | ||
| 137 | -> **写作目标**:阐明算子定义的参数含义、作用、规格等信息。 | ||
| 138 | -> | ||
| 139 | -> **写作规范**:采用表格形式,一般包括如下维度 | ||
| 140 | -> | ||
| 141 | -> - 参数名:解释算子定义文件中的参数,顺序保持一致,例如`op_host/add_example_def.cpp`或`op_graph/add_example_proto.h`。 | ||
| 142 | -> - 输入/输出/属性:明确参数定位,默认是必选,若为可选一般为可选输入/可选输出/可选属性。 | ||
| 143 | -> - 描述:提供参数含义、功能、使用场景等介绍,包括与上述公式变量的映射关系。 | ||
| 144 | -> - 数据类型:参数支持的data type,张量数据类型一般为`DT_XXX`形式。为方便写作,可不带`DT_`前缀。 | ||
| 145 | -> - 数据格式:参数支持的数据排布方式,张量format一般为`FORMAT_xxx`形式。为方便写作,可不带`FORMAT_`前缀。 | ||
| 146 | -> - 其他维度(可选):支持表格字段扩展,请根据实际情况自定义,比如shape规格等。 | ||
| 147 | - | ||
| 148 | -|参数名|输入/输出/属性|描述|数据类型|数据格式| | ||
| 149 | -|-----|-----------|----|---------|------| | ||
| 150 | -|x1|输入|表示add_example计算的第一个张量,即公式中`x1`。|FLOAT、FLOAT16、INT32|ND| | ||
| 151 | -|x2|输入|表示add_example计算的第二个张量,即公式中`x2`。|数据类型与x1保持一致|ND| | ||
| 152 | -|y| 输出 | 表示add_example计算结果张量,即公式中`y`。 |FLOAT、FLOAT16、INT32|ND| | ||
| 153 | - | ||
| 154 | -### 约束说明(可选) | ||
| 155 | - | ||
| 156 | -> [!NOTE] | ||
| 157 | -> | ||
| 158 | -> **写作目标**: 阐明算子使用过程中的注意事项,例如参数组合约束、适用场景、对业务影响、算子性能或精度等。 | ||
| 159 | -> | ||
| 160 | -> **写作规范**:**本章为可选**,若无约束可不呈现本章内容;若有请采用无序列表形式。 | ||
| 161 | - | ||
| 162 | -无 | ||
| 163 | - | ||
| 164 | -### 调用说明 | ||
| 165 | - | ||
| 166 | -> [!NOTE] | ||
| 167 | -> | ||
| 168 | -> **写作目标**: 提供算子调用方法,尽量是可直接拷贝运行的示例代码,方便快速验证。 | ||
| 169 | -> | ||
| 170 | -> **写作规范**:推荐表格形式,如果内容复杂可采用其他形式。 | ||
| 171 | -> | ||
| 172 | -> - 调用方式:支持aclnn、图模式等方式调用,也支持您自定义,请提供至少一种方式。 | ||
| 173 | -> - 样例代码:请在算子的`examples`目录提供调用示例代码,例如`examples/test_aclnn_add_example.cpp`。文件命名规则为test\_\$\{invoke\_mode\}\_\${op_name},\$\{invoke\_mode\}表示调用方式,\${op_name}表示算子名。 | ||
| 174 | -> - 说明:不同调用方式的补充说明,例如调用场景、调用原理、编译运行指导等,请根据实际情况自定义。 | ||
| 175 | - | ||
| 176 | -<table><thead> | ||
| 177 | - <tr> | ||
| 178 | - <th>调用方式</th> | ||
| 179 | - <th>调用样例</th> | ||
| 180 | - <th>说明</th> | ||
| 181 | - </tr></thead> | ||
| 182 | -<tbody> | ||
| 183 | - <tr> | ||
| 184 | - <td>aclnn调用</td> | ||
| 185 | - <td><a href="../examples/add_example/examples/test_aclnn_add_example.cpp">test_aclnn_add_example</a></td> | ||
| 186 | - <td rowspan="2">参见<a href="./zh/invocation/quick_op_invocation.md">算子调用</a>完成算子编译和验证。</td> | ||
| 187 | - </tr> | ||
| 188 | - <tr> | ||
| 189 | - <td>图模式调用</td> | ||
| 190 | - <td><a href="../examples/add_example/examples/test_geir_add_example.cpp">test_geir_add_example</a></td> | ||
| 191 | - </tr> | ||
| 192 | -</tbody> | ||
| 193 | -</table> | ||
| 194 | - | ||
| 195 | -### 参考资源(可选) | ||
| 196 | - | ||
| 197 | -> [!NOTE] | ||
| 198 | -> | ||
| 199 | -> **写作目标**: 提供除算子功能、规格、调用外的其他补充介绍,例如算子设计文档(Tiling/Kernel设计)、参考文献等。 | ||
| 200 | -> | ||
| 201 | -> **写作规范**:**本章为可选**,若无约束可不呈现本章内容;若有请采用无序列表形式。 | ||
| 202 | - | ||
| 203 | -无 | ||
| @@ -2,16 +2,38 @@ | |||
| 2 | 2 | ||
| 3 | ## 使用须知 | 3 | ## 使用须知 |
| 4 | 4 | ||
| 5 | -- 前提说明:算子调用前,请参考本项目README完成环境准备和源码下载,再完成[源码构建](../install/compile.md),此处不再赘述。 | 5 | +- 前提说明:算子调用前,请参考本项目README完成环境准备和源码下载,此处不再赘述。 |
| 6 | -- 调用算子:支持调用非experimental目录算子(内置算子,清单详见[算子列表](../op_list.md))和experimental目录算子(贡献算子)。 | ||
| 7 | 6 | ||
| 8 | -## 调用算子样例 | 7 | +- 调用范围:支持调用的算子清单参见[算子列表](../op_list.md),此外还支持调用experimental贡献目录的算子。 |
| 9 | 8 | ||
| 10 | -如何快速调用项目中的算子,本章介绍最简调用方法,通过build.sh命令执行算子样例。 | 9 | +- 调用场景: 请根据实际场景诉求选择合适的算子调用方案。 |
| 10 | + | ||
| 11 | + |调用场景|场景说明|特点| | ||
| 12 | + |--------|----|-----| | ||
| 13 | + |[快速调用算子](#快速调用算子)|适用于快速体验和验证算子功能的场景。|**无需搭建调用工程**,基于源码编译包和项目脚本build.sh可直接调用算子样例。| | ||
| 14 | + |[业务应用集成算子](#业务应用集成算子)|适用于将算子灵活集成到实际业务应用中。|**需自行搭建调用工程**,手动创建调用脚本/CMake工程,灵活实现算子编译和运行。| | ||
| 15 | + | ||
| 16 | +- 调用方式:当前主要提供如下算子调用方式,请按需选择。 | ||
| 17 | + | ||
| 18 | + |调用方式|说明| | ||
| 19 | + |--------|----| | ||
| 20 | + |[PyTorch API](#pytorch-api)|将算子Kernel注册到PyTorch原生框架,以类似于Torch原生API方式实现算子调用。| | ||
| 21 | + |[aclnn API](#aclnn-api)|针对算子提供相应的C语言API(前缀为aclnn),无需提供IR定义,实现API直接调用算子。| | ||
| 22 | + |[GE图模式](#ge图模式)|通过算子IR(Intermediate Representation)定义,以构图方式实现算子调用。| | ||
| 23 | + | ||
| 24 | +## 快速调用算子 | ||
| 25 | + | ||
| 26 | +**如需快速体验或验证项目中已有算子功能,可参考本章最简调用方法,通过build.sh执行算子样例**。 | ||
| 27 | + | ||
| 28 | +该方法特点是无需搭建调用工程(即创建编译/运行脚本等),简单易操作。 | ||
| 11 | 29 | ||
| 12 | > **说明**:对于Ascend 950PR产品,可通过Simulator仿真工具执行算子样例,详见[仿真指导](../debug/op_debug_prof.md#方式二针对ascend-950pr)。 | 30 | > **说明**:对于Ascend 950PR产品,可通过Simulator仿真工具执行算子样例,详见[仿真指导](../debug/op_debug_prof.md#方式二针对ascend-950pr)。 |
| 13 | 31 | ||
| 14 | -- 基于**自定义算子包**执行算子样例,包安装后,执行如下命令: | 32 | +**步骤1**:参考[源码构建指南](../install/compile.md)完成源码包编译和部署。 |
| 33 | + | ||
| 34 | +**步骤2**:执行项目中已有算子的样例。 | ||
| 35 | + | ||
| 36 | +- 基于**自定义算子包**执行算子样例,命令如下: | ||
| 15 | 37 | ||
| 16 | ```bash | 38 | ```bash |
| 17 | bash build.sh --run_example ${op} ${mode} ${pkg_mode} [--vendor_name=${vendor_name}] [--soc=${soc_version}] [--experimental] | 39 | bash build.sh --run_example ${op} ${mode} ${pkg_mode} [--vendor_name=${vendor_name}] [--soc=${soc_version}] [--experimental] |
| @@ -21,27 +43,27 @@ | |||
| 21 | # bash build.sh --experimental --run_example abs eager cust --vendor_name=custom | 43 | # bash build.sh --experimental --run_example abs eager cust --vendor_name=custom |
| 22 | ``` | 44 | ``` |
| 23 | 45 | ||
| 24 | - - \$\{op\}:表示待执行算子,算子名小写下划线形式,如abs。 | 46 | + - \$\{op\}:表示待执行算子,算子名小写下划线形式,如abs。 |
| 25 | - - \$\{mode\}:表示调用方式,目前支持eager(aclnn调用)、graph(图模式调用)。 | 47 | + - \$\{mode\}:表示调用方式,目前支持eager(aclnn调用)、graph(图模式调用)。 |
| 26 | - - \$\{pkg_mode\}:表示包模式,目前仅支持cust,即自定义算子包。 | 48 | + - \$\{pkg_mode\}:表示包模式,目前仅支持cust,即自定义算子包。 |
| 27 | - - \$\{vendor\_name\}(可选):与构建的自定义算子包设置一致,默认名为custom。 | 49 | + - \$\{vendor\_name\}(可选):与构建的自定义算子包设置一致,默认名为custom。 |
| 28 | - - \$\{soc_version\}(可选):表示NPU型号。 | 50 | + - \$\{soc_version\}(可选):表示NPU型号。 |
| 29 | - - \$\{experimental\}(可选):表示执行用户保存在experimental贡献目录下的算子。 | 51 | + - \$\{experimental\}(可选):表示执行用户保存在experimental贡献目录下的算子。 |
| 30 | - | 52 | + |
| 31 | 说明:\$\{mode\}为graph时,不指定\$\{pkg_mode\}和\$\{vendor\_name\} | 53 | 说明:\$\{mode\}为graph时,不指定\$\{pkg_mode\}和\$\{vendor\_name\} |
| 32 | 54 | ||
| 33 | -- 基于**ops-math包**执行算子样例,安装后,执行如下命令: | 55 | +- 基于**ops-math包**执行算子样例,命令如下: |
| 34 | 56 | ||
| 35 | ```bash | 57 | ```bash |
| 36 | bash build.sh --run_example ${op} ${mode} [--soc=${soc_version}] | 58 | bash build.sh --run_example ${op} ${mode} [--soc=${soc_version}] |
| 37 | # 以Abs算子example执行为例 | 59 | # 以Abs算子example执行为例 |
| 38 | # bash build.sh --run_example abs eager | 60 | # bash build.sh --run_example abs eager |
| 39 | ``` | 61 | ``` |
| 40 | - | 62 | + |
| 41 | - - \$\{op\}:表示待执行算子,算子名小写下划线形式,如abs。 | 63 | + - \$\{op\}:表示待执行算子,算子名小写下划线形式,如abs。 |
| 42 | - - \$\{mode\}:表示算子执行模式,目前支持eager(aclnn调用)、graph(图模式调用)。 | 64 | + - \$\{mode\}:表示算子执行模式,目前支持eager(aclnn调用)、graph(图模式调用)。 |
| 43 | - - \$\{soc_version\}(可选):表示NPU型号。 | 65 | + - \$\{soc_version\}(可选):表示NPU型号。 |
| 44 | - | 66 | + |
| 45 | - 基于**ops-math静态库**执行算子样例: | 67 | - 基于**ops-math静态库**执行算子样例: |
| 46 | 68 | ||
| 47 | 1. **前提条件** | 69 | 1. **前提条件** |
| @@ -59,7 +81,7 @@ | |||
| 59 | ```bash | 81 | ```bash |
| 60 | # 静态库文件路径 | 82 | # 静态库文件路径 |
| 61 | static_lib_path="" | 83 | static_lib_path="" |
| 62 | - | 84 | + |
| 63 | # 环境变量生效 | 85 | # 环境变量生效 |
| 64 | if [ -n "$ASCEND_INSTALL_PATH" ]; then | 86 | if [ -n "$ASCEND_INSTALL_PATH" ]; then |
| 65 | _ASCEND_INSTALL_PATH=$ASCEND_INSTALL_PATH | 87 | _ASCEND_INSTALL_PATH=$ASCEND_INSTALL_PATH |
| @@ -68,9 +90,9 @@ | |||
| 68 | else | 90 | else |
| 69 | _ASCEND_INSTALL_PATH="/usr/local/Ascend/cann" | 91 | _ASCEND_INSTALL_PATH="/usr/local/Ascend/cann" |
| 70 | fi | 92 | fi |
| 71 | - | 93 | + |
| 72 | source ${_ASCEND_INSTALL_PATH}/bin/setenv.bash | 94 | source ${_ASCEND_INSTALL_PATH}/bin/setenv.bash |
| 73 | - | 95 | + |
| 74 | # 编译可执行文件 | 96 | # 编译可执行文件 |
| 75 | g++ test_aclnn_abs.cpp \ | 97 | g++ test_aclnn_abs.cpp \ |
| 76 | -I ${static_lib_path}/include \ | 98 | -I ${static_lib_path}/include \ |
| @@ -83,145 +105,144 @@ | |||
| 83 | -lpthread -lmmpa -lmetadef -lascendalog -lregister -lopp_registry -lops_base -lascendcl -ltiling_api -lplatform \ | 105 | -lpthread -lmmpa -lmetadef -lascendalog -lregister -lopp_registry -lops_base -lascendcl -ltiling_api -lplatform \ |
| 84 | -ldl -lc_sec -lnnopbase -lruntime -lerror_manager -lunified_dlog \ | 106 | -ldl -lc_sec -lnnopbase -lruntime -lerror_manager -lunified_dlog \ |
| 85 | -o test_aclnn_abs # 替换为实际算子可执行文件名 | 107 | -o test_aclnn_abs # 替换为实际算子可执行文件名 |
| 86 | - | 108 | + |
| 87 | # 执行程序 | 109 | # 执行程序 |
| 88 | ./test_aclnn_abs | 110 | ./test_aclnn_abs |
| 89 | ``` | 111 | ``` |
| 90 | 112 | ||
| 91 | \$\{static\_lib\_path\}表示静态库统一放置路径; \$\{ASCEND\_INSTALL\_PATH\}已通过环境变量配置,表示CANN toolkit包安装路径; 最终可执行文件名请替换为**实际算子可执行文件名**。 | 113 | \$\{static\_lib\_path\}表示静态库统一放置路径; \$\{ASCEND\_INSTALL\_PATH\}已通过环境变量配置,表示CANN toolkit包安装路径; 最终可执行文件名请替换为**实际算子可执行文件名**。 |
| 92 | - | 114 | + |
| 93 | - 其中lcann\_math\_static、lcann\_legacy\_static表示算子依赖的静态库文件,从静态库统一放置路径\$\{static\_lib\_path\}中获取; | 115 | + 其中lcann\_math\_static、lcann\_legacy\_static表示算子依赖的静态库文件,从静态库统一放置路径\$\{static\_lib\_path\}中获取; |
| 94 | - lgraph、lmetadef等表示算子依赖的底层库文件,可在CANN toolkit包获取。 | 116 | + lgraph、lmetadef等表示算子依赖的底层库文件,可在CANN toolkit包获取。 |
| 95 | - | 117 | + |
| 96 | 3. **执行run.sh** | 118 | 3. **执行run.sh** |
| 97 | 119 | ||
| 98 | ```bash | 120 | ```bash |
| 99 | bash run.sh | 121 | bash run.sh |
| 100 | ``` | 122 | ``` |
| 101 | 123 | ||
| 102 | -无论上述哪种方式,算子样例执行后会打印结果,以Abs算子为例: | 124 | +**步骤3**:检查执行结果。 |
| 103 | 125 | ||
| 104 | -```bash | 126 | +算子样例执行后会打印结果,以Abs算子结果为例: |
| 105 | -abs result[0] is: 1.000000 | ||
| 106 | -abs result[1] is: 1.000000 | ||
| 107 | -abs result[2] is: 1.000000 | ||
| 108 | -abs result[3] is: 2.000000 | ||
| 109 | -abs result[4] is: 2.000000 | ||
| 110 | -abs result[5] is: 2.000000 | ||
| 111 | -abs result[6] is: 3.000000 | ||
| 112 | -abs result[7] is: 3.000000 | ||
| 113 | -``` | ||
| 114 | 127 | ||
| 115 | -## 调用方式 | 128 | + ```text |
| 129 | + abs result[0] is: 1.000000 | ||
| 130 | + abs result[1] is: 1.000000 | ||
| 131 | + abs result[2] is: 1.000000 | ||
| 132 | + abs result[3] is: 2.000000 | ||
| 133 | + abs result[4] is: 2.000000 | ||
| 134 | + abs result[5] is: 2.000000 | ||
| 135 | + abs result[6] is: 3.000000 | ||
| 136 | + abs result[7] is: 3.000000 | ||
| 137 | + ``` | ||
| 116 | 138 | ||
| 117 | -通过build.sh执行算子时,其底层调用算子的原理目前包括如下几种方式: | 139 | +## 业务应用集成算子 |
| 118 | 140 | ||
| 119 | -- PyTorch调用**(建设中)**:通过`<<<>>>`方式启动算子Kernel,流程极简,实现PyTorch方式调用NPU算子。 | 141 | +**如需将算子集成到实际业务应用中,可参考本章自行搭建调用工程。通过自定义调用脚本/CMake工程等,实现算子编译和运行**。 |
| 120 | 142 | ||
| 121 | -- aclnn调用 **(推荐)**:Host侧提供算子对应的C语言API(前缀aclnn),无需提供IR定义,实现aclnn API方式调用算子。 | 143 | +该方法特点是手动搭建调用工程,场景灵活度高,可移植性强。 |
| 122 | 144 | ||
| 123 | -- 图模式调用:提供IR(Intermediate Representation)定义,实现构图方式调用算子。 | 145 | +不同调用方式对应的编译工程不同,当前支持PyTorch API、aclnn API、GE图模式调用方式,调用方法和实践请参考下文,请按需选择。 |
| 124 | 146 | ||
| 125 | -### PyTorch调用(建设中) | 147 | +### PyTorch API |
| 126 | 148 | ||
| 127 | -该方式提供一套基于Ascend Extension for PyTorch(torch_npu)框架调用NPU算子的方法,具体调用原理和过程请参考[examples/fast_kernel_launch_example](../../../examples/fast_kernel_launch_example/README.md),内容仍在建设和优化中,欢迎您提问和建议。 | 149 | +该方式将算子Kernel注册到PyTorch原生框架,以类似于Torch原生API方式实现算子调用。 |
| 128 | 150 | ||
| 129 | -### aclnn调用 | 151 | +具体调用原理和过程请参考[examples/fast_kernel_launch_example](../../../examples/fast_kernel_launch_example/README.md),内容仍在建设和优化中,欢迎您提问和建议。 |
| 152 | + | ||
| 153 | +### aclnn API | ||
| 130 | 154 | ||
| 131 | #### 调用流程 | 155 | #### 调用流程 |
| 132 | 156 | ||
| 133 | -该方式也称为“单算子API调用”,通过提供一套基于C的API(以aclnn为前缀API)实现算子调用,无需提供算子IR(Intermediate Representation)定义。aclnn API的调用流程如下: | 157 | +为方便调用算子,Host侧提供算子对应的C语言API(以aclnn为前缀API)实现算子调用,无需提供算子IR(Intermediate Representation)定义。aclnn API调用流程如下: |
| 134 | 158 | ||
| 135 |  | 159 |  |
| 136 | 160 | ||
| 137 | -aclnn API调用示例以`AddExample`算子为例,代码示例如下,仅供参考,全量代码参见[test_aclnn_add_example.cpp](../../../examples/add_example/examples/test_aclnn_add_example.cpp)。调用前,请按照环境安装的提示信息设置环境变量。 | 161 | +#### 编译运行 |
| 138 | 162 | ||
| 139 | -> 注意:如需调用项目已实现的算子,可访问目标算子`examples`目录下test\_aclnn\_\$\{op\_name\}.cpp,\$\{op\_name\}表示算子名。 | 163 | +> 注意:操作过程中,如遇到日志提示设置环境变量,请按提示操作。 |
| 140 | 164 | ||
| 141 | -```Cpp | 165 | +1. 创建调用脚本。 |
| 142 | -int main() | ||
| 143 | -{ | ||
| 144 | - // 1. 调用acl进行device/stream初始化 | ||
| 145 | - int32_t deviceId = 0; | ||
| 146 | - aclrtStream stream; | ||
| 147 | - auto ret = Init(deviceId, &stream); | ||
| 148 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 149 | 166 | ||
| 150 | - // 2. 构造输入与输出,需要根据API的接口自定义构造 | 167 | + 在目标算子`examples`目录下,新建调用脚本test\_aclnn\_\$\{op\_name\}.cpp,\$\{op\_name\}表示目标算子名。以`AddExample`算子为例,调用脚本如下,仅供参考,全量代码参见[test_aclnn_add_example.cpp](../../../examples/add_example/examples/test_aclnn_add_example.cpp)。 |
| 151 | - aclTensor* selfX = nullptr; | ||
| 152 | - void* selfXDeviceAddr = nullptr; | ||
| 153 | - std::vector<int64_t> selfXShape = {32, 4, 4, 4}; | ||
| 154 | - std::vector<float> selfXHostData(2048, 1); | ||
| 155 | - ret = CreateAclTensor(selfXHostData, selfXShape, &selfXDeviceAddr, aclDataType::ACL_FLOAT, &selfX); | ||
| 156 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 157 | 168 | ||
| 158 | - aclTensor* selfY = nullptr; | 169 | + ```Cpp |
| 159 | - void* selfYDeviceAddr = nullptr; | 170 | + int main() |
| 160 | - std::vector<int64_t> selfYShape = {32, 4, 4, 4}; | 171 | + { |
| 161 | - std::vector<float> selfYHostData(2048, 1); | 172 | + // 1. 调用acl进行device/stream初始化 |
| 162 | - ret = CreateAclTensor(selfYHostData, selfYShape, &selfYDeviceAddr, aclDataType::ACL_FLOAT, &selfY); | 173 | + int32_t deviceId = 0; |
| 163 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 174 | + aclrtStream stream; |
| 164 | - | 175 | + auto ret = Init(deviceId, &stream); |
| 165 | - aclTensor* out = nullptr; | 176 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); |
| 166 | - void* outDeviceAddr = nullptr; | 177 | + |
| 167 | - std::vector<int64_t> outShape = {32, 4, 4, 4}; | 178 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 |
| 168 | - std::vector<float> outHostData(2048, 1); | 179 | + aclTensor* selfX = nullptr; |
| 169 | - ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | 180 | + void* selfXDeviceAddr = nullptr; |
| 170 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 181 | + std::vector<int64_t> selfXShape = {32, 4, 4, 4}; |
| 171 | - | 182 | + std::vector<float> selfXHostData(2048, 1); |
| 172 | - // 3. 调用CANN算子库API,需要修改为具体的Api名称 | 183 | + ret = CreateAclTensor(selfXHostData, selfXShape, &selfXDeviceAddr, aclDataType::ACL_FLOAT, &selfX); |
| 173 | - uint64_t workspaceSize = 0; | 184 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 174 | - aclOpExecutor* executor; | 185 | + |
| 175 | - | 186 | + aclTensor* selfY = nullptr; |
| 176 | - // 4. 调用aclnnAddExample第一段接口 | 187 | + void* selfYDeviceAddr = nullptr; |
| 177 | - ret = aclnnAddExampleGetWorkspaceSize(selfX, selfY, out, &workspaceSize, &executor); | 188 | + std::vector<int64_t> selfYShape = {32, 4, 4, 4}; |
| 178 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAddExampleGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | 189 | + std::vector<float> selfYHostData(2048, 1); |
| 179 | - | 190 | + ret = CreateAclTensor(selfYHostData, selfYShape, &selfYDeviceAddr, aclDataType::ACL_FLOAT, &selfY); |
| 180 | - // 根据第一段接口计算出的workspaceSize申请device内存 | 191 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 181 | - void* workspaceAddr = nullptr; | 192 | + |
| 182 | - if (workspaceSize > static_cast<uint64_t>(0)) { | 193 | + aclTensor* out = nullptr; |
| 183 | - ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | 194 | + void* outDeviceAddr = nullptr; |
| 184 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | 195 | + std::vector<int64_t> outShape = {32, 4, 4, 4}; |
| 185 | - } | 196 | + std::vector<float> outHostData(2048, 1); |
| 186 | - | 197 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); |
| 187 | - // 5. 调用aclnnAddExample第二段接口 | 198 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 188 | - ret = aclnnAddExample(workspaceAddr, workspaceSize, executor, stream); | 199 | + |
| 189 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAddExample failed. ERROR: %d\n", ret); return ret); | 200 | + // 3. 调用CANN算子库API,需要修改为具体的Api名称 |
| 190 | - | 201 | + uint64_t workspaceSize = 0; |
| 191 | - // 6. (固定写法)同步等待任务执行结束 | 202 | + aclOpExecutor* executor; |
| 192 | - ret = aclrtSynchronizeStream(stream); | 203 | + |
| 193 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | 204 | + // 4. 调用aclnnAddExample第一段接口 |
| 194 | - | 205 | + ret = aclnnAddExampleGetWorkspaceSize(selfX, selfY, out, &workspaceSize, &executor); |
| 195 | - // 7. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | 206 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAddExampleGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); |
| 196 | - PrintOutResult(outShape, &outDeviceAddr); | 207 | + |
| 197 | - | 208 | + // 根据第一段接口计算出的workspaceSize申请device内存 |
| 198 | - // 8. 释放aclTensor,需要根据具体API的接口定义修改 | 209 | + void* workspaceAddr = nullptr; |
| 199 | - aclDestroyTensor(selfX); | 210 | + if (workspaceSize > static_cast<uint64_t>(0)) { |
| 200 | - aclDestroyTensor(selfY); | 211 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); |
| 201 | - aclDestroyTensor(out); | 212 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); |
| 202 | - | 213 | + } |
| 203 | - // 9. 释放device资源 | 214 | + |
| 204 | - aclrtFree(selfXDeviceAddr); | 215 | + // 5. 调用aclnnAddExample第二段接口 |
| 205 | - aclrtFree(selfYDeviceAddr); | 216 | + ret = aclnnAddExample(workspaceAddr, workspaceSize, executor, stream); |
| 206 | - aclrtFree(outDeviceAddr); | 217 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAddExample failed. ERROR: %d\n", ret); return ret); |
| 207 | - if (workspaceSize > static_cast<uint64_t>(0)) { | 218 | + |
| 208 | - aclrtFree(workspaceAddr); | 219 | + // 6. (固定写法)同步等待任务执行结束 |
| 209 | - } | 220 | + ret = aclrtSynchronizeStream(stream); |
| 210 | - aclrtDestroyStream(stream); | 221 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); |
| 211 | - aclrtResetDevice(deviceId); | 222 | + |
| 212 | - | 223 | + // 7. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 |
| 213 | - // 9. acl去初始化 | 224 | + PrintOutResult(outShape, &outDeviceAddr); |
| 214 | - aclFinalize(); | 225 | + |
| 215 | - return 0; | 226 | + // 8. 释放aclTensor,需要根据具体API的接口定义修改 |
| 216 | -} | 227 | + aclDestroyTensor(selfX); |
| 217 | -``` | 228 | + aclDestroyTensor(selfY); |
| 218 | - | 229 | + aclDestroyTensor(out); |
| 219 | -#### 编译与运行 | 230 | + |
| 220 | - | 231 | + // 9. 释放device资源 |
| 221 | ->说明:对于本项目内已实现的算子(非自定义算子),可通过根目录下build.sh直接运行算子,操作请参考[调用算子样例](#调用算子样例)。 | 232 | + aclrtFree(selfXDeviceAddr); |
| 222 | - | 233 | + aclrtFree(selfYDeviceAddr); |
| 223 | -1. 前提条件。 | 234 | + aclrtFree(outDeviceAddr); |
| 224 | - 请参考本项目[源码编译](./quick_op_invocation.md#源码编译)完成目标算子的编译部署。 | 235 | + if (workspaceSize > static_cast<uint64_t>(0)) { |
| 236 | + aclrtFree(workspaceAddr); | ||
| 237 | + } | ||
| 238 | + aclrtDestroyStream(stream); | ||
| 239 | + aclrtResetDevice(deviceId); | ||
| 240 | + | ||
| 241 | + // 9. acl去初始化 | ||
| 242 | + aclFinalize(); | ||
| 243 | + return 0; | ||
| 244 | + } | ||
| 245 | + ``` | ||
| 225 | 246 | ||
| 226 | 2. 创建CMakeLists.txt文件。 | 247 | 2. 创建CMakeLists.txt文件。 |
| 227 | 248 | ||
| @@ -231,28 +252,28 @@ int main() | |||
| 231 | cmake_minimum_required(VERSION 3.14) | 252 | cmake_minimum_required(VERSION 3.14) |
| 232 | # 设置工程名 | 253 | # 设置工程名 |
| 233 | project(ACLNN_EXAMPLE) | 254 | project(ACLNN_EXAMPLE) |
| 234 | - | 255 | + |
| 235 | # 设置C++编译标准 | 256 | # 设置C++编译标准 |
| 236 | add_compile_options(-std=c++11) | 257 | add_compile_options(-std=c++11) |
| 237 | - | 258 | + |
| 238 | # 设置编译输出目录为当前目录下的bin文件夹 | 259 | # 设置编译输出目录为当前目录下的bin文件夹 |
| 239 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "./bin") | 260 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "./bin") |
| 240 | - | 261 | + |
| 241 | # 设置调试和发布模式的编译选项 | 262 | # 设置调试和发布模式的编译选项 |
| 242 | set(CMAKE_CXX_FLAGS_DEBUG "-fPIC -O0 -g -Wall") | 263 | set(CMAKE_CXX_FLAGS_DEBUG "-fPIC -O0 -g -Wall") |
| 243 | set(CMAKE_CXX_FLAGS_RELEASE "-fPIC -O2 -Wall") | 264 | set(CMAKE_CXX_FLAGS_RELEASE "-fPIC -O2 -Wall") |
| 244 | - | 265 | + |
| 245 | # 添加可执行文件(请替换为实际算子可执行文件),指定算子调用的*.cpp文件 | 266 | # 添加可执行文件(请替换为实际算子可执行文件),指定算子调用的*.cpp文件 |
| 246 | add_executable(test_aclnn_add_example | 267 | add_executable(test_aclnn_add_example |
| 247 | test_aclnn_add_example.cpp) | 268 | test_aclnn_add_example.cpp) |
| 248 | - | 269 | + |
| 249 | # ASCEND_PATH(CANN软件包目录,请根据实际路径修改) | 270 | # ASCEND_PATH(CANN软件包目录,请根据实际路径修改) |
| 250 | if(NOT "$ENV{ASCEND_HOME_PATH}" STREQUAL "") | 271 | if(NOT "$ENV{ASCEND_HOME_PATH}" STREQUAL "") |
| 251 | set(ASCEND_PATH $ENV{ASCEND_HOME_PATH}) | 272 | set(ASCEND_PATH $ENV{ASCEND_HOME_PATH}) |
| 252 | else() | 273 | else() |
| 253 | set(ASCEND_PATH "/usr/local/Ascend/cann") | 274 | set(ASCEND_PATH "/usr/local/Ascend/cann") |
| 254 | endif() | 275 | endif() |
| 255 | - | 276 | + |
| 256 | # 获取自定义算子包名称,存在多个自定义算子包时,只会使用其中一个 | 277 | # 获取自定义算子包名称,存在多个自定义算子包时,只会使用其中一个 |
| 257 | set(VENDORS_DIR "${ASCEND_PATH}/opp/vendors") | 278 | set(VENDORS_DIR "${ASCEND_PATH}/opp/vendors") |
| 258 | file(GLOB CUSTOM_DIRS "${VENDORS_DIR}/*") | 279 | file(GLOB CUSTOM_DIRS "${VENDORS_DIR}/*") |
| @@ -261,11 +282,11 @@ int main() | |||
| 261 | set(TARGET_SUBDIR ${CUSTOM_DIR}) | 282 | set(TARGET_SUBDIR ${CUSTOM_DIR}) |
| 262 | endif() | 283 | endif() |
| 263 | endforeach() | 284 | endforeach() |
| 264 | - | 285 | + |
| 265 | if(NOT DEFINED TARGET_SUBDIR) | 286 | if(NOT DEFINED TARGET_SUBDIR) |
| 266 | message(FATAL_ERROR "在路径${ASCEND_PATH}中未找到自定义算子包") | 287 | message(FATAL_ERROR "在路径${ASCEND_PATH}中未找到自定义算子包") |
| 267 | endif() | 288 | endif() |
| 268 | - | 289 | + |
| 269 | # 设置头文件路径 | 290 | # 设置头文件路径 |
| 270 | set(INCLUDE_BASE_DIR "${ASCEND_PATH}/include") | 291 | set(INCLUDE_BASE_DIR "${ASCEND_PATH}/include") |
| 271 | include_directories( | 292 | include_directories( |
| @@ -276,7 +297,7 @@ int main() | |||
| 276 | include_directories( | 297 | include_directories( |
| 277 | ${INCLUDE_BASE_DIR} | 298 | ${INCLUDE_BASE_DIR} |
| 278 | ) | 299 | ) |
| 279 | - | 300 | + |
| 280 | # 链接所需的动态库 | 301 | # 链接所需的动态库 |
| 281 | target_link_libraries(test_aclnn_add_example PRIVATE # 替换实际算子可执行文件 | 302 | target_link_libraries(test_aclnn_add_example PRIVATE # 替换实际算子可执行文件 |
| 282 | ${ASCEND_PATH}/lib64/libascendcl.so | 303 | ${ASCEND_PATH}/lib64/libascendcl.so |
| @@ -287,15 +308,15 @@ int main() | |||
| 287 | target_link_options(test_aclnn_add_example PRIVATE | 308 | target_link_options(test_aclnn_add_example PRIVATE |
| 288 | "-Wl,-rpath,${TARGET_SUBDIR}/op_api/lib" # 仅自定义算子需要 | 309 | "-Wl,-rpath,${TARGET_SUBDIR}/op_api/lib" # 仅自定义算子需要 |
| 289 | ) | 310 | ) |
| 290 | - | 311 | + |
| 291 | # 安装目标文件到bin目录 | 312 | # 安装目标文件到bin目录 |
| 292 | install(TARGETS test_aclnn_add_example DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) | 313 | install(TARGETS test_aclnn_add_example DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) |
| 293 | ``` | 314 | ``` |
| 294 | 315 | ||
| 295 | 3. 创建run.sh文件。 | 316 | 3. 创建run.sh文件。 |
| 296 | - | 317 | + |
| 297 | 在test\_aclnn\_\$\{op\_name\}.cpp同级目录下创建run.sh文件,以`AddExample`算子为例,示例如下,请根据实际情况自行修改。 | 318 | 在test\_aclnn\_\$\{op\_name\}.cpp同级目录下创建run.sh文件,以`AddExample`算子为例,示例如下,请根据实际情况自行修改。 |
| 298 | - | 319 | + |
| 299 | ```bash | 320 | ```bash |
| 300 | if [ -n "$ASCEND_INSTALL_PATH" ]; then # 实际CANN包安装路径 | 321 | if [ -n "$ASCEND_INSTALL_PATH" ]; then # 实际CANN包安装路径 |
| 301 | _ASCEND_INSTALL_PATH=$ASCEND_INSTALL_PATH | 322 | _ASCEND_INSTALL_PATH=$ASCEND_INSTALL_PATH |
| @@ -304,7 +325,7 @@ int main() | |||
| 304 | else | 325 | else |
| 305 | _ASCEND_INSTALL_PATH="/usr/local/Ascend/cann" | 326 | _ASCEND_INSTALL_PATH="/usr/local/Ascend/cann" |
| 306 | fi | 327 | fi |
| 307 | - | 328 | + |
| 308 | source ${_ASCEND_INSTALL_PATH}/bin/setenv.bash | 329 | source ${_ASCEND_INSTALL_PATH}/bin/setenv.bash |
| 309 | 330 | ||
| 310 | rm -rf build | 331 | rm -rf build |
| @@ -315,86 +336,83 @@ int main() | |||
| 315 | cd bin | 336 | cd bin |
| 316 | ./test_aclnn_add_example # 替换为实际算子可执行文件名 | 337 | ./test_aclnn_add_example # 替换为实际算子可执行文件名 |
| 317 | ``` | 338 | ``` |
| 318 | - | 339 | + |
| 319 | 4. 运行run.sh文件。 | 340 | 4. 运行run.sh文件。 |
| 320 | - 在run.sh文件所在路径执行如下命令: | 341 | + 在run.sh文件所在路径执行如下命令: |
| 321 | 342 | ||
| 322 | ```bash | 343 | ```bash |
| 323 | bash run.sh | 344 | bash run.sh |
| 324 | ``` | 345 | ``` |
| 325 | - | 346 | + |
| 326 | 默认在当前执行路径 `/build/bin`下生成可执行文件test\_aclnn\_add\_example,运行结果如下: | 347 | 默认在当前执行路径 `/build/bin`下生成可执行文件test\_aclnn\_add\_example,运行结果如下: |
| 327 | 348 | ||
| 328 | - ```bash | 349 | + ``` |
| 329 | mean result[2046] is 2.000000 | 350 | mean result[2046] is 2.000000 |
| 330 | mean result[2047] is 2.000000 | 351 | mean result[2047] is 2.000000 |
| 331 | ``` | 352 | ``` |
| 332 | 353 | ||
| 333 | -### 图模式调用 | 354 | +### GE图模式 |
| 334 | 355 | ||
| 335 | #### 调用流程 | 356 | #### 调用流程 |
| 336 | 357 | ||
| 337 | -该方式采用算子IR(Intermediate Representation)构图方式调用算子,调用流程如下: | 358 | +该方式基于算子GE IR(Intermediate Representation)定义,以构图方式调用算子,调用流程如下: |
| 338 | 359 | ||
| 339 |  | 360 |  |
| 340 | 361 | ||
| 341 | -调用示例以`AddExample`算子为例,代码示例如下,仅供参考,全量代码参见[test_geir_add_example.cpp](../../../examples/add_example/examples/test_geir_add_example.cpp)。调用前,请按照环境安装的提示信息设置环境变量。 | 362 | +#### 编译运行 |
| 342 | 363 | ||
| 343 | -> 说明:如需调用项目已实现算子,可访问目标算子`examples`目录下test\_geir\_\$\{op\_name\}.cpp,$\{op\_name\}表示算子名。 | 364 | +> 注意:操作过程中,如遇到日志提示设置环境变量,请按提示操作。 |
| 344 | 365 | ||
| 345 | -```CPP | 366 | +1. 创建调用脚本。 |
| 346 | -int main() { | ||
| 347 | - // 1. 创建图对象 | ||
| 348 | - Graph graph(graphName); | ||
| 349 | 367 | ||
| 350 | - // 2. 图全局编译选项初始化 | 368 | + 在目标算子`examples`目录下,新建调用脚本test\_geir\_\$\{op\_name\}.cpp,\$\{op\_name\}表示目标算子名。以`AddExample`算子为例,调用脚本如下,仅供参考,全量代码参见[test_geir_add_example.cpp](../../../examples/add_example/examples/test_geir_add_example.cpp)。 |
| 351 | - Status ret = ge::GEInitialize(globalOptions); | ||
| 352 | 369 | ||
| 353 | - // 3. 创建AddExample算子实例 | 370 | + ```CPP |
| 354 | - auto add1 = op::AddExample("add1"); | 371 | + int main() { |
| 372 | + // 1. 创建图对象 | ||
| 373 | + Graph graph(graphName); | ||
| 374 | + | ||
| 375 | + // 2. 图全局编译选项初始化 | ||
| 376 | + Status ret = ge::GEInitialize(globalOptions); | ||
| 377 | + | ||
| 378 | + // 3. 创建AddExample算子实例 | ||
| 379 | + auto add1 = op::AddExample("add1"); | ||
| 380 | + | ||
| 381 | + // 4. 定义图输入输出向量 | ||
| 382 | + std::vector<Operator> inputs{}; | ||
| 383 | + std::vector<Operator> outputs{}; | ||
| 384 | + | ||
| 385 | + // 5. 准备输入数据 | ||
| 386 | + std::vector<int64_t> xShape = {32,4,4,4}; | ||
| 387 | + // 宏展开方式处理变量赋值 | ||
| 388 | + ADD_INPUT(1, x1, inDtype, xShape); | ||
| 389 | + ADD_INPUT(2, x2, inDtype, xShape); | ||
| 390 | + ADD_OUTPUT(1, y, inDtype, xShape); | ||
| 391 | + | ||
| 392 | + outputs.push_back(add1); | ||
| 393 | + | ||
| 394 | + // 6. 设置图对象的输入算子和输出算子 | ||
| 395 | + graph.SetInputs(inputs).SetOutputs(outputs); | ||
| 396 | + | ||
| 397 | + // 7. 创建session对象 | ||
| 398 | + ge::Session* session = new Session(buildOptions); | ||
| 399 | + | ||
| 400 | + // 8. session添加图 | ||
| 401 | + ret = session->AddGraph(graphId, graph, graphOptions); | ||
| 402 | + | ||
| 403 | + // 9. 运行图 | ||
| 404 | + ret = session->RunGraph(graphId, input, output); | ||
| 405 | + | ||
| 406 | + // 10. 释放资源 | ||
| 407 | + GEFinalize(); | ||
| 408 | + | ||
| 409 | + return 0; | ||
| 410 | + } | ||
| 411 | + ``` | ||
| 355 | 412 | ||
| 356 | - // 4. 定义图输入输出向量 | 413 | +2. 创建CMakeLists.txt文件。 |
| 357 | - std::vector<Operator> inputs{}; | ||
| 358 | - std::vector<Operator> outputs{}; | ||
| 359 | 414 | ||
| 360 | - // 5. 准备输入数据 | 415 | + 在test\_geir\_\$\{op\_name\}.cpp同级目录下创建CMakeLists.txt文件,以`AddExample`算子为例,示例如下,请根据实际情况自行修改。 |
| 361 | - std::vector<int64_t> xShape = {32,4,4,4}; | ||
| 362 | - // 宏展开方式处理变量赋值 | ||
| 363 | - ADD_INPUT(1, x1, inDtype, xShape); | ||
| 364 | - ADD_INPUT(2, x2, inDtype, xShape); | ||
| 365 | - ADD_OUTPUT(1, y, inDtype, xShape); | ||
| 366 | - | ||
| 367 | - outputs.push_back(add1); | ||
| 368 | - | ||
| 369 | - // 6. 设置图对象的输入算子和输出算子 | ||
| 370 | - graph.SetInputs(inputs).SetOutputs(outputs); | ||
| 371 | - | ||
| 372 | - // 7. 创建session对象 | ||
| 373 | - ge::Session* session = new Session(buildOptions); | ||
| 374 | - | ||
| 375 | - // 8. session添加图 | ||
| 376 | - ret = session->AddGraph(graphId, graph, graphOptions); | ||
| 377 | - | ||
| 378 | - // 9. 运行图 | ||
| 379 | - ret = session->RunGraph(graphId, input, output); | ||
| 380 | - | ||
| 381 | - // 10. 释放资源 | ||
| 382 | - GEFinalize(); | ||
| 383 | - | ||
| 384 | - return 0; | ||
| 385 | -} | ||
| 386 | -``` | ||
| 387 | - | ||
| 388 | -#### 编译与运行 | ||
| 389 | - | ||
| 390 | ->说明:对于本项目内已实现的算子(非自定义算子),可通过根目录下build.sh直接运行算子,操作请参考[调用算子样例](#调用算子样例)。 | ||
| 391 | - | ||
| 392 | -1. 前提条件。 | ||
| 393 | - 请参考本项目[源码编译](./quick_op_invocation.md#源码编译)完成目标算子的编译部署。 | ||
| 394 | - | ||
| 395 | -2. 创建CMakelist文件。 | ||
| 396 | - | ||
| 397 | - 在test\_geir\_\$\{op\_name\}.cpp同级目录下创建CMakelist文件,以`AddExample`算子为例,示例如下,请根据实际情况自行修改。 | ||
| 398 | 416 | ||
| 399 | ```bash | 417 | ```bash |
| 400 | cmake_minimum_required(VERSION 3.14) | 418 | cmake_minimum_required(VERSION 3.14) |
| @@ -467,13 +485,13 @@ int main() { | |||
| 467 | 485 | ||
| 468 | 4. 运行run.sh脚本。 | 486 | 4. 运行run.sh脚本。 |
| 469 | 在run.sh文件所在路径执行如下命令: | 487 | 在run.sh文件所在路径执行如下命令: |
| 470 | - | 488 | + |
| 471 | ```bash | 489 | ```bash |
| 472 | bash run.sh | 490 | bash run.sh |
| 473 | ``` | 491 | ``` |
| 474 | - | 492 | + |
| 475 | 默认在当前执行路径 `/build/bin`下生成可执行文件test\_geir\_add\_example,运行结果如下: | 493 | 默认在当前执行路径 `/build/bin`下生成可执行文件test\_geir\_add\_example,运行结果如下: |
| 476 | - | 494 | + |
| 477 | - ```bash | 495 | + ``` |
| 478 | INFO - [XIR]: Finalize ir graph session success | 496 | INFO - [XIR]: Finalize ir graph session success |
| 479 | ``` | 497 | ``` |