CANN pyasc 贡献指南:从特性分级、Issue 创建到代码合入的完整实践
【免费下载链接】pyasc本项目为Python用户提供算子编程接口,支持在昇腾AI处理器上加速计算,接口与Ascend C一一对应并遵守Python原生语法。项目地址: https://gitcode.com/cann/pyasc
CANN pyasc 是一个为昇腾 AI 处理器提供 Python 算子编程接口的开源项目,其接口与 Ascend C 一一对应并遵循 Python 原生语法。本文基于仓库根目录的 CONTRIBUTING.md 贡献指南,系统梳理 pyasc 社区贡献的完整链路——特性分级(L1/L2/L3)、Issue 创建、方案评审、experimental 与 master 双分支合入流程、PR 上库要求(代码/文档交付件与合规检查),并结合仓库内的开发指南、门禁脚本与测试目录,说明一次"从 Issue 到合入"的贡献应如何落地。读完本文,你将掌握 pyasc 社区贡献的规范化流程,以及为 pyasc 新增一个 Ascend C API 的 Python 编程接口时所需准备的全部交付件。
一、贡献特性分类:L1 / L2 / L3 三级划分
参与 pyasc 贡献前,首先要判断你的变更属于哪一类特性,不同分类对应不同的贡献流程与评审深度。分类依据来自 CONTRIBUTING.md:
| 分类 | 说明 | 典型示例 |
|---|---|---|
| L1(轻量特性) | 简单的新增需求 / Bug 修复 / 特性优化 / 文档纠错等(< 200 行) | 新增 Ascend C Python API 接口、已支持特性场景 Bug 修复、性能优化、API 文档描述错误纠正等 |
| L2(大特性) | 大的功能特性 / 性能增强特性等 | 新增当前代码框架未支持的 PASS 优化大颗粒特性等 |
| L3(架构变更) | 核心接口变更 / 重大重构等 | 对外接口目录调整、对外核心流程接口变更、端到端编译运行流程变更等 |
其中,L1 中的"新增 Ascend C Python API 接口"是 pyasc 社区最常见的贡献形态。以仓库 docs/developer_guide.md 中的说明,新增一个 API 接口通常涉及四个开发模块:Python 前端模块(必需)、ASC-IR 定义模块(必需)、AST 转 ASC-IR 模块(非必需)、Ascend C 代码生成模块(非必需),这与 L1 特性"< 200 行"的规模预期基本吻合。
二、L1 特性贡献流程:Issue → 提交 → 标记完成
L1 特性(含 Bug 修复、文档纠错)流程最轻量,共三步:
Step1:创建 Issue
根据变更类型创建对应类别的 Issue:
| 类型 | 创建方式 | Issue 分配 |
|---|---|---|
| 新需求 | 新建Requirement\|需求建议类 Issue,阐明新增特性的设计方案 | 在评论框中输入/assign或/assign @yourself |
| Bug 修复 | 新建Bug-Report\|缺陷反馈类 Issue 描述 Bug | 在评论框中输入/assign或/assign @yourself |
| 特性优化 | 新建Requirement\|需求建议类 Issue 说明优化点,提供设计方案 | 在评论框中输入/assign或/assign @yourself |
| 文档纠错 | 新建Documentation\|文档反馈类 Issue 指出文档问题 | 在评论框中输入/assign或/assign @yourself |
新需求类 Issue 一般需包含以下内容:
- 背景信息:为什么要做这个需求;
- 价值 / 作用:该需求解决什么问题、带来什么收益;
- 设计方案:技术路线与实现思路。
Step2:代码提交与合入
- 若为
master分支上的特性内容,遵守master 主线分支的代码提交与合入流程; - 若为
experimental分支上的特性内容,遵守experimental 分支的代码提交与合入流程。
Step3:标记 Issue 已完成
代码合入并验证通过后,将对应 Issue 标记为已完成,闭环整个流程。
三、L2 与 L3 特性贡献流程:增加方案预讨论与 sig 评审
L2(大特性)与 L3(架构变更)相比 L1 多出方案预讨论和sig 评审两个关键阶段,整体流程为:
Step1:创建 Issue
同 L1 类特性的创建 Issue 步骤。
Step2:方案预讨论
- Issue 责任人找 sig 成员的 maintainer 指定架构师,进行方案预讨论,讨论形式可以是 Issue 区讨论或单独会议;
- 预讨论完成后,架构师勾选 Issue 状态为技术评审中,之后进入下一阶段——sig 评审方案。
Step3:sig 评审方案
- 申报 sig 评审议题:由 Issue 责任人申报评审议题;
- 参加 sig 例会评审方案:按时参加 sig 例会进行方案评审。
评审结果分两种情况:
- ❌ 评审未通过:可重新设计方案,继续 Step2 → Step3 流程;若需求未接纳,则流程终止。
- ✅ 评审通过:由 Issue 责任人填写会议纪要,重点包含以下信息:
- 评审通过结论(如有遗留问题,请记录遗留问题内容和闭环时间);
- sig 指定的新特性合入分支名(如有)——请重点关注这一项,新特性一般先合入对应特性分支,待验证充分且稳定后再同步合入 master 分支,新特性分支名由 sig 指定;
- sig 指定的新特性发布内容和 roadmap 节点(如有)。
基于评审结论纪要,找 sig 成员勾选 Issue 状态为已确认,并创建对应新特性分支(如有),之后进入下一阶段——合入 experimental 分支。
Step4:合入 experimental 分支
遵守 experimental 分支的代码提交与合入流程,完成代码开发与合入。
Step5:合入 master 主线分支
遵守 master 主线分支的代码提交与合入流程。此阶段有以下注意事项:
- 准备合入
master主线分支的内容,必须已合入experimental分支,且经过充分验证(如对应新增的 UT/ST 测试); - 准备合入
master主线分支前,建议跟 sig 成员的 maintainer 对齐合入时间,避免代码被拒绝合入(可在 PR 评论区 @maintainer_gitcode_id 对齐合入时间); - 相较于合入
experimental分支,多一步关键流程:触发 CI 门禁并通过。
Step6:标记 Issue 已完成
四、双分支代码合入流程:experimental 与 master
pyasc 采用experimental(特性验证)→ master(主线发布)的双分支演进策略,两条合入路径的差异核心在于 master 多了 CI 门禁环节。
experimental 分支的代码提交与合入流程
关键流程如下:
- Fork 仓库:将 pyasc 仓库 fork 到自己的命名空间下;
- 本地开发验证:在本地完成代码开发、编译与自测;
- 提交 Pull Request:向 experimental 分支提交 PR;
- 代码检视:找 sig 成员的 Committer 进行代码检视(可在评论区 @committer_gitcode_id 提醒);
- 闭环检视意见:找参与代码检视的对应 Committer 确认意见已闭环,然后申请加分 lgtm/approve;
- 合入 experimental 分支。
master 主线分支的代码提交与合入流程
关键流程如下:
- Fork 仓库;
- 本地开发验证;
- 提交 Pull Request;
- 触发 CI 门禁并通过:
- 通过评论
compile指令触发开源仓门禁,并依据 CI 检测结果进行修改; - 目前 CI 门禁包含以下检查项:代码编译、静态检查、UT 测试、冒烟测试;
- 如涉及 codecheck 误报,请提交给 sig 成员 Committer 屏蔽;如未及时处理,可在评论区 @committer_gitcode_id 提醒进行代码告警屏蔽处理;
- 通过评论
- 代码检视:找 sig 成员的 Committer 进行代码检视;
- 闭环检视意见:确认意见闭环后申请加分 lgtm/approve;
- 合入 master 主线分支。
仓库中的门禁脚本佐证
CI 门禁中的"静态检查"在仓库中有对应的可执行脚本实现,可提前在本地自查:
- scripts/static_check.sh:对
origin/master与 HEAD 之间的变更 C/C++ 文件执行两轮检查——clang-format-diff检查代码格式、clang-tidy-diff做静态分析,支持通过compile_commands.json或手动编译参数(-std=c++17 -I${PROJECT_ROOT}/include)驱动;脚本内置了TIDY_IGNORE_LIST白名单(例如python/asc/lib/runtime/print_utils.cpp的PrintWorkSpace符号因extern "C"ABI 需保留 PascalCase 而豁免readability-identifier-naming检查),最终输出clang-format-diff: N lines need formatting与clang-tidy-diff: N error(s), N warning(s)汇总并判定 PASSED/FAILED; - scripts/oat_check.sh:OAT 开源合规预提交检查(Python 版,依赖
oat-py>=1.0.1)。支持 PR 范围模式(基于 merge-base 收集整个 PR 的变更文件)与暂存文件模式,结合仓库根目录 OAT.xml 中的合规策略(CANN-2.0 许可证、华为版权头、禁止二进制文件类型)扫描文件,仅对Invalid File Type(非法文件类型)与License Header Invalid(缺少版权头)两类问题阻断提交,并在oat_reports/result.txt中输出扫描汇总。
五、PR 上库要求:代码交付件、文档交付件与合规检查
无论走哪条合入路径,PR 上库前都必须满足以下要求。
代码交付件
- 需提供新特性的功能实现文件和测试用例文件;
- 如果是贡献新的 Ascend C API 的 Python 编程接口,请参考 《Ascend C Python 编程接口开发指南》,完成对应代码交付件。该指南给出了完整的四模块开发链路:
- Python 前端模块(必需):在
python/asc/language/下的adv(高阶 API)、basic(基础 API)、core(核心数据结构与枚举)、fwk(内存管理与同步控制,含 TPipe/TQue)目录中新增接口代码; - ASC-IR 定义模块(必需):在
include/ascir/Dialect/Asc/IR/下新增 OP 节点定义(基于 MLIR/TableGen 语法); - AST 转 ASC-IR 模块(非必需):在
python/asc/codegen/function_visitor.py中新增语法节点处理接口; - Ascend C 代码生成模块(非必需):实现对应 API 的 ASC-IR 转 Ascend C 代码功能,涉及
lib/Target/AscendC/下的实现文件。
- Python 前端模块(必需):在
文档交付件
- 新特性 README 文档为必选,其余文档可视情况提供;
- 如果是贡献新的 Ascend C API 的 Python 编程接口,请参考 《Ascend C Python 编程接口开发指南》,完成对应文档交付件,其中 Python 接口资料(必需)的具体开发方法可参考 API 文档自动生成工具使用指南。
合规检查
- 代码是否符合 《C++ 编程规范》(项目内文档,基本参考 LLVM 代码风格并结合项目特点做约束)和 Python 的 PEP8 规范(
pyproject.toml中配置了ruff(line-length 120)与yapf(column_limit 120)作为自动格式化工具); - 代码是否编译通过;
- Markdown 文档语法是否符合规范。
PR 提交
- 通过
git命令提交目标分支 PR; - 检查 PR 标题是否清晰、PR 描述是否规范(指明更改内容和原因、是否关联对应 Issue);
- 检查是否签署 CLA。
六、贡献落地示例:以新增一个 Ascend C Python 接口为例
结合 docs/developer_guide.md,以基础 API 中最典型的双目矢量运算接口add(对应 Ascend C 的Add)为例,说明一份 L1 特性 PR 应包含的完整交付件:
1. Python 前端模块实现(python/asc/language/basic/vec_binary.py)
接口按"@overload声明重载 +@require_jit实现"的模式编写,覆盖 L0/L1/L2 三种重载形态(连续 count 模式、mask 逐 bit 模式、mask 数组模式):
@overload def add(dst: LocalTensor, src0: LocalTensor, src1: LocalTensor, count: int, is_set_mask: bool = True) -> None: ... @overload def add(dst: LocalTensor, src0: LocalTensor, src1: LocalTensor, mask: int, repeat_times: int, repeat_params: BinaryRepeatParams, is_set_mask: bool = True) -> None: ... @overload def add(dst: LocalTensor, src0: LocalTensor, src1: LocalTensor, mask: List[int], repeat_times: int, repeat_params: BinaryRepeatParams, is_set_mask: bool = True) -> None: ... @require_jit @set_binary_docstring(cpp_name="Add", append_text="按元素求和。") def add(dst: LocalTensor, src0: LocalTensor, src1: LocalTensor, *args, **kwargs) -> None: builder = global_builder.get_ir_builder() op_impl("add", dst, src0, src1, args, kwargs, builder.create_asc_AddL0Op, builder.create_asc_AddL1Op, builder.create_asc_AddL2Op)2. ASC-IR 定义(include/ascir/Dialect/Asc/IR/Base.td)
Add 属于双目矢量计算 API,可直接复用仓库提供的BinaryTemplateL0123Op模板,一行完成 L0/L1/L2/L3 四个 Op 的定义:
defm Add : BinaryTemplateL0123Op<"add", "Add", "operator+">;3. UT 测试用例(代码交付件中的必需项)
Python 前端 UT:在 python/test/unit/language/basic/test_vector_binary.py 中编写测试,通过
mock_launcher_run桩函数验证编译与执行流程,运行命令:pytest ./python/test/unit/language/basic/test_vector_binary.pyASC-IR / 代码生成 UT:采用 MLIR 的 lit 框架,测试文件位于 test/Target/AscendC/,用
CHECK指令断言 ASC-IR 能正确翻译为 Ascend C 代码。
4. 文档交付件:新特性 README 为必选;Python 接口资料按 API 文档自动生成工具使用指南 生成(可见@set_binary_docstring装饰器正是该自动生成机制的入口)。
5. 合规与门禁自查:本地先跑ruff check --fix与yapf -i --parallel -r规范 Python 代码(工具配置见 pyproject.toml),再按 scripts/static_check.sh 与 scripts/oat_check.sh 的逻辑自查 C++ 风格与开源合规,最后在 PR 中评论compile触发 CI 门禁(编译、静态检查、UT、冒烟测试四项),全部通过后找 Committer 检视并申请 lgtm/approve 合入。
七、常见问题与注意事项
- master 与 experimental 的关系:任何准备进入 master 的内容都必须先在 experimental 分支合入并经过充分验证,这是两条分支流程最本质的区别;
- CI 门禁误报处理:如遇 codecheck 误报,应提交给 sig 成员 Committer 屏蔽,而不是绕过门禁强行合入;
- 新特性分支:L2/L3 特性经 sig 评审通过后,一般先合入 sig 指定的特性分支,验证稳定后再同步 master,切勿在评审通过前直接向 master 提交;
- 交付件完整性:新增 Ascend C Python 接口时,Python 前端代码、ASC-IR 定义、UT 用例、Python 接口资料与 README 缺一不可,可对照 docs/developer_guide.md 的"开发内容"与"交付件"清单逐项核对;
- 仓库定位:本仓库为只读的公开仓库,贡献者通过 Fork + PR 方式参与,不直接修改主线代码。
【免费下载链接】pyasc本项目为Python用户提供算子编程接口,支持在昇腾AI处理器上加速计算,接口与Ascend C一一对应并遵守Python原生语法。项目地址: https://gitcode.com/cann/pyasc
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考