cann-samples 贡献指南:Sample 目录规范、构建验证与 PR 合入全流程
2026/9/18 2:52:57 网站建设 项目流程

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_dtypesml_dtypesnumpy>=2.0,<3torch>=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_Introduction1_Features2_Performance3_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.cpp1_multi_core.cpp2_double_buffer.cpp。编号应连续,并与 README 的讲解顺序一致;
  • include/common/scripts/images/docs/是该类内容的标准目录名,没有对应内容时可以省略;
  • common/仅用于存放具有明确复用价值的工具类或公共辅助代码,不承载单个阶段私有实现;
  • docs/仅承载 README 无法容纳的补充内容,不重复维护 README 已覆盖的信息;
  • 存在共享头文件、工具函数、验证脚本或验证数据时,应在 README 中说明其入口、适用范围和依赖关系,避免形成隐式依赖。

仓库中rms_norm_quant_storysrc/0_naive.asc1_preload_gamma.asc2_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

要求:明确输入规模、数据类型和随机种子;明确容差参数(例如atolrtol);输出清晰的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 最小内容外,还应包含以下章节:

  1. 引言:说明待优化算法的背景、计算公式或计算流图;说明该算子或算法的重要性及典型应用场景或代表性网络;说明优化目标(如吞吐、时延或接近硬件理论峰值的目标);说明测试所用硬件环境及关键规格。
  2. 硬件架构基础:只介绍与当前优化直接相关的硬件概念;必要时引用0_Introduction1_Features中的相关内容;给出用于后续对比的理论上限,例如 Roofline Model。
  3. 基准实现:指向基线代码文件(如0_naive.cpp);说明实现原理及其功能正确性;给出运行结果、性能测试结果和 profiling 数据;基于理论分析或 profiling 数据说明主要瓶颈;提供必要图示说明数据流、访存路径或瓶颈位置。
  4. 各优化阶段:每个优化阶段单独成节,标题与阶段文件名保持对应(如"优化阶段一:Multi Core"对应1_multi_core.cpp);每个阶段均应说明修改内容、设计动机、性能结果和瓶颈变化,并提供必要图示。
  5. 总结与最终结果:提供从基线实现到最终版本的性能对比图表;提供与加速库版本或参考实现的性能对比;说明最终结果达到理论上限的比例;说明后续可继续优化的方向。

涉及性能结论的 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 --parallel

NPU_ARCH为必填参数,支持dav-3510(Ascend 950)和dav-2201(Ascend 910B/C)。910B 环境请使用-DNPU_ARCH=dav-2201。该参数在根 CMakeLists.txt 中被强制校验:未定义或为空时直接FATAL_ERROR并提示用法,取值不在VALID_NPU_ARCHS列表内时同样报错,而不支持当前架构的样例会在配置阶段跳过。这也解释了为何全量配置dav-2201matmul_storygrouped_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 combinations

5. 推送并发起 PR

git push origin <branch-name>

然后在 GitCode 上向cann/cann-samplesmaster分支提交 Pull Request。PR 模板位于 .gitcode/PULL_REQUEST_TEMPLATE.zh-CN.md,包含描述、关联 Issue、测试、文档更新与类型标签(Bug 修复 / 新特性 / 性能优化 / 文档更新等)等字段。

6. 触发并通过 CI 门禁

提交 PR 后,需在 PR 评论区输入compile触发 CI 门禁(仓库在 .gitcode/workflows/ 下维护了compile_action.ymlstaticcheck_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: 4UseTab: Never
行宽120(ColumnLimit: 120
指针对齐左对齐,例如int* ptrPointerAlignment: 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),仅供参考

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

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

立即咨询