拆解昇腾 CANN 五层架构:一个 MatMul 请求的完整旅程
适合人群:想从全局视角理解 CANN 架构的开发者阅读时长:6 分钟。
适合人群:想从全局视角理解 CANN 架构的开发者
核心仓库:https://atomgit.com/cann
阅读时长:6 分钟
目录
- 一、为什么需要五层架构?
- 二、第1层:昇腾计算语言层 AscendCL
- 三、第2层:昇腾计算服务层
- 四、第3层:昇腾计算编译层
- 五、第4层:昇腾计算执行层
- 六、第5层:昇腾计算基础层
- 七、实战:追踪一个请求的完整路径
- 八、下一步资源
一、为什么需要五层架构?
拿到昇腾 NPU 的第一反应往往是:我写的 PyTorch 代码,是怎么跑到这块芯片上的?
答案藏在 CANN 的五层架构里。
先打个比方:你点外卖。用户(框架)→ 下单系统(AscendCL)→ 厨房调度(编译层)→ 出餐窗口(执行层)→ 灶台(硬件)。每一层各司其职,上层不用管下层怎么做,下层也不用管上层点什么。
这种分层的好处是解耦——框架升级不影响硬件调度,算子优化不影响上层接口。你的 PyTorch 代码今天能跑在 Ascend 910 上,明天换了新一代 NPU,代码也不用改。
如果只有三层会怎样?框架直接跟硬件打交道,每次换芯片就要重写一遍适配代码。昇腾 CANN 用五层架构把这个过程标准化了。
二、第1层:昇腾计算语言层 AscendCL
AscendCL 是 CANN 对外暴露的统一编程接口,相当于你跟昇腾 NPU 对话的"翻译官"。
不管你用的是 PyTorch、MindSpore 还是 TensorFlow,最终都会经过这一层。它提供的能力包括:
- 模型加载与执行:加载
.om离线模型,执行推理 - 内存管理:在 NPU 上分配/释放显存
- 流(Stream)管理:控制计算任务的并发执行
- 事件(Event)同步:多流之间的同步机制
# AscendCL 的核心 API 使用示例(Python绑定)
import acl
# 1. 初始化 AscendCL
acl.init() # 初始化ACL运行环境
# 2. 指定计算设备
device_id = 0
acl.rt.set_device(device_id) # 设置当前使用的NPU设备
# 3. 创建计算上下文和流
context = acl.rt.create_context(device_id)
stream = acl.rt.create_stream() # 创建执行流
# 4. 加载离线模型 (.om文件)
model_path = "resnet50.om"
model_id = acl.mdl.load_from_file(model_path)
# 5. 准备输入数据并执行推理
input_dataset = acl.mdl.create_dataset()
output_dataset = acl.mdl.create_dataset()
ret = acl.mdl.execute(model_id, input_dataset, output_dataset)
# 6. 释放资源
acl.mdl.unload(model_id)
acl.rt.destroy_stream(stream)
acl.rt.destroy_context(context)
acl.rt.reset_device(device_id)
acl.finalize()
大多数开发者不会直接调用 AscendCL API——框架适配层(torch.npu 等)已经帮你封装好了。但理解 AscendCL 的存在,能帮你搞清楚"代码到底是怎么到 NPU 上的"。
三、第2层:昇腾计算服务层
这一层是 CANN 的"武器库",包含两大核心组件:
AOL 算子库
AOL(Ascend Operator Library)提供了大量预优化好的算子实现,覆盖 AI 计算的各个场景:
| 算子库 | 仓库 | 定位 |
|---|---|---|
| ops-nn | https://atomgit.com/cann/ops-nn | NN 网络基础算子(Conv/BN/Pooling) |
| ops-transformer | https://atomgit.com/cann/ops-transformer | Transformer 进阶算子(FlashAttention/MoE) |
| ops-adv | https://atomgit.com/cann/ops-adv | 图像处理/科学计算算子 |
| ascend-transformer-boost | https://atomgit.com/cann/ascend-transformer-boost | Transformer 全流程加速库 |
AOE 调优引擎
AOE(Ascend Optimization Engine)负责根据你的模型结构和硬件配置,自动寻找最优的算子参数组合。比如:
- Conv2d 的 tile 大小用什么值最快
- MatMul 用哪种切分策略最省显存
- 多卡通信用什么拓扑最省带宽
# AOE 自动调优示例
# Step 1: 导出 ONNX 模型
python export_model.py --model resnet50 --output resnet50.onnx
# Step 2: 使用 AOE 调优(遗传算法 + 强化学习)
atc --model=resnet50.onnx \
--framework=5 \
--output=resnet50_optimized \
--soc_version=Ascend910 \
--auto_tune_mode="GA,RL"
# Step 3: 使用调优后的模型推理
# 调优后的 .om 文件已包含最优配置,直接部署即可
# 调优结果缓存在 ~/.ascend/aoe/ 目录,同结构模型可复用
AOE 的调优过程可能需要几小时,但只需跑一次,后续同结构的模型都能复用调优结果。
四、第3层:昇腾计算编译层
这是 CANN 架构里最"硬核"的一层,包含两个核心组件:
Graph Engine(GE)
GE 负责接收框架发来的计算图,执行以下优化:
- 算子融合:把相邻的小算子合成一个大算子。比如 Conv + BN + ReLU → FusedConvBNReLU,减少 kernel 启动开销和显存读写
- 常量折叠:编译期就能算出来的值直接算好,不等到运行时
- 死代码消除:删掉不会被执行到的算子
- 内存规划:复用中间 tensor 的显存,降低峰值
ATC 编译器
ATC(Ascend Tensor Compiler)把优化后的计算图编译成昇腾 NPU 可执行的 .om 文件:
# ATC 编译命令详解
atc --model=llama.onnx \ # 输入:ONNX模型
--framework=5 \ # 框架类型:5=ONNX
--output=llama_ascend \ # 输出:.om文件名
--soc_version=Ascend910 \ # 目标芯片
--input_shape="input:1,2048" \ # 输入shape(静态shape)
--insert_op_conf=aipp.cfg \ # AIPP预处理配置(可选)
--op_precision_mode=allow_fp32_to_fp16 # 精度策略
编译出的 .om 文件是一个自包含的离线模型,包含了算子指令、内存布局、调度顺序等所有信息,可以直接部署到昇腾 NPU 上运行。
五、第4层:昇腾计算执行层
编译好的 .om 文件到了这一层才真正开始跑。执行层包含:
Runtime
Runtime 是昇腾 NPU 的运行时环境,负责:
- 任务调度:把编译好的指令下发到 NPU
- 流管理:多流并发执行,最大化硬件利用率
- 显存管理:运行时的显存分配与回收
- 同步机制:Event/Stream 级别的同步
HCCL
HCCL(Huawei Collective Communication Library)是昇腾的多卡通信库,对标 NVIDIA 的 NCCL。支持:
- AllReduce / AllGather / Broadcast 等集合通信原语
- 多机多卡分布式训练
- 自动拓扑感知,选择最优通信路径
六、第5层:昇腾计算基础层
最底层,直接跟硬件打交道:
- 驱动(Driver):管理 NPU 设备的内核模块
- 固件(Firmware):运行在 NPU 芯片上的微代码
- 硬件管理:时钟频率、温度监控、功耗控制
这层对开发者基本透明,你唯一需要关心的是 npu-smi 工具——查看 NPU 状态、显存占用、温度等。
# npu-smi 常用命令
npu-smi list # 查看所有NPU设备
npu-smi info -t board # 查看指定卡的详细信息
npu-smi info -t usages # 查看显存和计算单元利用率
# 典型输出:
# NPU | Chip | Device | HBM-Used | AICore-Util
# 0 | 910 | 0000:01 | 12345/32768 | 85%
# 1 | 910 | 0000:02 | 8192/32768 | 42%
七、实战:追踪一个请求的完整路径
把前面六节串起来,看一个完整的请求路径:
PyTorch: model(x) → torch.npu 转发
↓
AscendCL: acl.mdl.execute() → 下发到编译层
↓
Graph Engine: 算子融合 + 内存规划 → 生成优化图
↓
ATC: 编译成 .om → 包含 NPU 指令
↓
Runtime: stream 调度 → 多流并发执行
↓
NPU: 达芬奇架构执行矩阵运算 → 结果写回 HBM
整个链路中,编译层的优化是性能差异最大的环节。同样一个 ResNet50,没优化可能只跑到 500fps,经过 ATC 编译 + GE 算子融合后可以跑到 2000fps 以上。
这就是为什么理解 CANN 架构很重要——不是让你手动优化每一层,而是帮你定位性能瓶颈在哪一层,然后对症下药。
八、去哪找资源
| 资源 | 链接 | 说明 |
|---|---|---|
| CANN 官方仓库 | https://atomgit.com/cann | 全部仓库索引 |
| Graph Engine | https://atomgit.com/cann/ge | 图执行引擎 |
| ATC 编译器 | https://atomgit.com/cann/atc | 模型编译工具 |
| 入门教程 | https://atomgit.com/cann/cann-learning-hub | 从浅到深 |
| 示例代码 | https://atomgit.com/cann/cann-samples | 官方 Sample |
建议先从 cann-learning-hub 的 “架构入门” 教程开始,把五层架构跑一遍。然后按需深入:做算子开发看 ops-* 仓库,做模型部署看 ATC 文档,做分布式训练看 HCCL。
遇到问题,atomgit 上的 issues 区和昇腾社区论坛都很活跃。
如果这篇文章帮你理清了 CANN 的架构脉络,点个赞👍,留个言💬,下期拆解 ATC 编译器的优化策略!
更多推荐




所有评论(0)