第3章 开发环境搭建:CANN安装与配置、AscendCL开发环境、算子开发工具链
说实话,搞算子适配第一步不是写代码,而是把环境整明白。我见过太多人卡在安装环节,一卡就是一整天。这一章咱们就把CANN、AscendCL、还有那堆工具链一次说透。你跟着我的节奏来,保证少踩坑。
3.1 CANN 安装与配置 —— 地基要打牢
CANN 的全称是 Compute Architecture for Neural Networks,说白了就是昇腾的软件栈核心。我习惯先装驱动和固件,再装 toolkit。顺序反了容易出幺蛾子。
版本配套表,官网有 Excel 文档,别偷懒。
安装步骤大致如下(以 Ubuntu 20.04 + CANN 7.0 为例):
# 1. 安装驱动和固件(需要 root)
./Ascend310B-firmware-*.run --full
./Ascend310B-driver-*.run --full
# 2. 安装 CANN-toolkit(普通用户也可以)
./Ascend-cann-toolkit_*-linux.run --install
# 3. 设置环境变量(建议写到 ~/.bashrc)
source /usr/local/Ascend/ascend-toolkit/set_env.sh
验证是否装好了?跑一句 npu-smi info,能看到芯片信息就说明驱动没问题。然后 ascend-dmi -i 可以看 toolkit 版本。我个人习惯再跑一个 sample 里的 add 算子,确认编译链路通。
--device=/dev/davinci0 和 --device=/dev/davinci_manager,不然卡不可见。我之前在容器里折腾了半天,最后发现是 device 没映射。
3.2 AscendCL 开发环境 —— 你写算子的第一站
AscendCL 是 CANN 提供的 C 语言 API 接口。你想想看,算子适配最终都要调到底层计算,而 AscendCL 就是那座桥。搭建这个环境其实不复杂,但有几个细节容易忽略。
头文件和库文件 在 toolkit 安装目录下:
/usr/local/Ascend/ascend-toolkit/latest/include/
/usr/local/Ascend/ascend-toolkit/latest/lib64/
编译时记得链接 -lascendcl 和 -lacl_dvpp(如果用到图像处理)。我一般写个 CMakeLists.txt 省事:
cmake_minimum_required(VERSION 3.10)
project(ascend_demo)
set(ASCEND_PATH /usr/local/Ascend/ascend-toolkit/latest)
include_directories(${ASCEND_PATH}/include)
link_directories(${ASCEND_PATH}/lib64)
add_executable(demo main.cpp)
target_link_libraries(demo ascendcl)
运行之前,记得 export LD_LIBRARY_PATH。我习惯在启动脚本里统一设,避免每次 export。
aclInit(nullptr) 程序,编译运行不报错,就说明 AscendCL 环境 ready 了。这一步通了,后面算子适配才有底气。
3.3 算子开发工具链介绍 —— 你的兵器库
昇腾给开发者准备了好几样兵器。我个人最常用的是 msopgen 和 tik,还有调试用的 gdb-davinci 和性能剖析工具 msprof。下面这张表一目了然:
| 工具 | 用途 | 我的使用频率 |
|---|---|---|
| msopgen | 自动生成算子描述文件、注册代码骨架 | ⭐⭐⭐⭐⭐ |
| tik (TBE IK) | 用 Python 写算子计算逻辑(DSL) | ⭐⭐⭐⭐ |
| gdb-davinci | 设备端调试,断点、查看 tensor | ⭐⭐⭐ |
| msprof | 性能数据采集,分析算子耗时 | ⭐⭐⭐⭐ |
| ascend-dmi | 设备信息查询、带宽测试 | ⭐⭐⭐ |
msopgen 这东西我太喜欢了。你只需要写一个 JSON 描述算子的输入输出、shape、数据类型,它就能帮你生成 C++ 和 Python 的适配代码框架。省去大量重复劳动。
# 举个例子,生成一个 "my_add" 算子的框架
msopgen gen -i my_add.json -c ai_core-ascend310b -o ./my_add_op
然后你会看到一堆文件:op_desc/, impl/, test/。你只需要往 impl 里填计算逻辑就行。嗯,这里要注意,生成的代码里有些占位符,比如 // TODO: implement,别漏了。
tik 是 TBE 的指令核(IK)编程方式。如果你习惯用 Python 写算子,tik 很友好。它底层会编译成达芬奇指令。我刚开始用 tik 时总搞混数据排布,后来发现只要记住 tensor 对象默认是 ND 格式,其他格式需要显式转换。
for 循环里用了 range(block_num) 但没对齐,导致越界。建议加上断言 assert 检查。
调试工具链 方面,gdb-davinci 支持在设备侧打断点,查看 tensor 值。但说实话,我更喜欢用 printf 大法(在 tik 里用 print_tensor)。性能调优时 msprof 是必须的,它能给出每个算子的执行时间、带宽利用率。