主题
达芬奇架构深度解析
达芬奇架构概述
达芬奇(DaVinci)架构是华为为昇腾 AI 处理器设计的专用 AI 计算架构,从第一代(Ascend 310/910)到最新一代持续演进。其核心设计哲学是:以矩阵计算为中心,向量和标量计算为辅助,通过精细的数据流管理最大化计算效率。
AI Core 内部微架构
┌─────────────────────────────────────────────────────────────┐
│ AI Core │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 计算单元 │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────────┐ │ │
│ │ │ Cube Unit │ │Vector Unit │ │ Scalar Unit │ │ │
│ │ │ 矩阵计算 │ │ 向量计算 │ │ 标量计算 │ │ │
│ │ │ (16×16 FP16│ │ 128×FP32 │ │ 通用 ALU │ │ │
│ │ │ per cycle)│ │ per cycle │ │ │ │ │
│ │ └────────────┘ └────────────┘ └────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 存储单元 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │
│ │ │ L1 Buffer│ │ L0 Buffer│ │ Unified Buffer │ │ │
│ │ │ (输入缓存)│ │ (计算缓存)│ │ UB (输出缓存) │ │ │
│ │ └──────────┘ └──────────┘ └──────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 控制单元 │ │
│ │ 指令调度器 / 流水线控制器 │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘Cube Unit:矩阵计算引擎
Cube Unit 是达芬奇架构的核心,专为矩阵乘法(GEMM)优化。
工作原理
Cube Unit 每个时钟周期执行一次 16×16 × 16×16 的矩阵乘法(FP16),即:
C[16×16] += A[16×16] × B[16×16]这等价于 16 × 16 × 16 × 2 = 8192 次 FP16 乘加运算(MACs)。
数据流
L1 Buffer (A矩阵) ──→
Cube Unit ──→ L0C Buffer ──→ UB
L1 Buffer (B矩阵) ──→支持的数据类型
| 数据类型 | 说明 | 典型场景 |
|---|---|---|
| FP16 | 半精度浮点 | 训练/推理主力 |
| BF16 | Brain Float 16 | 大模型训练 |
| INT8 | 8位整数 | 量化推理 |
| INT4 | 4位整数 | 极致压缩推理 |
| FP32 | 单精度浮点 | 精度敏感场景 |
Vector Unit:向量计算引擎
Vector Unit 负责逐元素运算,是 Cube Unit 的重要补充。
典型操作
- 激活函数:ReLU、GELU、Sigmoid、Tanh
- 归一化:LayerNorm、BatchNorm
- 逐元素加减乘除
- 数据类型转换(FP16 ↔ FP32)
向量宽度
- 单次处理 128 个 FP16 元素(或 64 个 FP32 元素)
- 支持 SIMD(单指令多数据)操作
存储层次与数据流
达芬奇架构的存储层次是性能优化的关键:
层级 容量 带宽 延迟
─────────────────────────────────────────────
寄存器 极小 极高 1 cycle
L0A/L0B/L0C ~512KB 极高 ~5 cycles (Cube专用)
L1 Buffer ~1MB 高 ~10 cycles
Unified Buffer ~256KB 高 ~10 cycles (Vector专用)
L2 Cache ~4MB 中 ~50 cycles
HBM 32-64GB ~900GB/s ~200 cycles关键设计:双缓冲(Double Buffering)
为了隐藏内存访问延迟,达芬奇架构支持双缓冲技术:
时间轴:
Cycle 1-N: 计算 Tile[0] 同时 预取 Tile[1] 到 L1
Cycle N+1-2N: 计算 Tile[1] 同时 预取 Tile[2] 到 L1
...这是 Ascend C 编程中 SetFlag/WaitFlag 机制的硬件基础。
指令集架构(ISA)
达芬奇架构有专用的指令集,主要分为四类:
1. 数据搬运指令(DMA)
GM → L1: Load 指令(从全局内存到 L1 缓存)
L1 → L0A: MTE1 指令(矩阵输入搬运)
UB → GM: Store 指令(结果写回全局内存)2. 矩阵计算指令(Cube)
MMAD:矩阵乘加(Matrix Multiply-Accumulate)
CONV:卷积运算3. 向量计算指令(Vector)
VADD/VMUL/VDIV:向量算术
VEXP/VLOG:超越函数
VCONV:数据类型转换4. 标量指令(Scalar)
通用 ALU 指令
分支跳转
地址计算流水线与并行性
达芬奇架构支持多级流水线并行:
┌─────────────────────────────────────────────────────┐
│ 流水线阶段 │
│ │
│ DMA Load ──→ Cube Compute ──→ Vector Compute ──→ DMA Store
│ ↑ ↑ ↑ ↑
│ 异步执行 异步执行 异步执行 异步执行
│ │
│ 通过 Barrier/Sync 指令保证数据依赖正确性 │
└─────────────────────────────────────────────────────┘这种设计要求开发者在编写 Ascend C 算子时,显式管理各阶段的同步关系。
Tiling:分块计算策略
由于 AI Core 的本地存储(L1/UB)容量有限,大矩阵必须分块(Tiling)处理:
python
# 概念示意(非真实代码)
for i in range(0, M, TILE_M):
for j in range(0, N, TILE_N):
for k in range(0, K, TILE_K):
# 将 A[i:i+TILE_M, k:k+TILE_K] 加载到 L1
# 将 B[k:k+TILE_K, j:j+TILE_N] 加载到 L1
# 执行 Cube 计算
# 将结果累加到 C[i:i+TILE_M, j:j+TILE_N]Tiling 策略的选择直接影响性能,这也是 TBE 和 Ascend C 中最重要的优化点之一。
数据对齐要求
达芬奇架构对数据对齐有严格要求:
| 操作 | 对齐要求 |
|---|---|
| Cube 输入(FP16) | 16 的倍数 |
| Vector 操作(FP16) | 16 的倍数 |
| DMA 搬运 | 32 字节对齐 |
| HBM 地址 | 512 字节对齐(最优) |
不满足对齐要求会导致性能下降或运行错误,这是算子开发中常见的坑。
达芬奇架构 vs GPU 架构对比
| 维度 | 达芬奇(昇腾) | CUDA(NVIDIA) |
|---|---|---|
| 核心设计 | 矩阵计算为中心 | 大规模并行线程 |
| 编程模型 | 数据流 + 显式缓存管理 | SIMT(单指令多线程) |
| 内存管理 | 显式分层(L1/UB/HBM) | 统一内存 + 自动缓存 |
| 并行粒度 | AI Core 级别 | Thread/Warp/Block 级别 |
| 适合场景 | 规则矩阵运算 | 通用并行计算 |
理解这一差异是从 CUDA 迁移到 CANN 开发的关键认知转变。