第一次在昇腾 NPU 上跑算子,很多人会遇到两个极端:要么觉得"太难了,肯定要写 Ascend C",要么觉得"直接用 PyTorch 就行,不需要了解底层"。两种想法都不对。

cann-samples 就是来解决这个认知差的。它是昇腾 CANN 官方提供的算子实战样例库,里面有大量经过优化的示例代码,从 Conv2D 到 MatMul,从简单的单算子调用到完整的性能调优,覆盖了算子开发的完整路径。它的定位是**“高性能实现示例 + 体系化调优知识库”**,是 CANN 五层架构第2层的示例资源,和 cann-learning-hub(教程博客)互为补充——cann-learning-hub 告诉你概念,cann-samples 让你亲手跑通。

环境准备

开始之前,确保环境满足以下条件:

# 1. 检查 NPU 是否在位
npu-smi info
# 预期输出:能看到 Ascend 910 / Atlas 800T 等设备信息

# 2. 检查 CANN 版本(需要 8.0+)
cat /usr/local/Ascend/ascend-toolkit/latest/version.cfg
# 预期输出包含:Version=8.0 或更高

# 3. 检查 gcc 版本(编译需要 7.3+)
gcc --version
# 预期:gcc 7.3.x 或更高

# 4. 检查 cmake 版本(需要 3.16+)
cmake --version
# 预期:cmake 3.16 或更高

⚠️ 踩坑预警 1:gcc 或 cmake 版本不够时,编译报错信息看起来像算子代码问题,实际是编译器版本太低。如果看到链接错误(undefined reference to …),先查 cmake --version,不到 3.16 就升级 cmake。

# 升级 cmake(如果版本不够)
wget https://github.com/Kitware/CMake/releases/download/v3.27.0/cmake-3.27.0-linux-x86_64.sh
chmod +x cmake-3.27.0-linux-x86_64.sh
sudo ./cmake-3.27.0-linux-x86_64.sh --prefix=/usr/local --skip-approval
cmake --version # 再次确认

Step 1:找到适合入门的示例

# clone 仓库
git clone https://atomgit.com/cann/cann-samples.git
cd cann-samples
ls -la

cann-samples 的目录结构设计得很清晰,按算子类别组织:

cann-samples/
├── 01_basic/ # 基础算子示例,适合入门
│ ├── conv2d/ # 卷积算子
│ ├── matmul/ # 矩阵乘算子
│ ├── activation/ # 激活函数(ReLU/GELU)
│ └── reduction/ # 归约操作(Sum/Max/Mean)
├── 02_optimized/ # 优化过的示例(有性能对比)
│ ├── conv2d_fused/ # 融合卷积(Conv+BN+ReLU)
│ └── attention_fused/ # 融合注意力
├── 03_advanced/ # 进阶示例(自定义算子)
└── docs/ # 体系化调优知识库

入门推荐从 01_basic/matmul/ 开始。理由:MatMul 是所有深度学习模型的核心,代码逻辑简单,输出验证容易,可以快速确认环境是否就绪。

cd 01_basic/matmul
ls -la
# 预期看到:build.sh CMakeLists.txt src/ README.md

每个示例的 README.md 都有详细的说明,先读再跑,不要跳过。

Step 2:编译示例

# 进入 matmul 示例目录
cd 01_basic/matmul

# 查看编译脚本(每个示例都有 build.sh)
cat build.sh

build.sh 的内容通常是这样:

#!/bin/bash
set -e

# 为什么用 build.sh 而不是直接 cmake?
# 因为 build.sh 里做了环境检查、CANN 路径探测这些前置工作
# 第一次跑建议先读一遍 build.sh,搞清楚它在做什么

# 创建编译目录
mkdir -p build
cd build

# cmake 配置
# ${ASCEND_INSTALL_PATH} 是 CANN 的安装路径
# 如果环境变量没配,这里会报错,找不到 AscendCLConfig.cmake
cmake .. \
 -DCMAKE_BUILD_TYPE=Release \
 -DCMAKE_CXX_COMPILER=g++ \
 -DASCEND_INSTALL_PATH=/usr/local/Ascend/ascend-toolkit/latest

# 编译
make -j$(nproc)

⚠️ 踩坑预警 2ACL RT ERROR: DRV version mismatch——这是最常见的运行期报错。原因是 CANN 版本和 NPU 驱动版本不匹配。先检查版本:

# 查看 CANN 版本
cat /usr/local/Ascend/ascend-toolkit/latest/version.cfg

# 查看驱动版本
npu-smi info

# 两者必须配套:CAN 8.0 需要对应的驱动版本
# 如果不匹配,去昇腾社区下载对应版本的 CANN 安装包重新安装

环境变量没生效时的另一种报错:找不到 acl_rt_create_stream。这是因为 CANN 的环境变量没有 source。编译和运行之前必须执行:

source /usr/local/Ascend/ascend-toolkit/latest/set_env.sh
# 这条命令把 AscendCL 的库路径和头文件路径加到当前 shell 的环境变量里
# 不执行的话,cmake 找不到 AscendCLConfig.cmake,编译报 undefined reference

Step 3:运行示例,验证输出正确性

编译成功后,运行编译产物:

# 编译产物在 build/ 目录下
ls build/
# 预期:matmul_op(可执行文件)

# 运行
./build/matmul_op

正常输出的样子:

[AscendCL] Device 0 initialized.
[MatMul] Input A shape: [32, 128, 256]
[MatMul] Input B shape: [32, 256, 512]
[MatMul] Output C shape: [32, 128, 512]
[MatMul] Compute time: 1.23 ms
[MatMul] NPU result vs CPU result: MAX_DIFF = 0.000122, PASSED ✓
[AscendCL] Device 0 finalized.

关键看最后一行:MAX_DIFF 是 NPU 计算结果和 CPU 参考结果之间的最大误差,float16 精度下小于 0.01 就说明算子实现正确。PASSED ✓ 是测试通过的标志。

如果输出 FAILED ✗,先检查输入数据有没有问题(NaN 或 Inf),再检查矩阵尺寸是否在 CANN 支持的范围内(某些尺寸的矩阵乘 CANN 会有特殊处理)。

Step 4:修改示例,观察性能变化

跑通基础示例之后,下一步是理解"为什么这个实现是快的"。以 Conv2D 为例,cann-samples 提供了原始版本和融合版本两个实现,它们的性能差距能直观展示融合算子的价值。

# Conv2D 示例目录
cd 01_basic/conv2d

# 运行原始 Conv2D(Conv + BN + ReLU 分开跑)
./build/conv2d_basic

# 运行融合版本(Conv+BN+ReLU 融合成一个算子)
./build/conv2d_fused

# 对比两者的性能
# 融合版本通常快 30%~50%,因为减少了中间结果写回显存的次数

融合算子的原理:传统做法是 Conv 算完写回显存,BN 再从显存读出来算,写回,ReLU 再读出来算。融合版本三次操作合并成一次,中间结果全程在片上缓存流动,一次性写回显存。减少了 2 次显存读写,延迟自然下降。

📦 cann-samples 在生态中的位置

cann-samples 不是孤立存在的。它是昇腾 CANN 开发者工具链的重要一环。

上游依赖:opbase(算子基础组件,所有示例编译前要先编译 opbase)。asc-devkit(Ascend C 开发语言)为进阶的自定义算子开发提供语法支持。

下游使用:cann-learning-hub(社区学习中心)里的实战教程引用了 cann-samples 的示例代码。cann-samples 本身也提供了体系化的调优知识库(docs/目录),涵盖性能分析方法、算子融合规则、内存优化策略等内容。

与 cann-learning-hub 的关系:cann-learning-hub 侧重 NoteBook 教程和博客,适合学习概念;cann-samples 侧重可以本地编译运行的代码,适合动手实践。两者搭配学习效果最好——先用 cann-learning-hub 理解原理,再在 cann-samples 里亲手验证。

结尾

cann-samples 是昇腾 NPU 开发者最值得收藏的资源。它不需要你有算子开发的经验,只要会 git clone 和 mkdir build,就能从跑通第一个 MatMul 开始,逐步深入到融合算子优化和自定义算子开发。

从跑通到调优,cann-samples 给你提供了一条清晰的路径:先验证正确性,再对比性能,最后理解为什么性能有差距。这条路走通了,你对昇腾 NPU 算子开发的理解就比 90% 的纸上谈兵者扎实得多。

仓库地址:https://atomgit.com/cann/cann-samples

相关仓库:

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐