CANN Runtime API 模块拆分:四 PR 分批上库流程实战指南
2026/9/20 8:03:38 网站建设 项目流程

CANN Runtime API 模块拆分:四 PR 分批上库流程实战指南

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

CANN Runtime 仓库在按官方对外接口文档将巨型主Api/ApiImpl/decorator 链路拆分为独立ApiXxx/ApiImplXxxAPI 大类时,采用"独立文档 PR -> 框架 PR -> 路由 PR -> 清理 PR"的四 PR 分批上库模式,保证每个阶段可独立编译、验证和回退。本文完整讲解这套上库流程的每条前置原则、分支与提交规范、阶段检查命令、PR 描述模板、CI 门禁口径以及三阶段代码 PR 各自的审查重点,并结合仓库中 Event 拆分的真实批次(event-batches.md)说明落地方式。读完本文,你将能够按仓库规范为 Runtime API 模块拆分规划、提交并验收一整套分批上库 PR。

一、这套流程解决什么问题

Runtime 长期演进后,大量对外接口的 C API 入口集中在 src/runtime/api/api_c_*.cc 系列文件中,实际实现则堆积在单一主ApiApiImpl及其 decorator(api_decorator.cc)链路上。拆分工作的技术方法见 method.md,其核心链路是:

官方 acl/aclrt 接口 -> ACL 实现与 rt/rts 调用 -> src/runtime/api/api_c*.cc C 入口 -> 当前 Api 大类及成员函数 -> ApiImpl/平台实现/对象实现 -> CMake、stub、UT

把"一个官方模块"拆成新ApiXxx大类,如果一次性把所有改动压进一个 PR,会产生巨型 diff:既有新框架代码、C API 路由切换,又有旧链路删除,任何一步出问题都难以定位和回退。因此仓库规定:业务上永远是"框架 -> 路由 -> 清理"三个串行阶段,首次交付则固定为 4 个 PR(文档 PR + 三个代码阶段 PR),每一个 PR 只包含一个阶段、一个清晰提交。

以 Event 拆分为例(见 event-batches.md),首批 IPC Event 的落地就是:框架 PR(新增 api_event.hpp、api_impl_event.cc 等)-> 框架稳定化 -> 路由 PR(aclrtIpcGetEventHandle/aclrtIpcOpenEventHandle切到ApiEvent)-> 清理 PR(删除主Api旧链路)。三个代码阶段严格串行,后一个 PR 必须基于前一个实际合入后的最新主线。

二、前置原则:一次只做一件事

上库流程的第一步是确认以下 6 条前置原则,它们决定了所有后续操作的口径:

  1. 首次交付固定为 4 个 PR:独立文档 PR -> 第一批框架 PR -> 第一批路由 PR -> 第一批清理 PR。
  2. 三个代码业务阶段串行合入:框架 -> 路由 -> 清理,不允许并行推进或颠倒顺序。
  3. 文档 PR 纯净:只包含分析和方案交付件,不混入源代码、CMake 或 UT 改动。
  4. 基于实际主线:每个阶段基于前一阶段实际合入后的最新origin/master,不要长期堆叠在未合入提交上。
  5. 单 PR 单阶段:每个 PR 只包含一个阶段和一个清晰提交;检视清理确有必要时使用窄 PR,不混入下一阶段。
  6. 权限边界:推送、创建/更新 PR、发布评论或审批都需要用户明确授权,Agent 不得擅自执行线上写操作。

此外,submission.md特别强调要保留用户工作区中的无关改动:大改优先使用隔离 worktree,避免reset/checkout等可能覆盖用户工作的操作。

三、分支与提交建议

每个阶段使用独立分支,命名规则为:

docs/api-<module>-split-plan refactor/api-<module>-framework refactor/api-<module>-route refactor/api-<module>-cleanup

建议的提交标题如下:

docs: 新增 <Module> API 拆分分析与计划 refactor: 新增 Api<Module> 框架 refactor: 切换 <Module> API 调用链 refactor: 清理主 Api <Module> 旧链路

若阶段一合入后检视提出确定的依赖收敛意见,需要以窄补丁修复时,可使用:

refactor: 清理 Api<Module> 冗余依赖

Event 拆分中实际采用的分支与提交与此一致(event-batches.md),例如框架稳定化 PR 只收敛头文件和具体实现依赖,不改变业务路由,因而提交标题明确为"清理冗余依赖",不属于新的业务阶段。

四、准备阶段:隔离 worktree 与精准提取改动

创建分支前,先确认工作区和远程状态:

git status --short git remote -v git fetch origin master

为避免污染用户工作区,建议在隔离目录中基于主线创建分支:

git worktree add <isolated-path> -b refactor/api-<module>-framework origin/master

submission.md明确规定不要使用会覆盖用户改动的 reset/checkout 操作。若此前有聚合分支(例如包含完整三阶段验证的临时分支),需要按文件和 hunk 精准提取本阶段内容,而不是整体复制:

git diff --stat origin/master...<aggregate-branch> git diff origin/master...<aggregate-branch> -- <path> git add -p <path> git diff --cached --stat git diff --cached

提交前必须确认:暂存内容没有混入下一阶段接口,也没有包含用户无关文件。这一步是"单 PR 单阶段"原则在 git 操作层面的落地,git add -p允许逐 hunk 选择,是避免跨阶段污染的主要手段。

五、阶段提交检查

每个阶段提交后,至少执行以下三项检查:

git diff --check origin/master...HEAD git diff --stat origin/master...HEAD git log --oneline origin/master..HEAD
  • git diff --check:检查空白错误等低级问题;
  • git diff --stat:核对变更文件清单是否落在本阶段范围内;
  • git log --oneline:确认提交历史只有一个本阶段提交。

随后按 risk-and-validation.md 执行对应验证。该文档给出了框架、路由、清理三个阶段的最小验证矩阵,例如框架阶段要证明"现有 C API 仍走旧路径",路由阶段要证明"新路径与旧路径行为等价且旧主Api方法尚未删除",清理阶段要扫描全部旧符号残留并完成正式构建与多平台 UT。

submission.md特别强调:验证失败不能只写"环境问题"。要定位:

  • 失败发生在改动前还是改动后;
  • 是否进入目标源文件;
  • 属于功能回归还是证据缺口。

每个阶段的验证证据(命令、目标、通过/失败数、失败原因)都要真实记录,不得以"计划通过"之类的表述代替实际结果。

六、推送与创建 PR

推送与创建 PR 只能在用户明确要求后进行,完整流程为:

  1. 读取仓库gitcode-prSkill(涉及 GitCode PR 时)。
  2. 读取当前.gitcode/PULL_REQUEST_TEMPLATE.zh-CN.md不要使用旧硬编码模板
  3. 推送当前阶段分支到用户指定 fork。
  4. 创建目标为cann/runtime:master或用户明确指定分支的 PR。
  5. 若代码发生变更后刷新已有 PR,同步更新 PR 描述中的变更范围、风险、实际验证结果和剩余工作,不得保留与最新代码不一致的旧描述
  6. 回读线上 PR 的 title、head/base、提交数、描述和最新 commit,确认与本地一致。

关键的时序约束是:前一阶段 squash/no-merge 合入后,下一阶段要基于实际主线提交刷新,并重新执行完整阶段验证submission.md提醒不要假设 PR head SHA 等于最终主线 SHA——合入过程可能经历 squash 或 rebase,只有合入后的真实主线提交才可作为下一阶段基线。

七、CI 门禁:每个 PR 的可合入前提

每个 PR 创建或刷新后都必须检查线上 CI,文档 PR 与代码 PR 的门禁不同:

  1. 文档 PR:适用的文档、格式、OAT 和仓库必选任务必须通过。
  2. 框架、路由、清理 PR:仓库必选任务和 CI 编译任务必须通过,并结合阶段风险执行对应 UT。
  3. CI 失败时先定位并修复,推送修复后同步更新 PR 描述,再等待新一轮 CI。
  4. CI 未触发、仍在运行、编译目标被跳过或产物不可读时,记录为证据缺口,不得写成"CI 编译通过"。
  5. 只有线上 CI 显示成功且目标编译任务确实执行,才能将代码 PR 标记为可合入。

三个代码 PR 严格串行:前一代码 PR 实际合入且 CI 编译通过后,下一代码 PR 才基于最新主线刷新、验证和提交。这与 risk-and-validation.md 的验收结论分类一致——必须明确区分"已本地验证""已由线上流水线验证""因环境或权限未验证"等状态,CI 产物不可读时写"证据缺口"而非"全部通过"。

八、PR 描述模板与填写要点

PR 描述按仓库模板填充,描述部分至少包含以下内容:

## 描述 本 PR 是 `<模块>` API 大类拆分的 `<框架/路由/清理>` 阶段。 本批接口: - `<aclrtXxx>` -> `<rtXxx>` -> `<ApiXxx::Xxx>` 具体变更: - ... 行为等价说明: - C API 签名、参数校验、返回码、ErrMsg、profiling、Context/线程环境和产品支持保持不变。 本 PR 不包含: - 不切换/不删除下一阶段链路。 - 不整改 `<剩余接口>`;原因是 `<跨模块依赖/后续批次>`。 剩余工作: - ...

填写要点(submission.md与 method.md 的一致要求):

  • "本批接口"逐条给出 C API -> Runtime 入口 -> 新ApiXxx::Xxx的映射,这正是 method.md 端到端追踪的成果形态;
  • "行为等价说明"覆盖行为等价基线的关键维度:C API 签名、参数校验顺序、返回码转换、ErrMsg、profiling begin/end、Context/线程环境以及产品支持矩阵(标准、David/V201、tiny/arch5162、910B 等);
  • "本 PR 不包含"明确划清本阶段边界,防止检视者误以为路由阶段会顺带清理旧链路;
  • "剩余工作"列出后续批次和暂缓原因。

"如何测试"一节必须写实际执行结果,包括命令、目标、通过数和未完成项;不要预填计划结果。Checklist 只勾选真正完成的项目。这一口径贯穿整套流程:任何"计划验证""预计通过"性质的表述都不被接受。

九、三阶段代码 PR 的审查重点

三个代码阶段虽然共用同一套 PR 规范,但各自的描述重点和验收证据不同。

框架 PR

框架阶段为第一批接口新增或扩展ApiXxx/ApiImplXxx、Runtime 生命周期、构建接入和直接 UT,不切换任何 C API 路由。PR 描述必须强调:

  • 现有 C API 未切路由,对外行为没有变化;
  • 列出 Runtime 生命周期改动、各产品 CMake/stub 源文件清单和直接 UT;
  • 说明新增成员布局(Runtime 新成员位置、虚函数变化)与不支持产品语义。

以 Event 拆分批次一为例(event-batches.md),框架阶段新增 api_event.hpp 与 api_impl_event.cc,标准产品编译正式实现,tiny/arch5162 继续编译 api_impl_event_stub.cc 中的 not-support 桩;创建器(api_impl_creator.cc)按产品返回正确的动态类型。框架阶段合入后如检视提出高置信度的依赖收敛意见,可用窄范围稳定化 PR 处理(如 Event 的 PR 4219),它仍属于框架稳定化,不改变三阶段业务主线。

路由 PR

路由阶段只切换本批选中 C API 的入口到ApiXxx保留主Api旧方法。PR 描述必须:

  • 列出切换的确切 C API 清单(例如aclrtIpcGetEventHandleaclrtIpcOpenEventHandle);
  • 声明旧主Api方法仍保留、未删除;
  • 给出路由证明(通过隔离主Api实例证明 C API 确实进入ApiEvent);
  • 提供新旧行为对比(成功、空入参、非法 handle、Context/Device 异常、底层失败、feature-not-support、profiling、线程环境)和环境/profiling 验证结果。

路由阶段的风险点在于"表面上切换、实际仍走残留路径",因此 risk-and-validation.md 要求路由 UT 能隔离旧实例并证明参数、结果和输出写回的一致性。

清理 PR

清理阶段在前两阶段稳定后删除主ApiApiImpl、decorator、平台 stub 和旧 UT 中的本批残留。PR 描述必须:

  • 列出删除的 ApiImpl/decorator/platform/UT 范围;
  • 声明只清理本批接口,不扩展范围;
  • 附残留扫描(对主Api、ApiImpl、decorator、平台 override/stub、mock 和旧 UT 按确切符号执行rg扫描)、正式构建和多平台 UT 结果。

需要特别注意的是:删除虚函数和 include 后,各产品(标准、910B、tiny、arch5162、cmodel 等)必须均可编译和链接,新虚实现文件一旦漏进某平台源列表就会出现 vtable undefined 符号。因此 event-batches.md 强调:新增虚函数定义必须进入标准、David/V201、cmodel、tiny、arch5162、910B 及对应 UT 源列表,只验证 common 目标不能证明其他平台无链接缺口。

十、合入后收尾

每个 PR 合入后都要执行收尾动作,submission.md给出的清单如下:

  1. 记录实际主线提交和合入时间。
  2. 更新后续阶段基线与 PR 描述。
  3. 重新核对官方模块接口清单和剩余接口。
  4. 将已完成项标为"本批完成",保留后续/暂缓原因。
  5. 最后一阶段合入后,确认在线 PR 描述、设计文档和主线代码一致。

其中最后一条是关键的一致性收口:只有在线 PR 描述、设计文档与主线代码三方一致,才算一个模块批次的完整闭环。

最后,submission.md给出了一个重要的结论口径:不得因为三个阶段完成就自动宣称整个官方模块已完成。只有接口全集均有明确归属和处理结论(本批完成、后续整改、暂缓整改、无需整改)时,才能给出模块级完成结论。Event 拆分的状态汇报方式(event-batches.md)就是示例:

已合入:批次一 IPC Event 进行中:批次二查询、时间和标识 下一优先批次:批次三 GetAvailEventNum、EventWorkModeSet/Get(API 模块边界独立) 依赖解耦后决策:批次四 Event 同步(Soma 成功后副作用) 有条件推进:批次五生命周期 暂缓:批次六 Record/Reset 明确保留:StreamWaitEvent、SetOpWaitTimeOut

十一、配套资料与仓库依据

  • 拆分方法总纲:method.md(端到端映射、批次划分、行为等价基线、三阶段边界)
  • 上库与验证标准:risk-and-validation.md(风险矩阵、分阶段最小验证、命令选择、验收结论口径)
  • Event 真实批次与后续计划:event-batches.md(22 个 ACL 接口、六个业务批次、三阶段 PR 编号)
  • 模块拆分 Skill 主文档:SKILL.md(首次输出四 PR、执行流程、7 项文档交付件)
  • 代码结构参考:src/runtime/api/api_c_event.cc(C 入口)、api_event.hpp 与 impl/api_impl_event.cc、impl/api_impl_event_common.cc、impl/api_impl_event_stub.cc(实现层次)、impl/api_decorator.cc(decorator 链)、impl/api_impl_creator.cc(创建器)
  • 官方接口文档对照:docs/zh/api_ref/07_event_management.md(用于交叉核对接口清单)
  • UT 与构建入口:tests/ut/runtime、tests/build_ut.sh(--ut=runtime --target=runtime_utest_api等目标)

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询