已合并
【feat】: add acl external api skills #4308
tang-haojie创建于 18 天前
【feat】: add acl external api skills #4308
已合并
共 2 个文件变更+380-0
| @@ -0,0 +1,375 @@ | |||
| 1 | +--- | ||
| 2 | +name: acl-mdl-api-creator | ||
| 3 | +description: Use when adding new public APIs to inc/external/acl/ headers (acl_mdl.h, acl_base_mdl.h, acl_op.h, acl_op_compiler.h), or adding new types (enums/macros/structs) to those headers. Covers three-layer architecture for acl_mdl.h, naming conventions, Doxygen comments, stub generation, UT patterns, and binary compatibility rules. | ||
| 4 | +--- | ||
| 5 | + | ||
| 6 | +# ACL Public API Creator | ||
| 7 | + | ||
| 8 | +## Overview | ||
| 9 | + | ||
| 10 | +GE 在 `inc/external/acl/` 下对外暴露 4 个头文件: | ||
| 11 | + | ||
| 12 | +| 头文件 | 内容 | 新增频率 | | ||
| 13 | +|--------|------|----------| | ||
| 14 | +| `acl_mdl.h` | 模型加载/执行/查询/Dataset/AIPP/Config 等 | 高(主要新增入口) | | ||
| 15 | +| `acl_base_mdl.h` | TensorDesc 等基础类型接口 | 低 | | ||
| 16 | +| `acl_op.h` | 算子相关接口 | 低 | | ||
| 17 | +| `acl_op_compiler.h` | 算子编译相关接口 | 低 | | ||
| 18 | + | ||
| 19 | +- **acl_mdl.h 新增接口**:需要完整走三层架构(头文件 → 路由层 → Impl 层)+ 测试 + 兼容性看护 | ||
| 20 | +- **其他头文件新增接口**:主要关注兼容性规范(命名、编码规范、兼容性看护),实现链路参考各自模块现有代码 | ||
| 21 | + | ||
| 22 | +## When to Use | ||
| 23 | + | ||
| 24 | +- 新增 ACL 对外接口、对外 API、acl_mdl.h 接口、acl_op.h 接口 | ||
| 25 | +- 新增对外枚举、宏、结构体 | ||
| 26 | +- 为已有接口添加 `V2`/`V3` 版本 | ||
| 27 | +- 修改 `inc/external/acl/` 下头文件(仅允许兼容性追加,不允许删除或改变已有定义) | ||
| 28 | + | ||
| 29 | +## Architecture | ||
| 30 | + | ||
| 31 | +``` | ||
| 32 | +acl_mdl.h (对外声明,C 风格) | ||
| 33 | + ↓ | ||
| 34 | +acl_model.cpp (路由层 → libacl_mdl.so,仅 1 个源文件) | ||
| 35 | + ├── model_om2.cpp (OM2 Impl → libacl_mdl_impl_om2.so) | ||
| 36 | + └── model.cpp (Legacy/OM1 Impl → libacl_mdl_impl.so) | ||
| 37 | + └── 反向依赖 libacl_mdl_impl_om2.so(复用共用代码) | ||
| 38 | +``` | ||
| 39 | + | ||
| 40 | +**编写代码前,先读取以下文件学习现有模式**: | ||
| 41 | +- 路由层:`api/acl/acl_model/model/acl_model.cpp` | ||
| 42 | +- OM2 Impl 声明:`api/acl/acl_model/model/acl_model_impl_om2.h` | ||
| 43 | +- OM2 Impl 实现:`api/acl/acl_model/model/model_om2.cpp` | ||
| 44 | +- Legacy Impl 声明:`api/acl/acl_model/model/acl_model_impl.h` | ||
| 45 | +- Legacy Impl 实现:`api/acl/acl_model/model/model.cpp` | ||
| 46 | +- UT 测试:`tests/test_c/ut/testcase/acl/acl_mdl_test.cc` | ||
| 47 | +- 兼容性看护:`tests/acl_ut/ut/acl/testcase/compatibility/` | ||
| 48 | +- 内部结构体:`api/acl/acl_model/model/model_desc_internal.h` | ||
| 49 | +- 共用函数:`api/acl/acl_model/model/model_common.h` | ||
| 50 | + | ||
| 51 | +### 头文件结构 (acl_mdl.h, 1725 行) | ||
| 52 | + | ||
| 53 | +| 区域 | 行号 | 内容 | | ||
| 54 | +|------|------|------| | ||
| 55 | +| Include Guard | 11-12 | `INC_EXTERNAL_ACL_ACL_MODEL_H_` | | ||
| 56 | +| Include 依赖 | 14-18 | `<stddef.h>`, `<stdint.h>`, `acl_base.h`, `acl_rt.h` | | ||
| 57 | +| extern "C" | 20-22 | C 兼容声明 | | ||
| 58 | +| 宏定义 | 24-49 | `ACL_MAX_DIM_CNT`(128), 加载类型(1-6), 流标志等 | | ||
| 59 | +| 前向声明 | 51-58 | `aclmdlDataset`, `aclmdlDesc`, `aclmdlAIPP`, `aclmdlConfigHandle` 等 | | ||
| 60 | +| 枚举定义 | 60-137 | `aclmdlConfigAttr`, `aclmdlAttr`, `aclmdlExecConfigAttr` 等 | | ||
| 61 | +| 结构体定义 | 139-233 | `aclmdlIODims`, `aclAippDims`, `aclmdlBatch`, `aclmdlHW`, `aclAippInfo` 等 | | ||
| 62 | +| 函数声明 | 235-1719 | 所有对外 API(带 Doxygen 注释) | | ||
| 63 | + | ||
| 64 | +**新增代码插入位置**: | ||
| 65 | +- 新增前向声明 → 追加到前向声明区域末尾 | ||
| 66 | +- 新增枚举值 → 追加到对应枚举定义末尾(不要插入中间,避免改变已有取值) | ||
| 67 | +- 新增枚举类型 → 追加到枚举定义区域末尾 | ||
| 68 | +- 新增结构体 → 追加到结构体定义区域末尾 | ||
| 69 | +- 新增函数声明 → 追加到函数声明区域末尾,按功能分组 | ||
| 70 | + | ||
| 71 | +## 开发流程 | ||
| 72 | + | ||
| 73 | +新增 ACL 对外接口分三个阶段:**设计分析 → 代码实现 → 验证**。 | ||
| 74 | + | ||
| 75 | +### 阶段一:设计分析(编码前必须完成) | ||
| 76 | + | ||
| 77 | +**1. 接口必要性** | ||
| 78 | +- 是否已有类似接口可以满足需求?(优先复用,避免接口膨胀) | ||
| 79 | +- 如果是修改已有接口的行为,必须新增 V2/V3 版本,不能改原接口 | ||
| 80 | + | ||
| 81 | +**2. 接口签名设计** | ||
| 82 | + | ||
| 83 | +| 决策项 | 确认内容 | | ||
| 84 | +|--------|----------| | ||
| 85 | +| 函数名 | 符合 `aclmdl` + 操作动词 + 对象 规则?无形容词? | | ||
| 86 | +| 返回类型 | 操作型→`aclError`,创建型→指针,查询型→`size_t`? | | ||
| 87 | +| 异步版本 | 是否需要同步接口 + `Async` 后缀的异步版本? | | ||
| 88 | +| 参数列表 | 每个参数的 `[IN]`/`[OUT]`/`[IN][OUT]` 方向明确? | | ||
| 89 | +| `const` 修饰 | 指针入参是否加 `const`?未来是否需要修改该参数(如动态 shape 场景)? | | ||
| 90 | +| 返回码 | 是否需要新增 `ACL_ERROR_*` 返回码?与已有返回码是否冲突? | | ||
| 91 | +| 新增类型 | 是否需要新增前向声明/枚举/结构体?放在头文件的哪个区域? | | ||
| 92 | +| 结构体扩展 | 新增结构体是否需要预留指针参数扩展字段? | | ||
| 93 | + | ||
| 94 | +**3. 路由模式选择** — 按下方"路由模式决策"确定 | ||
| 95 | + | ||
| 96 | +**4. 兼容性影响评估** | ||
| 97 | + | ||
| 98 | +| 检查项 | 确认 | | ||
| 99 | +|--------|------| | ||
| 100 | +| 是否修改了已有对外接口? | 不允许,只能新增 | | ||
| 101 | +| 是否修改了已有枚举值? | 不允许,只能追加 | | ||
| 102 | +| 是否修改了已有结构体字段? | 不允许,只能追加且不影响已有偏移 | | ||
| 103 | +| 新增枚举取值是否与已有冲突? | 不允许冲突 | | ||
| 104 | +| 新增返回码是否与已有冲突? | 不允许冲突 | | ||
| 105 | + | ||
| 106 | +**5. 实现方案确认** | ||
| 107 | +- Impl 层需要调用哪些内部 API? | ||
| 108 | +- 是否可以复用 `model_common.h` 中的共用函数? | ||
| 109 | +- 是否需要修改 `model_desc_internal.h` 中的内部结构体? | ||
| 110 | + | ||
| 111 | +### 阶段二:代码实现 | ||
| 112 | + | ||
| 113 | +按 Checklist 逐文件修改,编写时先读取对应现有文件学习写法。 | ||
| 114 | + | ||
| 115 | +### 阶段三:验证 | ||
| 116 | + | ||
| 117 | +| # | 验证项 | 方式 | | ||
| 118 | +|---|--------|------| | ||
| 119 | +| 1 | 编译通过 | `bash build.sh --ge_executor` | | ||
| 120 | +| 2 | UT 通过 | 使用 `ge-dt-runner` skill 编译运行 acl_utest | | ||
| 121 | +| 3 | 兼容性看护通过 | 确认 compatibility 测试全部通过 | | ||
| 122 | +| 4 | Stub 自动生成 | 构建日志中确认 stub 生成无报错 | | ||
| 123 | + | ||
| 124 | +--- | ||
| 125 | + | ||
| 126 | +## Checklist | ||
| 127 | + | ||
| 128 | +| # | 文件 | 修改内容 | | ||
| 129 | +|---|------|----------| | ||
| 130 | +| 1 | `inc/external/acl/acl_mdl.h` | 函数声明 + Doxygen 注释 | | ||
| 131 | +| 2 | `api/acl/acl_model/model/acl_model_impl_om2.h` | `ImplOm2` 声明 | | ||
| 132 | +| 3 | `api/acl/acl_model/model/model_om2.cpp` | OM2 实现 | | ||
| 133 | +| 4 | `api/acl/acl_model/model/acl_model.cpp` | 路由函数(选择路由模式) | | ||
| 134 | +| 5 | `api/acl/acl_model/model/acl_model_impl.h` | (如需 Legacy)`Impl` 声明 | | ||
| 135 | +| 6 | `api/acl/acl_model/model/model.cpp` | (如需 Legacy)实现 | | ||
| 136 | +| 7 | `tests/test_c/ut/testcase/acl/acl_mdl_test.cc` | UT 测试用例 | | ||
| 137 | +| 8 | `tests/acl_ut/ut/acl/testcase/compatibility/enum_check.cpp` | (如有新增枚举)追加枚举值看护 | | ||
| 138 | +| 9 | `tests/acl_ut/ut/acl/testcase/compatibility/const_check.cpp` | (如有新增宏/常量)追加宏值看护 | | ||
| 139 | +| 10 | `tests/acl_ut/ut/acl/testcase/compatibility/struct_check.cpp` | (如有新增/修改结构体)追加偏移量+大小看护 | | ||
| 140 | + | ||
| 141 | +**自动处理(无需手动修改):** | ||
| 142 | +- Stub 生成:两个脚本分工生成 stub,均位于 `api/acl/stub/`: | ||
| 143 | + - `gen_stubapi.py`:从对外头文件(`acl_mdl.h` 等)解析**对外接口**(无后缀),生成同名 stub,返回 `ACL_ERROR_COMPILING_STUB_MODE` | ||
| 144 | + - `gen_stubapi_acl_mdl_impl.py`:从 `acl_model_impl.h`/`acl_model_impl_om2.h` 解析,为 `*Impl`(Legacy)和 `*ImplOm2`(OM2)函数生成 stub,函数名自动追加 `Impl` 后缀,返回 `ACL_ERROR_API_NOT_SUPPORT` | ||
| 145 | +- 符号导出:使用 `ACL_FUNC_VISIBILITY` 宏即自动导出。该宏定义在外部 CANN runtime SDK 头文件 `acl/acl_base_rt.h` 中,不在 GE 仓库内,构建时通过 `${TOP_DIR}/runtime/include/external` 引入 | ||
| 146 | + | ||
| 147 | +## 路由模式决策 | ||
| 148 | + | ||
| 149 | +``` | ||
| 150 | +接口参数中是否包含 modelId / modelPath / modelData / bundleId / ConfigHandle / Desc? | ||
| 151 | + ├── 否 → 模式 A:纯 OM2 直连(直接调用 ImplOm2) | ||
| 152 | + └── 是 → 是否需要 Legacy(OM1) 支持? | ||
| 153 | + ├── 否 → 模式 A:纯 OM2 直连 | ||
| 154 | + └── 是 → 按参数类型选择路由判断函数: | ||
| 155 | + modelId → ById | modelPath → ByPath | modelData → ByData | ||
| 156 | + Desc → ByDesc | ConfigHandle → ByConfig | bundleId → BundleById | ||
| 157 | +``` | ||
| 158 | + | ||
| 159 | +### 模式 A:纯 OM2 直连 | ||
| 160 | + | ||
| 161 | +路由层直接调用 `ImplOm2`,不做 OM1/OM2 判断。适用于 Desc/Dataset/AIPP/ConfigHandle 的创建销毁和属性查询,或 OM1 从未支持的全新功能。参考 `acl_model.cpp` 中 `aclmdlGetNumInputs` 等接口的写法。 | ||
| 162 | + | ||
| 163 | +### 模式 B:OM1/OM2 分发 | ||
| 164 | + | ||
| 165 | +通过路由判断函数区分 OM 格式,分发到 `ImplOm2` 或 `Impl`。适用于模型加载、执行、卸载、动态 shape 设置、AIPP 绑定等。参考 `acl_model.cpp` 中 `aclmdlExecute`、`aclmdlLoadFromFile` 等接口的写法。 | ||
| 166 | + | ||
| 167 | +**6 个路由判断函数**(定义在 `acl_model_router.h`): | ||
| 168 | + | ||
| 169 | +| 函数 | 判断依据 | 实现原理 | | ||
| 170 | +|------|----------|----------| | ||
| 171 | +| `AclIsOm2ModelById(modelId, &isOm2)` | `uint32_t modelId` | 查 `AclResourceManagerOm2` | | ||
| 172 | +| `AclIsOm2ModelByPath(modelPath, &isOm2)` | `const char* path` | 读文件头魔数 | | ||
| 173 | +| `AclIsOm2ModelByData(model, size, &isOm2)` | `const void*, size_t` | 读内存头魔数 | | ||
| 174 | +| `AclIsOm2ModelByDesc(desc, &isOm2)` | `aclmdlDesc*` | 通过 `desc->modelId` 查 | | ||
| 175 | +| `AclIsOm2ModelByConfig(handle, &isOm2)` | `aclmdlConfigHandle*` | 从 `handle->loadPath` 或 `handle->mdlAddr` 判断 | | ||
| 176 | +| `AclIsOm2BundleById(bundleId, &isOm2)` | `uint32_t bundleId` | 查 `AclResourceManagerOm2` | | ||
| 177 | + | ||
| 178 | +### 模式 C/D/E:特殊路由 | ||
| 179 | + | ||
| 180 | +- **C(OM2 优先回退 OM1)**:先调 `ImplOm2`,特定错误码时回退 `Impl`。参考 `aclmdlCreateAndGetOpDesc` | ||
| 181 | +- **D(先 OM1 后 OM2)**:两者都需执行。参考 `aclRecoverAllHcclTasks` | ||
| 182 | +- **E(只用 Legacy)**:直接调 `Impl`。参考 `aclTransTensorDescFormat` | ||
| 183 | + | ||
| 184 | +### 何时需要 Legacy Impl | ||
| 185 | + | ||
| 186 | +| 场景 | 是否需要 Legacy | | ||
| 187 | +|------|----------------| | ||
| 188 | +| Desc/Dataset/AIPP/ConfigHandle 的创建销毁和属性查询 | 不需要(纯 OM2) | | ||
| 189 | +| 模型加载/执行/卸载/动态 shape/AIPP 绑定 | 需要(OM1+OM2 分发) | | ||
| 190 | +| 全新功能(OM1 从未支持) | 不需要(纯 OM2) | | ||
| 191 | + | ||
| 192 | +## ACL 编码规范 | ||
| 193 | + | ||
| 194 | +### 命名 | ||
| 195 | + | ||
| 196 | +| # | 规则 | 示例 | | ||
| 197 | +|---|------|------| | ||
| 198 | +| 1 | 驼峰风格。模块名全小写放最前 | `aclmdlLoadFromFile` | | ||
| 199 | +| 2 | 对外:`acl` + 模块类别 + 操作动词 + 对象。内部:大驼峰,无需 `acl` 前缀 | 对外:`aclmdlCreateDesc`;内部:`CreateModelDesc` | | ||
| 200 | +| 3 | 模块名与操作对象重叠时,对象省略 | — | | ||
| 201 | +| 4 | 接口名原则上不允许有形容词 | — | | ||
| 202 | +| 5 | 不暴露实现细节,使用前向声明 | `typedef struct aclmdlDesc aclmdlDesc;` | | ||
| 203 | +| 6 | 对外头文件为 C 风格,不使用 C++ 标识符 | — | | ||
| 204 | +| 7 | 用宏定义常量,避免 `const int` | `#define ACL_MAX_DIM_CNT 8` | | ||
| 205 | +| 8 | 避免 `bool` 类型,用 `uint8_t` 替代 | `uint8_t enable;` | | ||
| 206 | +| 9 | 枚举值全大写 + `ACL_` 前缀 | `ACL_MDL_LOAD_FROM_FILE` | | ||
| 207 | +| 10 | 整型优先 `<cstdint>`;长度用 `size_t` | `uint32_t modelId` | | ||
| 208 | +| 11 | 异步接口名末尾加 `Async`,`stream` 参数放最后 | `aclmdlExecuteAsync` | | ||
| 209 | +| 12 | 类成员变量 `_` 后缀,结构体成员小驼峰 | 类:`modelId_`;结构体:`modelId` | | ||
| 210 | + | ||
| 211 | +### Impl 函数命名 | ||
| 212 | + | ||
| 213 | +| 层级 | 命名规则 | 示例 | | ||
| 214 | +|------|----------|------| | ||
| 215 | +| 对外接口 | `aclmdl` + PascalCase | `aclmdlLoadFromFile` | | ||
| 216 | +| OM2 Impl | 对外名 + `ImplOm2` | `aclmdlLoadFromFileImplOm2` | | ||
| 217 | +| Legacy Impl | 对外名 + `Impl` | `aclmdlLoadFromFileImpl` | | ||
| 218 | + | ||
| 219 | +Impl 函数签名与对外接口参数完全一致,仅函数名不同。 | ||
| 220 | + | ||
| 221 | +### 格式 | ||
| 222 | + | ||
| 223 | +- 对外接口必须使用 `ACL_FUNC_VISIBILITY` 标记(该宏定义在外部 CANN runtime SDK 头文件 `acl/acl_base_rt.h` 中,不在 GE 仓库内) | ||
| 224 | +- 对外头文件必须使用 `extern "C"` 包裹,确保 C++ 代码能正确调用 C 语言接口,指示编译器按 C 语言方式编译和链接: | ||
| 225 | + ```c | ||
| 226 | + #ifdef __cplusplus | ||
| 227 | + extern "C" { | ||
| 228 | + #endif | ||
| 229 | + // 所有对外函数声明和类型定义 | ||
| 230 | + #ifdef __cplusplus | ||
| 231 | + } | ||
| 232 | + #endif | ||
| 233 | + ``` | ||
| 234 | + | ||
| 235 | +### 注释 | ||
| 236 | + | ||
| 237 | +- 函数头注释按 Doxygen 格式,必须包含 `@ingroup AscendCL`、`@brief`、`@param`(标注方向)、`@retval`: | ||
| 238 | + ```c | ||
| 239 | + /** | ||
| 240 | + * @ingroup AscendCL | ||
| 241 | + * @brief 简短描述接口功能 | ||
| 242 | + * | ||
| 243 | + * @param modelId [IN] model id | ||
| 244 | + * @param result [OUT] query result | ||
| 245 | + * | ||
| 246 | + * @retval ACL_SUCCESS The function is successfully executed. | ||
| 247 | + * @retval OtherValues Failure | ||
| 248 | + */ | ||
| 249 | + ``` | ||
| 250 | +- 指针入参且函数体不修改时,加 `const` 修饰,注释标 `[IN]` | ||
| 251 | +- 既作入参又作出参时,注释标 `[IN][OUT]` | ||
| 252 | +- 新建接口先读取 `acl_mdl.h` 中相邻接口的注释学习格式 | ||
| 253 | + | ||
| 254 | +### 其他注意事项 | ||
| 255 | + | ||
| 256 | +- 枚举无效值需足够大,或不定义无效值 | ||
| 257 | +- 高频接口中不增加非必要耗时逻辑 | ||
| 258 | +- 接口参数设为 `const` 需从扩展性思考(`aclopExecute` 的 `inputDesc`/`outputDesc` 定义为 `const` 导致动态 shape 场景无法使用,不得不新增 `aclopExecuteV2`) | ||
| 259 | + | ||
| 260 | +## 兼容性规范(强制) | ||
| 261 | + | ||
| 262 | +### 对外接口兼容性 | ||
| 263 | + | ||
| 264 | +| 规则 | 说明 | | ||
| 265 | +|------|------| | ||
| 266 | +| 不允许删除 | 已发布的对外接口永远不能删除 | | ||
| 267 | +| 不允许改名 | 包括大小写 | | ||
| 268 | +| 参数不可修改 | 对象类型不可改变,已有含义不可改变。例外:变更后相同输入必须有相同输出 | | ||
| 269 | +| 返回码不可变 | 原有含义及取值不可改变,新增特性可增加返回码 | | ||
| 270 | +| 存在即合理 | 即使旧接口定义不合理,只要已在现网运行,不允许擅自修改 | | ||
| 271 | + | ||
| 272 | +### 实现和逻辑兼容性 | ||
| 273 | + | ||
| 274 | +- 新增/增强功能不允许丢失原有特性 | ||
| 275 | +- 新增功能默认情况下必须和基础版本完全兼容 | ||
| 276 | +- 修正老代码错误不能造成特性改变 | ||
| 277 | + | ||
| 278 | +### 数据兼容性 | ||
| 279 | + | ||
| 280 | +- 已定义的对外数据对象不能删除,名称不能修改 | ||
| 281 | +- 枚举类型取值不能减少,非枚举类型取值含义不能修改 | ||
| 282 | +- 新增枚举取值不能与已有取值冲突 | ||
| 283 | +- 数据对象需考虑可扩展性,扩展属性不能影响兼容性 | ||
| 284 | + | ||
| 285 | +### 结构体扩展性 | ||
| 286 | + | ||
| 287 | +- 对外结构体原则上需要稳定,不存在后续参数扩展 | ||
| 288 | +- 如果不确定结构体后续是否会扩展,**预留一个指针参数**方便后续扩展 | ||
| 289 | + | ||
| 290 | +### 兼容性看护(必须执行) | ||
| 291 | + | ||
| 292 | +新增或修改对外头文件中的枚举、宏、结构体时,**必须**在 `tests/acl_ut/ut/acl/testcase/compatibility/` 对应文件中追加断言: | ||
| 293 | + | ||
| 294 | +| 新增类型 | 看护文件 | 断言方式 | | ||
| 295 | +|----------|----------|----------| | ||
| 296 | +| 枚举类型/枚举值 | `enum_check.cpp` | `(枚举类型)固定整数值` vs `枚举常量`,测试类 `UTEST_ACL_compatibility_enum_check` | | ||
| 297 | +| 宏/常量 | `const_check.cpp` | `宏名` vs `固定字面量`,字符串宏用 `std::string` 包装,测试类 `UTEST_ACL_compatibility_const_check` | | ||
| 298 | +| 结构体/结构体字段 | `struct_check.cpp` | `OFFSET_OF_MEMBER` 算偏移 + `sizeof` 算总大小,测试类 `UTEST_ACL_compatibility_struct_check` | | ||
| 299 | + | ||
| 300 | +编写时先读取对应看护文件学习现有断言写法。 | ||
| 301 | + | ||
| 302 | +## API 参考 | ||
| 303 | + | ||
| 304 | +### 参数校验宏 | ||
| 305 | + | ||
| 306 | +定义在 `api/acl/common/log_inner.h`: | ||
| 307 | + | ||
| 308 | +| 宏 | 用途 | | ||
| 309 | +|----|------| | ||
| 310 | +| `ACL_REQUIRES_NOT_NULL(ptr)` | 非空校验 | | ||
| 311 | +| `ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(ptr)` | 非空校验 + 报错上报(推荐) | | ||
| 312 | +| `ACL_REQUIRES_NOT_NULL_RET_NULL(ptr)` | 非空校验,失败返回 `nullptr` | | ||
| 313 | +| `ACL_REQUIRES_NOT_NULL_RET_VOID(ptr)` | 非空校验,失败返回 `void` | | ||
| 314 | +| `ACL_REQUIRES_OK(expr)` | 表达式成功校验(返回 aclError) | | ||
| 315 | +| `ACL_REQUIRES_OK_WITH_INNER_MESSAGE(expr, ...)` | 同上,附加内部错误日志 | | ||
| 316 | +| `ACL_REQUIRES_TRUE(expr, errCode, errDesc)` | 条件校验,失败返回指定错误码 | | ||
| 317 | +| `ACL_REQUIRES_CALL_GE_OK(expr, ...)` | GE `Status` 成功校验 | | ||
| 318 | +| `ACL_REQUIRES_CALL_RTS_OK(expr, fn)` | Runtime 调用成功校验 | | ||
| 319 | +| `ACL_REQUIRES_NON_NEGATIVE(val)` | 非负校验 | | ||
| 320 | +| `ACL_REQUIRES_POSITIVE(val)` | 正值校验 | | ||
| 321 | +| `ACL_REQUIRES_EQ(a, b)` | 相等校验 | | ||
| 322 | +| `ACL_REQUIRES_LE(a, b)` | 小于等于校验 | | ||
| 323 | +| `ACL_CHECK_MALLOC_RESULT(val)` | malloc 结果校验,失败返回 `ACL_ERROR_BAD_ALLOC` | | ||
| 324 | +| `ACL_CHECK_RANGE_INT(val, min, max)` | int 范围校验 | | ||
| 325 | + | ||
| 326 | +### 错误码 | ||
| 327 | + | ||
| 328 | +| 宏/值 | 用途 | | ||
| 329 | +|-------|------| | ||
| 330 | +| `ACL_GET_ERRCODE_GE(ret)` | GE 错误码转换 | | ||
| 331 | +| `ACL_GET_ERRCODE_RTS(ret)` | Runtime 错误码转换 | | ||
| 332 | +| `ACL_ERROR_INVALID_PARAM` | 参数无效 | | ||
| 333 | +| `ACL_ERROR_FAILURE` | 通用失败 | | ||
| 334 | +| `ACL_ERROR_STORAGE_OVER_LIMIT` | 存储超限 | | ||
| 335 | + | ||
| 336 | +### 日志宏 | ||
| 337 | + | ||
| 338 | +| 宏 | 级别 | | ||
| 339 | +|----|------| | ||
| 340 | +| `ACL_LOG_ERROR("[Tag][SubTag] ...")` | 错误 | | ||
| 341 | +| `ACL_LOG_INNER_ERROR("[Check][Param] ...")` | 内部错误 | | ||
| 342 | +| `ACL_LOG_CALL_ERROR("[Model][FromData] ...")` | 调用失败 | | ||
| 343 | +| `ACL_LOG_WARN(...)` | 警告 | | ||
| 344 | +| `ACL_LOG_INFO(...)` | 信息 | | ||
| 345 | +| `ACL_LOG_DEBUG(...)` | Debug | | ||
| 346 | + | ||
| 347 | +日志标签格式: `[功能标签][子标签]` | ||
| 348 | + | ||
| 349 | +### OM1 vs OM2 关键差异 | ||
| 350 | + | ||
| 351 | +| 维度 | Legacy (OM1) | OM2 | | ||
| 352 | +|------|-------------|-----| | ||
| 353 | +| 执行器 | `ge::GeExecutor` + `gert::ModelV2Executor` | `gert::Om2ModelExecutor` | | ||
| 354 | +| 资源管理 | `acl::AclResourceManager` | `acl::AclResourceManagerOm2` | | ||
| 355 | +| 模型加载 | `executor.LoadDataFromFile` + `LoadModelFromDataWithArgs` | `gert::LoadOm2DataFromFile` + `LoadOm2ExecutorFromData` | | ||
| 356 | +| 模型数据 | `ge::ModelData` + `ge::ModelLoadArg` | `ge::ModelData` + `gert::Om2ModelLoadArg` | | ||
| 357 | + | ||
| 358 | +Legacy 存在两条加载路径:传统路径(`ge::GeExecutor`)和 RT2.0 路径(`gert::ModelV2Executor`),根据模型是否支持 RT2.0 选择。 | ||
| 359 | + | ||
| 360 | +## Common Mistakes | ||
| 361 | + | ||
| 362 | +| 错误 | 正确做法 | | ||
| 363 | +|------|----------| | ||
| 364 | +| 路由层直接写业务逻辑 | 路由层只做 OM1/OM2 分发,逻辑放 Impl 层 | | ||
| 365 | +| 忘记 `ACL_FUNC_VISIBILITY` 宏 | 对外接口和 Impl 声明都必须加 | | ||
| 366 | +| Impl 函数名不加后缀 | OM2 加 `ImplOm2`,Legacy 加 `Impl` | | ||
| 367 | +| Impl 签名与对外接口不一致 | Impl 参数必须与对外接口完全一致 | | ||
| 368 | +| 手动修改 stub 文件 | stub 由 `gen_stubapi.py` / `gen_stubapi_acl_mdl_impl.py` 自动生成,不要手动改 | | ||
| 369 | +| 头文件中使用 `bool`/`const int` | 用 `uint8_t` 替代 `bool`,用 `#define` 替代 `const int` | | ||
| 370 | +| 对外结构体不考虑扩展 | 预留指针参数方便后续扩展 | | ||
| 371 | +| 参数加 `const` 不考虑未来扩展 | 评估动态 shape 等场景是否需要修改参数 | | ||
| 372 | +| 修改/删除已有对外接口 | 存在即合理,只能新增,不能删改 | | ||
| 373 | +| 新增枚举/宏/结构体不加兼容性看护 | 必须在 `compatibility/` 对应文件中追加断言 | | ||
| 374 | +| 纯数据结构操作加 OM1/OM2 路由判断 | Desc/Dataset/AIPP 操作用模式 A 直连 OM2 | | ||
| 375 | +| 新功能加 Legacy Impl | OM1 从未支持的新功能只需 OM2 Impl | | ||
| @@ -60,6 +60,11 @@ bash build.sh --output_path=<PATH> # 设置自定义输出路径 | |||
| 60 | rm -rf build_ut/ build_st/ output/ build/ build_out/ cov/ build_cmake_gcov/ | 60 | rm -rf build_ut/ build_st/ output/ build/ build_out/ cov/ build_cmake_gcov/ |
| 61 | ``` | 61 | ``` |
| 62 | 62 | ||
| 63 | +## ACL 接口开发 | ||
| 64 | + | ||
| 65 | +**使用技能**: `acl-mdl-api-creator` | ||
| 66 | +**适用场景**: 新增 acl_mdl.h / acl_base_mdl.h 公开 API 接口,包括模型加载、执行、查询、Desc/Dataset/Config 操作等。 | ||
| 67 | + | ||
| 63 | ## 需求开发与新增功能 | 68 | ## 需求开发与新增功能 |
| 64 | > **触发词**:新增功能/需求/特性、开发新功能/需求/特性、实现功能/需求/特性 | 69 | > **触发词**:新增功能/需求/特性、开发新功能/需求/特性、实现功能/需求/特性 |
| 65 | 70 | ||