已合并
update readme #702
liuyufan创建于 1月12日
update readme #702
已合并
共 5 个文件变更+179-97
| @@ -1,17 +1,20 @@ | |||
| 1 | -# 算子开发快速入门:基于ops-nn仓 | 1 | +# 快速入门:基于ops-nn仓 |
| 2 | -算子开发贡献流程如下: | 2 | + |
| 3 | +本指南旨在帮助您快速上手CANN和`ops-nn`算子仓的使用,最简化地完成环境安装、编译部署及算子运行。算子开发和贡献流程如下图,我们欢迎并鼓励您在社区贡献算子,共同丰富项目生态。 | ||
| 4 | + | ||
| 3 |  | 5 |  |
| 4 | 6 | ||
| 5 | -本指南旨在帮助你快速上手基于CANN和`ops-nn`算子仓的使用,最简化地完成环境安装、编译部署及算子运行。 | 7 | + |
| 8 | +这里将以**AddExample**算子作为实践对象,源文件位于`ops-nn/examples/add_example`目录,请参考下述步骤快速体验起来吧! | ||
| 6 | 9 | ||
| 7 | ## 目录导读 | 10 | ## 目录导读 |
| 8 | -1. **[环境安装](#一环境安装)**:通过Docker快速搭建算子开发环境。 | 11 | +1. **[环境安装](#一环境安装)**:搭建算子开发和运行环境。 |
| 9 | -2. **[编译部署](#二编译部署)**:编译自定义算子包并进行安装,快速调用算子样例验证。 | 12 | +2. **[编译部署](#二编译部署)**:编译自定义算子包并部署安装,实现快速调用算子。 |
| 10 | 3. **[算子开发](#三算子开发)**:通过修改现有算子Kernel,体验开发、编译、验证的完整闭环。 | 13 | 3. **[算子开发](#三算子开发)**:通过修改现有算子Kernel,体验开发、编译、验证的完整闭环。 |
| 11 | -4. **[算子调试能力](#四算子调试能力)**:掌握算子打印和性能采集方法。 | 14 | +4. **[算子调试](#四算子调试)**:掌握算子打印和性能采集方法。 |
| 12 | -5. **[算子验证](#五算子验证)**:学习如何修改样例,以验证算子在不同输入下的功能正确性。 | 15 | +5. **[算子验证](#五算子验证)**:学习如何修改算子example样例,以验证算子在不同输入下的功能正确性。 |
| 13 | 16 | ||
| 14 | -完成以上步骤,你将对算子开发的全流程有一个基础实践认知。 | 17 | +完成以上步骤,您将对算子开发的全流程有一个基础的实践认知。 |
| 15 | 18 | ||
| 16 | ## 一、环境安装 | 19 | ## 一、环境安装 |
| 17 | ### 1. 有环境场景:Docker安装 | 20 | ### 1. 有环境场景:Docker安装 |
| @@ -20,6 +23,7 @@ Docker安装环境以Atlas A2产品(910B)为例。 | |||
| 20 | **前提条件**: | 23 | **前提条件**: |
| 21 | * **Docker环境**:宿主机已安装Docker引擎(版本1.11.2及以上)。 | 24 | * **Docker环境**:宿主机已安装Docker引擎(版本1.11.2及以上)。 |
| 22 | * **驱动与固件**:宿主机已安装昇腾NPU的[驱动与固件](https://www.hiascend.com/hardware/firmware-drivers/community?product=1&model=30&cann=8.0.RC3.alpha002&driver=1.0.26.alpha)Ascend HDK 24.1.0版本以上。安装指导详见《[CANN 软件安装指南](https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/850alpha002/softwareinst/instg/instg_0005.html?Mode=PmIns&OS=openEuler&Software=cannToolKit)》。 | 25 | * **驱动与固件**:宿主机已安装昇腾NPU的[驱动与固件](https://www.hiascend.com/hardware/firmware-drivers/community?product=1&model=30&cann=8.0.RC3.alpha002&driver=1.0.26.alpha)Ascend HDK 24.1.0版本以上。安装指导详见《[CANN 软件安装指南](https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/850alpha002/softwareinst/instg/instg_0005.html?Mode=PmIns&OS=openEuler&Software=cannToolKit)》。 |
| 26 | + | ||
| 23 | > **注意**:使用`npu-smi info`查看对应的驱动与固件版本。 | 27 | > **注意**:使用`npu-smi info`查看对应的驱动与固件版本。 |
| 24 | 28 | ||
| 25 | #### 下载镜像 | 29 | #### 下载镜像 |
| @@ -49,45 +53,86 @@ docker run --name cann_container --device /dev/davinci0 --device /dev/davinci_ma | |||
| 49 | | :--- | :--- | :--- | | 53 | | :--- | :--- | :--- | |
| 50 | | `--name cann_container` | 为容器指定名称,便于管理。 | 可自定义。 | | 54 | | `--name cann_container` | 为容器指定名称,便于管理。 | 可自定义。 | |
| 51 | | `--device /dev/davinci0` | 核心:将宿主机的NPU设备卡映射到容器内,可指定映射多张NPU设备卡。 | 必须根据实际情况调整:`davinci0`对应系统中的第0张NPU卡。请先在宿主机执行 `npu-smi info`命令,根据输出显示的设备号(如`NPU 0`, `NPU 1`)来修改此编号。| | 55 | | `--device /dev/davinci0` | 核心:将宿主机的NPU设备卡映射到容器内,可指定映射多张NPU设备卡。 | 必须根据实际情况调整:`davinci0`对应系统中的第0张NPU卡。请先在宿主机执行 `npu-smi info`命令,根据输出显示的设备号(如`NPU 0`, `NPU 1`)来修改此编号。| |
| 52 | -| `-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/` | 关键挂载:将宿主机的NPU驱动库映射到容器内。 | | | 56 | +| `-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/` | 关键挂载:将宿主机的NPU驱动库映射到容器内。 | - | |
| 53 | 57 | ||
| 54 | #### 检查环境 | 58 | #### 检查环境 |
| 55 | 进入容器后,验证环境和驱动是否正常。 | 59 | 进入容器后,验证环境和驱动是否正常。 |
| 56 | 60 | ||
| 57 | -* **检查NPU设备**: | 61 | +- **检查NPU设备** |
| 58 | - ```bash | 62 | + |
| 59 | - # 运行npu-smi,若返回驱动相关信息说明已成功挂载。 | 63 | + 执行如下命令,若返回驱动相关信息说明已成功挂载。 |
| 64 | + ```bash | ||
| 60 | npu-smi info | 65 | npu-smi info |
| 61 | ``` | 66 | ``` |
| 62 | -* **检查CANN安装**: | 67 | +- **检查CANN安装** |
| 68 | + | ||
| 69 | + 执行如下命令查看CANN Toolkit版本信息,是否为8.5.0版本。 | ||
| 63 | ```bash | 70 | ```bash |
| 64 | - # 查看CANN Toolkit版本信息,是否为对应的8.5.0版本 | ||
| 65 | cat /usr/local/Ascend/ascend-toolkit/latest/opp/version.info | 71 | cat /usr/local/Ascend/ascend-toolkit/latest/opp/version.info |
| 66 | ``` | 72 | ``` |
| 67 | 73 | ||
| 68 | 你已经拥有了一个“开箱即用”的算子开发环境。接下来,需要在这个环境里验证从源码到可运行算子的完整工具链。 | 74 | 你已经拥有了一个“开箱即用”的算子开发环境。接下来,需要在这个环境里验证从源码到可运行算子的完整工具链。 |
| 69 | 75 | ||
| 70 | -### 2. 无环境场景:WebIDE开发(建设中) | 76 | +### 2. 无环境场景:WebIDE开发(内测中) |
| 71 | -对于无环境的用户,提供WebIDE开发方式,目前本方式正在建设中。 | 77 | +对于无环境的用户,提供WebIDE开发平台,即“**算子一站式开发平台**”。该平台为您提供在线可直接运行的昇腾环境,环境中已安装必备的软件包,无需手动安装。 |
| 78 | + | ||
| 79 | +> **前提说明:** | ||
| 80 | +> 当前平台功能正在内测中,若您想体验,请先单击[LINK](https://gitcode.com/org/cann/discussions/47)申请云开发平台资源,并获取平台介绍文档。只有成功申请了平台资源,开源项目的首页才会有“**云开发**”按钮,您才可以参考下述步骤体验。 | ||
| 81 | + | ||
| 82 | +1. 进入ops-nn开源项目,单击“`云开发 > WebIDE for Ascend`”进入算子一站式开发平台,根据页面提示启动云开发环境。 | ||
| 83 | + | ||
| 84 | + <img src="docs/zh/figures/cloudIDE.png" alt="云平台" width="700px" height="100px"> | ||
| 85 | + | ||
| 86 | +2. 检查环境是否完备。 | ||
| 87 | + | ||
| 88 | + 打开`云平台终端`窗口,默认在`/mnt/workspace`目录下,执行如下命令验证环境和驱动是否正常。 | ||
| 89 | + | ||
| 90 | + - **检查NPU设备**: | ||
| 91 | + | ||
| 92 | + 执行如下命令,若返回驱动相关信息说明已成功挂载。 | ||
| 93 | + | ||
| 94 | + ```bash | ||
| 95 | + npu-smi info | ||
| 96 | + ``` | ||
| 97 | + | ||
| 98 | + - **检查CANN安装**: | ||
| 99 | + 执行如下命令查看CANN Toolkit版本信息,是否为8.5.0版本。 | ||
| 100 | + | ||
| 101 | + ```bash | ||
| 102 | + cat /home/developer/Ascend/ascend-toolkit/latest/opp/version.info | ||
| 103 | + ``` | ||
| 72 | 104 | ||
| 73 | ## 二、编译部署 | 105 | ## 二、编译部署 |
| 74 | 106 | ||
| 75 | -本阶段的目的是**快速走通标准流程**,验证你的开发环境能否成功地将算子源代码编译、打包、安装并运行。我们以仓库内置的`AddExample`算子作为实践对象。 | 107 | +本阶段目的是**快速体验项目标准流程**,验证环境能否成功进行算子源码编译、打包、安装和运行。 |
| 76 | 108 | ||
| 77 | -### 1. 拉取ops-nn仓库代码 | 109 | +### 1. 获取项目源码 |
| 78 | 110 | ||
| 79 | -在容器内获取算子源代码。 | 111 | +1. 获取项目源码,命令如下: |
| 80 | -```bash | 112 | + |
| 81 | -git clone https://gitcode.com/cann/ops-nn.git | 113 | + ```bash |
| 82 | -cd ops-nn | 114 | + git clone https://gitcode.com/cann/ops-nn.git |
| 83 | -``` | 115 | + ``` |
| 116 | + 若出现“`fatal: destionation path 'ops-nn' already exists and is not an empty directory.`”说明项目源码已存在,如需刷新项目代码可使用`git pull`命令。 | ||
| 117 | + | ||
| 118 | +2. 进入项目根目录,命令如下,请区分Docker和WebIDE场景。 | ||
| 119 | + - Docker场景: | ||
| 120 | + ```bash | ||
| 121 | + cd ops-nn | ||
| 122 | + ``` | ||
| 123 | + - WebIDE场景: | ||
| 124 | + ```bash | ||
| 125 | + cd /mnt/workspace/ops-nn | ||
| 126 | + ``` | ||
| 84 | 127 | ||
| 85 | ### 2. 编译AddExample算子 | 128 | ### 2. 编译AddExample算子 |
| 86 | 129 | ||
| 87 | -以AddExample算子为例,进入项目根目录,编译指定的AddExample算子。 | 130 | +进入项目根目录,编译指定算子,通用编译命令格式:`bash build.sh --pkg --soc=<芯片版本> --ops=<算子名>`。 |
| 131 | + | ||
| 132 | +以AddExample算子为例,编译命令如下: | ||
| 133 | + | ||
| 88 | ```bash | 134 | ```bash |
| 89 | -# 编译命令格式:bash build.sh --pkg --soc=<芯片版本> --ops=<算子名> | 135 | +bash build.sh --pkg --soc=ascend910b --ops=add_example -j16 |
| 90 | -bash build.sh --pkg --soc=ascend910b --ops=add_example | ||
| 91 | ``` | 136 | ``` |
| 92 | 137 | ||
| 93 | 若提示如下信息,说明编译成功。 | 138 | 若提示如下信息,说明编译成功。 |
| @@ -109,60 +154,89 @@ Self-extractable archive "cann-ops-nn-custom-linux.${arch}.run" successfully cre | |||
| 109 | export LD_LIBRARY_PATH=${ASCEND_HOME_PATH}/opp/vendors/custom_nn/op_api/lib:${LD_LIBRARY_PATH} | 154 | export LD_LIBRARY_PATH=${ASCEND_HOME_PATH}/opp/vendors/custom_nn/op_api/lib:${LD_LIBRARY_PATH} |
| 110 | ``` | 155 | ``` |
| 111 | 156 | ||
| 112 | -### 5.快速验证:运行算子样例 | 157 | +### 5. 快速验证:运行算子样例 |
| 113 | 158 | ||
| 114 | -`AddExample`目录下提供了简单的算子样例`add_example/examples/test_aclnn_add_example.cpp`,运行该样例来验证算子功能是否正常。 | 159 | +通用的运行命令格式:`bash build.sh --run_example <算子名> <运行模式> <包模式>`。 |
| 160 | + | ||
| 161 | +以AddExample为例,其提供了简单算子样例`add_example/examples/test_aclnn_add_example.cpp`,运行该样例验证算子功能是否正常。 | ||
| 115 | 162 | ||
| 116 | ```bash | 163 | ```bash |
| 117 | -# 运行命令格式:bash build.sh --run_example <算子名> <运行模式> <包模式> | ||
| 118 | bash build.sh --run_example add_example eager cust --vendor_name=custom | 164 | bash build.sh --run_example add_example eager cust --vendor_name=custom |
| 119 | ``` | 165 | ``` |
| 120 | -> 预期输出:打印算子`AddExample`的加法计算结果,表明算子已成功部署并正确执行。 | 166 | +预期输出:打印算子`AddExample`的加法计算结果,表明算子已成功部署并正确执行。 |
| 121 | -``` | ||
| 122 | -add_example result[0] is: 2.000000 | ||
| 123 | -add_example result[1] is: 2.000000 | ||
| 124 | -add_example result[2] is: 2.000000 | ||
| 125 | -add_example result[3] is: 2.000000 | ||
| 126 | -add_example result[4] is: 2.000000 | ||
| 127 | -add_example result[5] is: 2.000000 | ||
| 128 | -add_example result[6] is: 2.000000 | ||
| 129 | -add_example result[7] is: 2.000000 | ||
| 130 | -``` | ||
| 131 | 167 | ||
| 132 | -成功运行AddExample算子后,我们尝试修改这个算子的核函数代码。 | 168 | +``` |
| 169 | +add_example first input[0] is: 1.000000, second input[0] is: 1.000000, result[0] is: 2.000000 | ||
| 170 | +add_example first input[1] is: 1.000000, second input[1] is: 1.000000, result[1] is: 2.000000 | ||
| 171 | +add_example first input[2] is: 1.000000, second input[2] is: 1.000000, result[2] is: 2.000000 | ||
| 172 | +add_example first input[3] is: 1.000000, second input[3] is: 1.000000, result[3] is: 2.000000 | ||
| 173 | +add_example first input[4] is: 1.000000, second input[4] is: 1.000000, result[4] is: 2.000000 | ||
| 174 | +add_example first input[5] is: 1.000000, second input[5] is: 1.000000, result[5] is: 2.000000 | ||
| 175 | +add_example first input[6] is: 1.000000, second input[6] is: 1.000000, result[6] is: 2.000000 | ||
| 176 | +add_example first input[7] is: 1.000000, second input[7] is: 1.000000, result[7] is: 2.000000 | ||
| 177 | +... | ||
| 178 | +``` | ||
| 133 | 179 | ||
| 134 | ## 三、算子开发 | 180 | ## 三、算子开发 |
| 135 | 181 | ||
| 136 | -### 1. 修改kernel实现 | 182 | +本阶段目的是对已成功运行的AddExample算子尝试**修改核函数代码**。 |
| 137 | -找到AddExample算子的核心kernel实现文件`ops-nn/examples/add_example/op_kernel/add_example.h`,尝试在Init函数中增加打印: | ||
| 138 | 183 | ||
| 139 | -``` | 184 | +### 1. 修改Kernel实现 |
| 140 | -__aicore__ inline void AddExample<T>::Init(GM_ADDR x, GM_ADDR y, GM_ADDR z, const AddExampleTilingData* tilingData) | 185 | +找到AddExample算子的核心kernel实现文件`ops-nn/examples/add_example/op_kernel/add_example.h`,尝试将算子中的Add操作改为Mul操作: |
| 186 | + | ||
| 187 | +```cpp | ||
| 188 | +__aicore__ inline void AddExample<T>::Compute(int32_t progress) | ||
| 141 | { | 189 | { |
| 142 | - // === 在此处添加一行调试打印 === | 190 | + AscendC::LocalTensor<T> xLocal = inputQueueX.DeQue<T>(); |
| 143 | - AscendC::PRINTF("This is AddExample Kernel Init.\n"); | 191 | + AscendC::LocalTensor<T> yLocal = inputQueueY.DeQue<T>(); |
| 144 | - | 192 | + AscendC::LocalTensor<T> zLocal = outputQueueZ.AllocTensor<T>(); |
| 145 | - blockLength_ = (tilingData->totalLength + AscendC::GetBlockNum() - 1) / AscendC::GetBlockNum(); | 193 | + // === 在此处将Add替换为Mul === |
| 146 | - // ... 后续原有代码 ... | 194 | + // AscendC::Add(zLocal, xLocal, yLocal, tileLength_); |
| 195 | + AscendC::Mul(zLocal, xLocal, yLocal, tileLength_); | ||
| 196 | + outputQueueZ.EnQue<T>(zLocal); | ||
| 197 | + inputQueueX.FreeTensor(xLocal); | ||
| 198 | + inputQueueY.FreeTensor(yLocal); | ||
| 147 | } | 199 | } |
| 148 | ``` | 200 | ``` |
| 149 | -保存修改。 | 201 | +### 2. 编译与验证 |
| 150 | - | ||
| 151 | -### 2.重新编译、部署与验证 | ||
| 152 | 202 | ||
| 153 | 重复[编译部署](#二编译部署)章节中的第2至第5步: | 203 | 重复[编译部署](#二编译部署)章节中的第2至第5步: |
| 154 | -1. **重新编译**:回到根目录,`bash build.sh --pkg --soc=ascend910b --ops=add_example`。 | 204 | +1. **重新编译**: |
| 155 | -2. **重新安装**:`./build_out/cann-ops-nn-*linux*.run` | 205 | + 先回到项目根目录,编译命令如下: |
| 156 | -3. **重新验证**:`bash build.sh --run_example add_example eager cust --vendor_name=custom`。 | 206 | + ```bash |
| 157 | -4. **成功标志**:在运行结果中,除了计算结果,你应能看到打印的"This is AddExample Kernel Init."信息。 | 207 | + bash build.sh --pkg --soc=ascend910b --ops=add_example -j16 |
| 208 | + ``` | ||
| 158 | 209 | ||
| 159 | -## 四、算子调试能力 | 210 | +2. **重新安装**: |
| 160 | -以`AddExample`算子为例,在算子中添加打印和采集性能数据。 | 211 | + ```bash |
| 212 | + ./build_out/cann-ops-nn-*linux*.run | ||
| 213 | + ``` | ||
| 214 | + | ||
| 215 | +3. **重新验证**: | ||
| 216 | + ```bash | ||
| 217 | + bash build.sh --run_example add_example eager cust --vendor_name=custom | ||
| 218 | + ``` | ||
| 219 | + | ||
| 220 | +4. **成功标志**:输出结果变成乘法结果。 | ||
| 221 | + ``` | ||
| 222 | + add_example first input[0] is: 1.000000, second input[0] is: 1.000000, result[0] is: 1.000000 | ||
| 223 | + add_example first input[1] is: 1.000000, second input[1] is: 1.000000, result[1] is: 1.000000 | ||
| 224 | + add_example first input[2] is: 1.000000, second input[2] is: 1.000000, result[2] is: 1.000000 | ||
| 225 | + add_example first input[3] is: 1.000000, second input[3] is: 1.000000, result[3] is: 1.000000 | ||
| 226 | + add_example first input[4] is: 1.000000, second input[4] is: 1.000000, result[4] is: 1.000000 | ||
| 227 | + add_example first input[5] is: 1.000000, second input[5] is: 1.000000, result[5] is: 1.000000 | ||
| 228 | + add_example first input[6] is: 1.000000, second input[6] is: 1.000000, result[6] is: 1.000000 | ||
| 229 | + add_example first input[7] is: 1.000000, second input[7] is: 1.000000, result[7] is: 1.000000 | ||
| 230 | + ... | ||
| 231 | + ``` | ||
| 232 | + | ||
| 233 | +## 四、算子调试 | ||
| 234 | +本阶段以AddExample为例,在算子中添加打印并采集算子性能数据,以便后续问题分析定位。 | ||
| 161 | 235 | ||
| 162 | ### 1. 打印 | 236 | ### 1. 打印 |
| 163 | 算子如果出现执行失败、精度异常等问题,添加打印进行问题分析和定位。 | 237 | 算子如果出现执行失败、精度异常等问题,添加打印进行问题分析和定位。 |
| 164 | 238 | ||
| 165 | -请在`examples/add_example/op_kernel/add_example.h`中进行代码修改调试: | 239 | +请在`examples/add_example/op_kernel/add_example.h`中进行代码修改。 |
| 166 | 240 | ||
| 167 | * **printf** | 241 | * **printf** |
| 168 | 242 | ||
| @@ -187,39 +261,38 @@ __aicore__ inline void AddExample<T>::Init(GM_ADDR x, GM_ADDR y, GM_ADDR z, cons | |||
| 187 | ``` | 261 | ``` |
| 188 | ### 2. 性能采集 | 262 | ### 2. 性能采集 |
| 189 | 263 | ||
| 190 | -当算子功能正确后,可通过`msprof`工具采集算子性能数据。 | 264 | +当算子功能验证正确后,可通过`msprof`工具采集算子性能数据。 |
| 191 | 265 | ||
| 192 | -* **生成可执行文件**: | 266 | +- **生成可执行文件** |
| 193 | - ``` | 267 | + |
| 268 | + 调用AddExample算子的example样例,生成可执行文件(test_aclnn_add_example),该文件位于项目`ops-nn/build`目录。 | ||
| 269 | + ```bash | ||
| 194 | bash build.sh --run_example add_example eager cust --vendor_name=custom | 270 | bash build.sh --run_example add_example eager cust --vendor_name=custom |
| 195 | ``` | 271 | ``` |
| 196 | 272 | ||
| 197 | - 调用`AddExample`的example样例,生成算子可执行文件(test_aclnn_add_example)。该文件位于本项目的`ops-nn/build/`目录。 | 273 | +- **采集性能数据** |
| 198 | 274 | ||
| 199 | -* **采集性能数据**: | 275 | + 进入AddExample算子可执行文件目录`ops-nn/build/`,执行如下命令: |
| 200 | - | ||
| 201 | - 进入`AddExample`算子可执行文件目录`ops-nn/build/`,执行如下命令: | ||
| 202 | 276 | ||
| 203 | ```bash | 277 | ```bash |
| 204 | msprof --application="./test_aclnn_add_example" | 278 | msprof --application="./test_aclnn_add_example" |
| 205 | ``` | 279 | ``` |
| 206 | -采集结果在本项目`ops-nn/build/`目录,msprof命令执行完成后,会自动解析并导出性能数据结果文件,详细内容请参见:[msprof](https://www.hiascend.com/document/detail/zh/mindstudio/82RC1/T&ITools/Profiling/atlasprofiling_16_0110.html#ZH-CN_TOPIC_0000002504160251) | 280 | +采集结果在项目`ops-nn/build/`目录,msprof命令执行完后会自动解析并导出性能数据结果文件,详细内容请参见[msprof](https://www.hiascend.com/document/detail/zh/mindstudio/82RC1/T&ITools/Profiling/atlasprofiling_16_0110.html#ZH-CN_TOPIC_0000002504160251)。 |
| 207 | - | ||
| 208 | -掌握了调试手段,你的算子开发能力将更加全面。最后,为了确保算子的通用性,需要学习如何构建不同的测试用例对其进行验证。 | ||
| 209 | 281 | ||
| 210 | ## 五、算子验证 | 282 | ## 五、算子验证 |
| 211 | 283 | ||
| 212 | -通过修改example样例中的输入数据,可以验证算子在多种场景下的功能正确性。 | 284 | +本阶段通过修改AddExample算子example样例中的输入数据,验证该算子在多种场景下的功能正确性。 |
| 213 | 285 | ||
| 214 | ### 1. 修改测试输入 | 286 | ### 1. 修改测试输入 |
| 215 | 找到并编辑`AddExample`的`ops-nn/examples/add_example/examples/test_aclnn_add_example.cpp`,修改输入张量的形状和数值。 | 287 | 找到并编辑`AddExample`的`ops-nn/examples/add_example/examples/test_aclnn_add_example.cpp`,修改输入张量的形状和数值。 |
| 216 | 288 | ||
| 217 | -- **修改输入、输出数据**: | 289 | +**修改输入/输出数据**:修改输入、输出的shape信息,以及初始化数据,构造相应的输入、输出tensor。 |
| 218 | -修改输入、输出的shape信息,以及初始化数据,构造相应的输入、输出tensor。 | 290 | + |
| 219 | ```c++ | 291 | ```c++ |
| 220 | int main() { | 292 | int main() { |
| 221 | // ... 初始化代码 ... | 293 | // ... 初始化代码 ... |
| 222 | 294 | ||
| 295 | + // === ① 修改selfX的输入 === | ||
| 223 | // 修改前:shape = {32, 4, 4, 4}, 数值全为1 | 296 | // 修改前:shape = {32, 4, 4, 4}, 数值全为1 |
| 224 | // 修改后:将输入shape改为 {8, 8, 8, 8},并填充不同的测试数据 | 297 | // 修改后:将输入shape改为 {8, 8, 8, 8},并填充不同的测试数据 |
| 225 | std::vector<int64_t> selfXShape = {8, 8, 8, 8}; | 298 | std::vector<int64_t> selfXShape = {8, 8, 8, 8}; |
| @@ -228,27 +301,30 @@ int main() { | |||
| 228 | for (int i = 0; i < 4096; ++i) { | 301 | for (int i = 0; i < 4096; ++i) { |
| 229 | selfXHostData[i] = static_cast<float>(i % 10); // 填充0-9的循环值 | 302 | selfXHostData[i] = static_cast<float>(i % 10); // 填充0-9的循环值 |
| 230 | } | 303 | } |
| 231 | - // 同理修改selfY的输入... | 304 | + // === ② 参考selfX,同理修改selfY、selfZ的输入 === |
| 232 | 305 | ||
| 233 | // ... 后续执行代码 ... | 306 | // ... 后续执行代码 ... |
| 234 | } | 307 | } |
| 235 | ``` | 308 | ``` |
| 236 | -### 2. 重新编译并运行验证 | 309 | +### 2. 重新编译并验证 |
| 237 | 310 | ||
| 238 | 1. 由于只修改了example测试代码,无需重新编译算子包。 | 311 | 1. 由于只修改了example测试代码,无需重新编译算子包。 |
| 239 | 312 | ||
| 240 | -2. 直接重新运行验证命令即可:`bash build.sh --run_example add_example eager cust --vendor_name=custom` | 313 | +2. 重新执行验证命令: |
| 241 | 314 | ||
| 242 | -3. 观察输出结果是否符合运算的预期。 | 315 | + ```bash |
| 316 | + bash build.sh --run_example add_example eager cust --vendor_name=custom | ||
| 317 | + ``` | ||
| 243 | 318 | ||
| 244 | -## 开发贡献 | 319 | +3. 观察算子输出结果是否符合预期。 |
| 245 | 320 | ||
| 246 | -开发完成后,可以将完成的算子贡献到算子仓,以下为贡献流程:[贡献指南](CONTRIBUTING.md)。 | 321 | +## 六、开发贡献 |
| 247 | 322 | ||
| 248 | -若需深入每个环节,请参考以下详细指南: | 323 | +体验完上述操作,基本完成了一个算子开发,您可以将算子贡献到本项目`experimental`目录,贡献流程请参考[贡献指南](CONTRIBUTING.md)。过程中,任何问题可通过Issue方式咨询。 |
| 249 | 324 | ||
| 250 | -- [环境部署](./docs/zh/context/quick_install.md):更详细的环境搭建说明。 | 325 | +如果您想要**深入了解**上述每个环节,请参考如下指南: |
| 251 | -- [编译部署及算子调用](./docs/zh/invocation/quick_op_invocation.md):深入了解编译参数与调用方式。 | ||
| 252 | -- [算子开发](./docs/zh/develop/aicore_develop_guide.md):学习如何从零创建算子工程,实现Tiling和Kernel。 | ||
| 253 | -- [调试调优](./docs/zh/debug/op_debug_prof.md):掌握更系统的调试技巧与性能优化方法。 | ||
| 254 | 326 | ||
| 327 | +- [环境部署](./docs/zh/context/quick_install.md):提供不同场景环境搭建指导,包括Docker安装、手动安装CANN软件包等。 | ||
| 328 | +- [编译部署及算子调用](./docs/zh/invocation/quick_op_invocation.md):提供不同场景和方式的算子包编译和验证指导,深入了解编译参数与调用方式。 | ||
| 329 | +- [算子开发](./docs/zh/develop/aicore_develop_guide.md):提供算子开发指南,学习从零创建算子工程、实现Tiling和Kernel。 | ||
| 330 | +- [调试调优](./docs/zh/debug/op_debug_prof.md):提供更系统的调试技巧与性能优化方法。 | ||
| @@ -12,19 +12,24 @@ ops-nn是[CANN](https://hiascend.com/software/cann) (Compute Architecture for | |||
| 12 | 12 | ||
| 13 | ## ⚡️快速入门 | 13 | ## ⚡️快速入门 |
| 14 | 14 | ||
| 15 | -若您希望快速体验算子的调用和开发过程,请访问如下文档获取简易教程。 | 15 | +若您希望**从零到一了解并快速体验项目**,请访问如下文档。可以先了解项目算子信息,再尝试算子调用、开发、贡献等操作。 |
| 16 | 16 | ||
| 17 | -- [算子列表](docs/zh/op_list.md):介绍项目提供的全量算子信息,方便快速查询。 | 17 | +1. [算子列表](docs/zh/op_list.md):项目全量算子信息,方便快速查询。 |
| 18 | -- [环境部署](docs/zh/context/quick_install.md):介绍项目基础环境的搭建,包括软件包和第三方依赖的获取和安装。 | 18 | + |
| 19 | -- [算子调用](docs/zh/invocation/quick_op_invocation.md):环境部署后,介绍如何快速调用算子,包括编译执行算子包和UT等。 | 19 | +2. [QuickStart](QUICKSTART.md):端到端快速上手指南,包括搭建环境、编译部署、算子调用/开发/调试调优、贡献等过程。 |
| 20 | -- [算子开发](docs/zh/develop/aicore_develop_guide.md):环境部署后,介绍如何快速开发算子,包括创建算子工程、实现Tiling和Kernel核心交付件等。 | ||
| 21 | 20 | ||
| 22 | ## 📖学习教程 | 21 | ## 📖学习教程 |
| 23 | 22 | ||
| 24 | -若您希望深入体验项目功能并修改算子源码,请访问如下文档获取详细教程。 | 23 | +若您**已完成快速入门**学习,对本项目有了一定认知,并希望**深入了解和体验项目**,请访问如下文档。 |
| 25 | -- [算子调用方式](docs/zh/invocation/op_invocation.md):介绍不同的调用算子方式,方便快速应用于不同的AI业务场景。 | 24 | + |
| 26 | -- [算子调试调优](docs/zh/debug/op_debug_prof.md):介绍常见的算子调试和调优方法,如DumpTensor、msProf等。 | 25 | +这些文档提供了多样化的场景介绍和更全面的操作指导,方便您应用于各种AI业务场景。 |
| 27 | -- [算子基本概念](docs/zh/context/基本概念.md):介绍算子领域相关术语和概念,如非连续Tensor、量化模式等。 | 26 | + |
| 27 | +1. [环境部署](docs/zh/context/quick_install.md):搭建基础环境的指南,提供了多种场景下第三方依赖和软件包安装方法等。 | ||
| 28 | +2. [算子调用](docs/zh/invocation/quick_op_invocation.md):编译部署并调用算子的指南,提供了多种编译算子包以及运行算子的方法(包括执行算子样例和UT)等。 | ||
| 29 | +3. [算子开发](docs/zh/develop/aicore_develop_guide.md):基于本项目工程开发新算子的指南,提供了创建算子工程、实现Tiling和Kernel核心交付件等指导。 | ||
| 30 | +4. [算子调试调优](docs/zh/debug/op_debug_prof.md):提供了常见的算子调试和调优方法,如DumpTensor、msProf、Simulator等。 | ||
| 31 | + | ||
| 32 | +除了上述指南,还提供了其他文档介绍,例如算子调用方式和流程、算子基本概念等,全量文档介绍请访问[docs](docs/README.md)。 | ||
| 28 | 33 | ||
| 29 | ## 🔍目录结构 | 34 | ## 🔍目录结构 |
| 30 | 关键目录如下,详细目录介绍参见[项目目录](./docs/zh/context/dir_structure.md)。 | 35 | 关键目录如下,详细目录介绍参见[项目目录](./docs/zh/context/dir_structure.md)。 |
| @@ -75,7 +75,7 @@ | |||
| 75 | 75 | ||
| 76 | ## 环境验证 | 76 | ## 环境验证 |
| 77 | 77 | ||
| 78 | -安装完CANN包或进入Docker容器后,需验证环境和驱动是否正常。 | 78 | +安装完CANN包后,需验证环境和驱动是否正常。 |
| 79 | 79 | ||
| 80 | - **检查NPU设备**: | 80 | - **检查NPU设备**: |
| 81 | ```bash | 81 | ```bash |
| @@ -34,7 +34,8 @@ int64_t GetShapeSize(const std::vector<int64_t>& shape) | |||
| 34 | return shapeSize; | 34 | return shapeSize; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | -void PrintOutResult(std::vector<int64_t>& shape, void** deviceAddr) | 37 | +void PrintOutResult(std::vector<int64_t>& shape, void** deviceAddr, |
| 38 | + const std::vector<float>& selfXHostData, const std::vector<float>& selfYHostData) | ||
| 38 | { | 39 | { |
| 39 | auto size = GetShapeSize(shape); | 40 | auto size = GetShapeSize(shape); |
| 40 | std::vector<float> resultData(size, 0); | 41 | std::vector<float> resultData(size, 0); |
| @@ -43,7 +44,7 @@ void PrintOutResult(std::vector<int64_t>& shape, void** deviceAddr) | |||
| 43 | ACL_MEMCPY_DEVICE_TO_HOST); | 44 | ACL_MEMCPY_DEVICE_TO_HOST); |
| 44 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return); | 45 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return); |
| 45 | for (int64_t i = 0; i < size; i++) { | 46 | for (int64_t i = 0; i < size; i++) { |
| 46 | - LOG_PRINT("mean result[%ld] is: %f\n", i, resultData[i]); | 47 | + LOG_PRINT("add_example first input[%ld] is: %f, second input[%ld] is: %f, result[%ld] is: %f\n", i, selfXHostData[i], i, selfYHostData[i], i, resultData[i]); |
| 47 | } | 48 | } |
| 48 | } | 49 | } |
| 49 | 50 | ||
| @@ -139,7 +140,7 @@ int main() | |||
| 139 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | 140 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); |
| 140 | 141 | ||
| 141 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | 142 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 |
| 142 | - PrintOutResult(outShape, &outDeviceAddr); | 143 | + PrintOutResult(outShape, &outDeviceAddr, selfXHostData, selfYHostData); |
| 143 | 144 | ||
| 144 | // 7. 释放aclTensor,需要根据具体API的接口定义修改 | 145 | // 7. 释放aclTensor,需要根据具体API的接口定义修改 |
| 145 | aclDestroyTensor(selfX); | 146 | aclDestroyTensor(selfX); |