cann-samples 贡献指南:Sample 目录规范、构建验证与 PR 合入全流程
【免费下载链接】cann-samplesCANN高性能实战演进样例与体系化调优知识库项目地址: https://gitcode.com/cann/cann-samples
导读
本文基于 CANN 高性能实战演进样例仓库cann-samples的 CONTRIBUTING.md 贡献指南,系统梳理仓库的贡献范围、三套 Sample 目录结构模板(模板 A/B/C)、README 与教程写作要求、本地构建验证流程以及从 Fork 到 PR 合入的完整链路。读者完成本文后,将掌握新增一个可独立构建、可验证结果、符合仓库规范的样例的全部实操要点,并理解根工程 CMake 配置、NPU_ARCH架构参数、.clang-format代码风格与 CI 门禁背后的实现机制。
仓库定位与贡献范围
cann-samples是一个"高性能实战演进样例 + 体系化调优知识库",其样例按主题被划分为三个目录层级,贡献者提交的改动必须与对应目录的定位一致:
| 目录 | 定位 |
|---|---|
0_Introduction | 介绍基础知识,建立基本概念,补全从入门到精通过程中的知识空缺 |
1_Features | 介绍关键特性,解耦大模型底层算子能力,包括公共优化技巧和关键芯片特性 |
2_Performance | 面向典型性能问题,展示专题化优化方法、演进过程和设计取舍 |
可接受的贡献类型
- 新增可独立构建、可验证结果的样例;
- 对现有样例进行问题修复、性能优化或可读性改进;
- 完善 README、tutorial、图示、验证脚本和构建说明;
- 补充通用脚本、公共组件或工程化改进,但必须服务于样例使用场景。
不应提交的内容
- 只有结论、没有可复现代码或验证过程的"经验总结";
- 与样例无关的大规模基础设施改造;
- 仅适用于个人环境的绝对路径、本地脚本、私有依赖或临时调试代码;
- 构建产物、压缩包、日志、核心转储、下载文件等生成物,例如
build/、build_out/、*.zip。
跨多个主题的改动应拆分为独立 PR,不要在同一个 PR 中混合提交新样例、重构和大规模文档调整。
开始之前:环境要求与兼容范围声明
环境要求
贡献者本地环境需要满足以下条件(与根 README.md 的环境部署章节保持一致):
- 已安装社区版 CANN Toolkit,并正确配置
ASCEND_HOME_PATH; - CANN Toolkit 版本要求与根 README.md 保持一致,使用其中说明的最低支持基线或更高版本的社区包;
CMake >= 3.16;Python >= 3.10;GCC >= 11.3.0;clang-format;requirements.txt中声明的 Python 依赖(当前声明en_dtypes、ml_dtypes、numpy>=2.0,<3、torch>=2.0,见 requirements.txt);- CMake 可发现的
ASC工具链包。
兼容范围声明
每个样例不需要覆盖全部硬件和场景,但每个贡献都必须声明以下内容,且同时出现在样例README.md和 PR 描述中:
- 已验证的硬件型号或架构;
- 已验证的 CANN 版本;
- 支持的数据类型、shape 约束和已知限制;
- 未覆盖但可能被用户误用的场景。
Fork 与远程配置
在 GitCode 上 Forkcann/cann-samples后,配置远程仓库:
git clone https://gitcode.com/<your-username>/cann-samples.git cd cann-samples git remote add upstream https://gitcode.com/cann/cann-samples.git提交前同步最新主线:
git fetch upstream git checkout master git rebase upstream/master社区协作与沟通
提交 Issue、PR 或参与讨论时,请聚焦问题本身:优先提供事实、复现步骤、边界条件和数据;对评审意见有异议时,给出代码、日志、数据或文档依据;若社区已有统一行为规范,以该规范为准。
仓库结构
根 README.md 的目录结构章节给出了完整视图,贡献指南中的骨架如下:
cann-samples/ ├── Samples/ │ ├── 0_Introduction/ # 基础知识与入门样例 │ ├── 1_Features/ # 关键特性与能力演示样例 │ └── 2_Performance/ # 性能专题与优化演进样例 ├── cmake/ # 工具链与公共 CMake 配置 ├── .ci/ # CI 相关脚本 ├── .gitcode/ # Issue / PR 模板 ├── CMakeLists.txt # 根工程构建入口 ├── README.md # 仓库总览 └── CONTRIBUTING.md # 贡献指南根 CMakeLists.txt 中,Samples目录按0_Introduction、1_Features、2_Performance、3_Utilities四个分组依次add_subdirectory,并借助set_property(GLOBAL PROPERTY USE_FOLDERS ON)与CMAKE_FOLDER在 IDE 中归类展示(见 Samples/CMakeLists.txt)。因此,新增样例除了补齐自身目录的CMakeLists.txt,还必须接入所属分组的父级CMakeLists.txt,才会成为根工程正式接纳的可构建目标。
Sample 目录结构规范:模板 A / B / C
新增样例应使用模板 A、B 或 C 之一。历史样例可以在既有结构内演进,但新增目录和新增专题应优先对齐模板;同一层级不要混用无语义命名;新增样例必须同时接入对应父级CMakeLists.txt。非标准目录结构只应用于收益明确的场景,并在 PR 中说明原因及其与模板的对应关系。
模板选择规则:
- 同时提供"可直接复用的最佳实践变体"和"按步骤展开的教程路径"时,优先使用模板 C;
- 样例围绕单一主题按优化阶段展开,且需要在
src/中平铺维护多个阶段实现时,使用模板 B; - 当样例代码可以直接平铺在样例根目录下、不需要稳定拆分
src/、include/、common/等职责目录时,使用模板 A;即使根目录下存在多个用于演示或对比的.cpp文件,也不必因此升级为模板 B。
模板 A:简单 Sample
适用于源文件少、逻辑集中的样例,例如vector_add一类最小可运行示例:
<sample_name>/ ├── CMakeLists.txt # 必须,构建配置 ├── <demo_a>.cpp # 必须,演示源码 ├── <demo_b>.cpp # 可选,并列对比的演示源码 ├── <helper>.h # 可选,平铺放置的辅助头文件 ├── README.md # 必须,样例说明文档 ├── images/ # 可选,README 引用的图片资源 └── scripts/ # 可选,数据生成和结果验证脚本 ├── gen_data.py └── verify_result.py适用条件:样例源码可直接平铺在根目录下,不需要再拆出稳定职责目录;允许存在多个并列的 demo.cpp文件用于展示不同写法、不同参数或不同实现之间的对比;可以有少量平铺放置的辅助.cpp/.h文件,但不应继续演化出独立模块层级;验证逻辑简单,可通过脚本或内嵌校验完成。样例目录名、目标名、README 标题应保持可映射,不应出现三套互不对应的命名。
模板 B:复杂 Sample
适用于围绕单一主题按优化阶段展开、需要集中展示基线实现与后续优化阶段的样例:
<sample_name>/ ├── CMakeLists.txt # 必须,构建配置 ├── README.md # 必须,样例说明文档 ├── src/ # 必须,源码目录 │ ├── 0_naive.cpp # 必须,基线实现 │ ├── 1_<stage>.cpp # 可选,第一阶段优化实现 │ └── 2_<stage>.cpp # 可选,后续阶段优化实现 ├── include/ # 可选,业务代码对应的头文件 ├── scripts/ # 可选,数据生成和结果验证脚本 ├── common/ # 可选,工具类或公共辅助代码 ├── images/ # 可选,README/docs 引用的图片资源 └── docs/ # 可选,README 之外的补充文档目录约束:
src/采用按阶段编号的平铺命名,文件名格式为<index>_<stage>.cpp,例如0_naive.cpp、1_multi_core.cpp、2_double_buffer.cpp。编号应连续,并与 README 的讲解顺序一致;include/、common/、scripts/、images/、docs/是该类内容的标准目录名,没有对应内容时可以省略;common/仅用于存放具有明确复用价值的工具类或公共辅助代码,不承载单个阶段私有实现;docs/仅承载 README 无法容纳的补充内容,不重复维护 README 已覆盖的信息;- 存在共享头文件、工具函数、验证脚本或验证数据时,应在 README 中说明其入口、适用范围和依赖关系,避免形成隐式依赖。
仓库中rms_norm_quant_story的src/下0_naive.asc、1_preload_gamma.asc、2_multi_core.asc等按阶段编号平铺的实现(见 Samples/2_Performance/rms_norm_quant_story/src/),即为模板 B 的典型落地形态。
模板 C:专题型 Story Sample
适用于同一算子主题下同时提供最佳实践与演进教程的专题样例:
<sample_name>_story/ ├── CMakeLists.txt # 必须,顶层构建配置 ├── README.md # 必须,专题总览 │ ├── <sample_name>_recipes/ # 必须,最佳实践代码 │ ├── CMakeLists.txt # 顶层,add_subdirectory 各变体 │ ├── README.md # 变体总览 │ ├── include/ # recipes 内共享的业务头文件 │ ├── common/ # recipes 内共享的公共辅助代码 │ └── <variant>/ # 每个变体一个子目录 │ ├── CMakeLists.txt # 当前变体的构建配置 │ ├── <variant>.cpp # 当前变体的实现代码 │ ├── images/ # 当前变体 README 引用的图片资源 │ ├── scripts/ # 当前变体的数据生成和结果验证脚本 │ │ ├── gen_data.py │ │ └── verify_result.py │ ├── README.md # 当前变体的使用说明 │ └── tutorial.md # 当前变体的设计说明或实现解读 │ └── <sample_name>_tutorials/ # 必须,演进教程代码 ├── CMakeLists.txt # 顶层,add_subdirectory 各 step ├── README.md # 教程总述 ├── include/ # tutorials 内共享的业务头文件 ├── common/ # tutorials 内共享的公共辅助代码 ├── scripts/ # 教程公共的数据生成和结果验证脚本 │ ├── gen_data.py │ └── verify_result.py ├── images/ # 教程总述或阶段文档引用的图片资源 ├── docs/ # 补充教程说明、图示或阶段说明 ├── 0_naive/ │ ├── CMakeLists.txt # 当前阶段的构建配置 │ ├── naive.cpp # 基线实现 │ └── include/ # 当前阶段的业务头文件 ├── 1_multi_core/ │ ├── CMakeLists.txt │ ├── multi_core.cpp │ └── include/ └── 2_double_buffer/ ├── CMakeLists.txt ├── double_buffer.cpp └── include/两条路径的职责必须清晰区分:
| 维度 | *_recipes/ | *_tutorials/ |
|---|---|---|
| 目标读者 | 有经验开发者 | 入门或中级开发者 |
| 主要目的 | 直接复用或二次开发 | 理解优化过程和原理 |
| 内容组织 | 各变体一个目录 | 按编号 step 组织 |
| 文档侧重点 | 怎么用、适合什么场景 | 为什么这样做、每一步改了什么 |
结构约束:顶层必须包含专题总览README.md、顶层CMakeLists.txt、*_recipes/和*_tutorials/;*_recipes/只存放可直接复用或对比的实现变体,*_tutorials/只存放按步骤展开的教学代码;共享common/只允许位于*_recipes/或*_tutorials/各自目录内,不得上提到专题顶层;*_recipes/与*_tutorials/相互独立,不共享代码、脚本、图片或验证数据;不允许不同 sample 目录之间相互复用代码、脚本或验证数据。仓库中 Samples/2_Performance/matmul_story/ 即为模板 C 的代表性实现(matmul_recipes/与matmul_tutorials/并行组织)。
验证方式
以下两种验证方式都可以使用,但结果必须可复现。
方式一:Python 验证脚本,适用于生成输入、调用框架计算标杆结果或进行批量验证的场景:
python3 scripts/gen_data.py ./<executable> python3 scripts/verify_result.py要求:明确输入规模、数据类型和随机种子;明确容差参数(例如atol、rtol);输出清晰的PASS/FAIL结论;验证失败时必须返回非零退出码,并打印可定位问题的关键信息;标杆输入、临时输出、性能测试原始数据应通过脚本生成,不直接提交大文件或本地导出结果。
方式二:C++ 内嵌验证,适用于简单、无额外依赖且标杆结果计算容易表达的样例。要求:不要把大量测试数据硬编码进源码;失败时输出足够的定位信息,例如索引、期望值、实际值。
新增样例接入清单
- 补齐本目录
CMakeLists.txt - 补齐所属分组父目录
add_subdirectory(<sample_name>) - 如引入专题子层级,补齐各层
CMakeLists.txt - 确保
cmake --build build --target help可见对应目标 - 确保 README 中的目标名、可执行名、运行命令与实际构建结果一致
README 和教程必须包含的内容
每个样例的README.md至少包含以下内容:
- 功能简介:1 到 3 句话说明样例目标;
- 支持范围:硬件架构、数据类型、shape 约束、输入限制;
- 目录说明:关键文件的作用;
- 构建与运行:完整命令;
- 验证方式:如何获得标杆结果或判定依据、如何检查结果;
- 预期输出:关键日志或结果示例;
- 性能说明:性能样例需说明主要优化点与收益。
Story / Tutorial 要求
Story / Tutorial 文档除 README 最小内容外,还应包含以下章节:
- 引言:说明待优化算法的背景、计算公式或计算流图;说明该算子或算法的重要性及典型应用场景或代表性网络;说明优化目标(如吞吐、时延或接近硬件理论峰值的目标);说明测试所用硬件环境及关键规格。
- 硬件架构基础:只介绍与当前优化直接相关的硬件概念;必要时引用
0_Introduction或1_Features中的相关内容;给出用于后续对比的理论上限,例如 Roofline Model。 - 基准实现:指向基线代码文件(如
0_naive.cpp);说明实现原理及其功能正确性;给出运行结果、性能测试结果和 profiling 数据;基于理论分析或 profiling 数据说明主要瓶颈;提供必要图示说明数据流、访存路径或瓶颈位置。 - 各优化阶段:每个优化阶段单独成节,标题与阶段文件名保持对应(如"优化阶段一:Multi Core"对应
1_multi_core.cpp);每个阶段均应说明修改内容、设计动机、性能结果和瓶颈变化,并提供必要图示。 - 总结与最终结果:提供从基线实现到最终版本的性能对比图表;提供与加速库版本或参考实现的性能对比;说明最终结果达到理论上限的比例;说明后续可继续优化的方向。
涉及性能结论的 Story / Tutorial 文档,必须写清以下上下文:硬件型号及关键规格、CANN 版本、输入规模、数据类型、测量方法。
贡献流程:从分支到合入
1. 创建分支
基于最新master创建独立分支,建议使用以下命名方式:
| 类型 | 格式 | 示例 |
|---|---|---|
| 新样例 | sample/<sample_name> | sample/softmax |
| 问题修复 | fix/<description> | fix/matmul-shape-check |
| 文档修改 | docs/<description> | docs/contributing-guide |
| 性能优化 | perf/<description> | perf/matmul-tile-opt |
git checkout -b <branch-name>2. 实现改动
- 一个样例目录应尽量自洽,避免对其他样例产生隐式依赖;
- 优先保持示例代码直观可读,再考虑过度抽象;公共逻辑只有在多个样例明确复用时才抽取;
- 如果引入限制条件,请在代码和文档里都写清楚;
- 如果修改已有样例的入口、目标名、目录结构或脚本参数,必须在 README 和 PR 中写明兼容性影响;若存在破坏性变更,必须提供迁移说明。
3. 本地构建与验证
根目录基础构建方式:
cmake -S . -B build -DNPU_ARCH=dav-3510 cmake --build build --parallelNPU_ARCH为必填参数,支持dav-3510(Ascend 950)和dav-2201(Ascend 910B/C)。910B 环境请使用-DNPU_ARCH=dav-2201。该参数在根 CMakeLists.txt 中被强制校验:未定义或为空时直接FATAL_ERROR并提示用法,取值不在VALID_NPU_ARCHS列表内时同样报错,而不支持当前架构的样例会在配置阶段跳过。这也解释了为何全量配置dav-2201时matmul_story、grouped_matmul_story会被跳过(见根 README.md 的说明)。
CI 打包脚本可通过参数指定架构;未传参数时默认使用dav-3510:
bash .ci/build.sh bash .ci/build.sh dav-3510 bash .ci/build.sh dav-2201.ci/build.sh 的完整流程是:清理build/build_out目录 →cmake -S . -B build -DNPU_ARCH="${NPU_ARCH}"配置 →cmake --build build --parallel并行编译 →cmake --install build --prefix ./build_out安装 → 按build_out_${NPU_ARCH}_${GIT_HASH}.zip命名打包,并用unzip -t校验压缩包完整性。
如果cmake -S . -B build -DNPU_ARCH=dav-3510失败,请先检查:
ASC工具链是否已被 CMake 正确发现(根 CMakeLists.txt 通过include(cmake/ascend.cmake)后执行find_package(ASC));ASCEND_HOME_PATH是否指向有效安装目录(cmake/ascend.cmake 优先读取该环境变量,未设置时会依次探测/usr/local/Ascend/ascend-toolkit/latest、$HOME/Ascend/ascend-toolkit/latest等默认路径,仍找不到则FATAL_ERROR;同时该文件会将 Bisheng 编译器路径导出为默认的 C/CXX 编译器与链接器);NPU_ARCH是否已传入且取值合法;- 样例是否遗漏父级
add_subdirectory(...)。
可选命令:
# 查看可编译目标 cmake --build build --target help # 安装构建产物 cmake --install build --prefix ./build_out如果 PR 只改动单个样例,请至少验证:根工程可以成功配置;受影响目标可以成功编译;样例结果验证通过;文档中的命令可以按描述执行;目标已被根工程正式接纳——仅存在目录但未被父级CMakeLists.txt通过add_subdirectory(...)接线的内容,不属于仓库正式可构建样例,不应在 README 或 PR 中声明"已支持"。
4. 提交代码
建议使用 Conventional Commit 风格:
<type>(<scope>): <subject>常用类型:feat(新增样例或能力)、fix(修复功能问题)、perf(性能优化)、docs(文档更新)、refactor(重构但不改变行为)、test(测试或验证逻辑调整)、build(构建系统或依赖调整)。
示例:
feat(sample): add softmax example with verification scripts docs(contributing): clarify review checklist and PR expectations fix(matmul): reject unsupported shape combinations5. 推送并发起 PR
git push origin <branch-name>然后在 GitCode 上向cann/cann-samples的master分支提交 Pull Request。PR 模板位于 .gitcode/PULL_REQUEST_TEMPLATE.zh-CN.md,包含描述、关联 Issue、测试、文档更新与类型标签(Bug 修复 / 新特性 / 性能优化 / 文档更新等)等字段。
6. 触发并通过 CI 门禁
提交 PR 后,需在 PR 评论区输入compile触发 CI 门禁(仓库在 .gitcode/workflows/ 下维护了compile_action.yml、staticcheck_action.yml等工作流配置)。要求:
- 根据 CI 检测结果修复构建、验证、格式或文档问题;
- 修复后重新推送分支,并再次触发门禁,直至 CI 通过;
- 在 PR 描述或评论中同步关键修复内容和当前状态。
7. 响应 Committer 检视
CI 通过后,等待 Committer 检视:根据检视意见继续修改代码、文档或构建配置;修改完成后重新推送分支,并在 PR 中同步更新说明;修改完成后@指派的 Committer,通知其继续检视。
8. Maintainer 最终审核与合入
Committer 检视通过后,PR 会标注/lgtm标签;随后等待 Maintainer 在 1 天内完成最终审核,确认无问题后标注/approve标签并合入 PR。
编码与文档规范
代码风格
项目使用根目录 .clang-format 统一格式,提交前格式化变更文件:
clang-format -i --style=file <source_files>.clang-format 中的主要规则如下:
| 项目 | 要求 |
|---|---|
| 基础风格 | BasedOnStyle: Google |
| 缩进 | 4 空格,禁止 Tab(IndentWidth: 4、UseTab: Never) |
| 行宽 | 120(ColumnLimit: 120) |
| 指针对齐 | 左对齐,例如int* ptr(PointerAlignment: Left) |
| 大括号 | 函数定义换行(AfterFunction: true) |
| include 顺序 | 不强制自动重排(SortIncludes: false) |
命名与可读性
- 目录名、样例名使用小写加下划线;
- 变量、函数、类型命名保持与所在目录既有风格一致;
- 避免使用无含义缩写,尤其在教程类样例中;
- 注释应解释"为什么这样做",不要机械复述代码。
许可证声明
新增源文件、头文件、CMake 文件请补齐许可证头,格式可参考现有文件(例如 Samples/CMakeLists.txt 顶部的 CANN Open Software License Agreement Version 2.0 声明)。
文档规范
- 所有命令示例默认以仓库根目录为起点,若不是,请显式说明;
- 文档中的路径、目标名、脚本名必须与仓库实际内容一致;
- 示例输出不要伪造;如果有简化,需说明是示意输出;
- 若复用了公共资源目录(共享标杆数据、公共辅助代码或共享脚本),README 必须写明其位置和用途;
- 如果新增脚本或流程会稳定产生输出文件,应同步更新 .gitignore(当前已隔离
build/、build_out/、__pycache__/、*.pyc)或在文档中明确约定输出目录。
构建、验证与提交前检查
提交前请至少检查以下内容:
- 改动范围与仓库定位一致,没有顺手夹带无关修改;
- 代码已经按
.clang-format格式化; - 根工程可成功
cmake -S . -B build -DNPU_ARCH=dav-3510; - 受影响目标能够成功编译;
- 新增样例已正确接入父级
CMakeLists.txt,根工程能够发现目标; - 样例结果验证通过,且验证过程可复现;
- README / tutorial / 图片 / 脚本已经与代码同步更新;
- 明确写出支持范围、限制条件和已知前提;
- 没有提交
build/、build_out/、压缩包、日志、下载包、临时标杆输出等生成物; - 新增脚本或流程产生的稳定输出已通过
.gitignore或目录约定隔离; - 提交信息符合约定,PR 描述能说明改动原因和测试结果。
如果改动涉及性能结论,请额外检查:
- 性能数据包含测试环境与输入条件;
- 优化收益可复现,不是偶然结果;
- 同时说明收益和代价,例如可读性、适用范围或资源占用变化。
Pull Request 要求与评审关注点
PR 至少应包含:影响范围(改了哪个样例、哪个目录、哪些目标)、改动动机(新增能力、修复问题还是补全文档)、验证命令(直接给出本地执行过的命令)、结果摘要(构建、验证、性能结果)、限制说明(未覆盖的硬件、shape、数据类型或后续工作)。
代码类 PR 还必须补充:已验证的平台、CANN 版本和关键依赖版本;目录结构是否完全符合模板,如有例外给出映射关系和原因;如涉及破坏性变更,给出迁移说明。建议补充:关键设计取舍或替代方案说明、典型日志截图或性能图表、未纳入本次 PR 的后续工作说明。
评审通常重点关注:改动是否与仓库定位一致;样例是否完整、能否独立构建和验证;文档是否足够让其他开发者复现;代码是否清晰、是否保持样例的教学价值;性能结论是否有数据支撑且上下文完整。
以下问题通常需要在评审前补齐:
- README 只写背景,不写运行方法;
- 只给构建命令,不给验证命令;
- 性能图表没有测试条件;
- 新增脚本但没有说明依赖和入口;
- PR 描述只写"优化代码"或"修复问题",缺少上下文。
Issue 反馈
仓库已提供以下模板(位于 .gitcode/ISSUE_TEMPLATE/):
- Bug:.gitcode/ISSUE_TEMPLATE/bug-report.yml
- 需求:.gitcode/ISSUE_TEMPLATE/feature-request.yml
- 文档:.gitcode/ISSUE_TEMPLATE/documentation.yml
- 咨询:.gitcode/ISSUE_TEMPLATE/question.yml
提交 Issue 前,请先搜索已有的 Issue、PR 和 Discussion;提问前请先阅读根 README.md 和对应样例文档。提交 Issue 时至少提供:硬件型号和架构、CANN 版本、操作系统与关键依赖版本、复现步骤、期望结果与实际结果、错误日志截图或最小复现样例。如果问题只在特定输入下出现,请写清输入规模、数据类型和约束条件。
安全与许可证
- 请勿提交账号、口令、Token、许可证文件或任何敏感配置;
- 请勿在文档中泄露内网地址、私有镜像源或本地路径;
- 发现安全问题时,请优先参考 SECURITY.md 的说明处理;
- 本仓库基于 LICENSE(CANN Open Software License Agreement Version 2.0)开源,贡献内容需与仓库许可证兼容。
【免费下载链接】cann-samplesCANN高性能实战演进样例与体系化调优知识库项目地址: https://gitcode.com/cann/cann-samples
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考