[AI][昇腾950]ND-DMA与PCIe-Through
AICore NDDMA 指令搬运能力与使用指南
1. NDDMA 概述
1.1 定义
NDDMA(N-Dimensional DMA,多维 DMA) 是 AICore 中 MTE2(Memory Transfer Engine 2)模块提供的硬件 DMA 指令,用于在 OUT(DDR/L2-cache)与 UB(Unified Buffer)之间执行点对点的高维张量搬运。它将传统 DMA 的"一维搬运"扩展为"5 维循环 + 5 维独立 stride"的通用形式,使得 transpose、broadcast、reshape+broadcast_pad、as_strided 等 AI 算子可通过单条指令完成。
1.2 支持的指令
| 指令名 | 方向 | 备注 |
|---|---|---|
ND_DMA_OUT_TO_UB |
OUT → UB | AIV 主用 |
GATHER_DMA_OUT_TO_UB |
OUT → UB(离散读) | NDDMA 的扩展,支持 UB 中的 IDX 索引 |
注:ND2NZ 与 NDDMA 共享硬件通路与 Cache,但 ND2NZ 是从 OUT 搬到 L1(AIC 专用),NDDMA 是从 OUT 搬到 UB(AIV 主用)。本文聚焦 NDDMA(OUT→UB)。
1.3 硬件共享关系
2 个 AIV Core 共享同一个 NDDMA-HAC(Hardware Accelerator)。
- AIC : AIV 比例 = 1 : 2
- 两条指令(NDDMA_OUT_TO_UB / GATHER_OUT_TO_UB)以命令级轮询、时分复用方式调度
- 因 ND-DMA 能力与带宽匹配,未做增强(不需要额外加速)
2. NDDMA 搬运能力
2.1 表达的算子类型
NDDMA 可表达所有点对点 DMA 算子,包括:
| 算子 | 配置方式 |
|---|---|
| Transpose(转置) | 设置 dst_stride 与 src_stride 为对应轴的置换 |
| Broadcast(广播) | 将部分 src_stride 设为 0,单点数据广播到 UB 多个位置 |
| Reshape + Broadcast_pad | 通过 axis division + padding 实现 |
| as_strided | 5 维 stride 自由配置 |
2.2 维度与循环参数
NDDMA 提供 5 个独立循环,每个循环具有独立的 size 与 stride:
| 参数 | 含义 |
|---|---|
loop0_size ~ loop4_size |
5 个循环的迭代次数 |
loop0_src_stride ~ loop4_src_stride |
源端每轴 stride(字节或元素) |
loop0_dst_stride ~ loop4_dst_stride |
目的端每轴 stride |
src_base_addr / dst_base_addr |
源/目的基地址 |
关键能力:
- 5 个循环独立可配
- 支持 padding 在内层 5 个循环中
- src_stride 设为 0 即实现 broadcast(多源 stride 为 0 → 多维广播)
2.3 数据类型支持
| 类型 | 位宽 | 数据宽度 |
|---|---|---|
| INT8 / B8 | 1B | 1B |
| FP16 / INT16 / BF16 | 2B | 2B |
| FP32 / INT32 / UINT32 | 4B | 4B(最小数据元素决定 bank 宽度) |
支持字节粒度读访问(FP16 = 2B、B8 = 1B)。
2.4 写 UB 规格
| 项 | 值 |
|---|---|
| 写 UB 端口 | 仅使用低 4 个写 UB port |
| 写粒度 | NDDMA 是唯一支持 partial write 写 UB 的指令,其他指令(L1/FIXP/MOV_ALGIN)均为 32B 粒度 |
2.5 NDDMA Cache 规格
NDDMA 配备专用 数据 Cache(用于缓存从 BIF/ROB 返回的数据):
| 项 | 值 |
|---|---|
| 总 RAM size | 16 KB |
| NDDMA Cache | 8 KB |
| ND2NZ Cache | 16 KB |
| Cache 行大小 | NDDMA: 128B / ND2NZ: 256B |
| 映射方式 | 直接映射(Direct Mapping),VIVT,1-way set associative |
| Tag RAM | 多 bank(T bank),支持 N bank 同周期读 |
| 替换策略 | 冲突 miss 时立即更新 tag 和 cache 内容(无 write back) |
| 共享 | 不仅 ND-DMA 访问,其他子模块也可访问;不同 U user 共享同一 cache partition |
| 端口 | M×read ports + M×write ports(不同 user 可共享同一 port) |
| ECC | 支持可配 ECC + read-modify-write(4B ECC 时字节读触发 RMW) |
| 失效 | 每条指令前由硬件自动 invalidate;另外两种失效场景:① 当前指令 scramble 模式与上条不同;② 高层 DDR/OUT 访问引起一致性问题,下发 DCI 指令 |
2.6 性能优化机制
(1) 硬化轴置换与拆分算法(Harden Axis Permutation & Division)
硬件电路实现轴置换与拆分,将整个张量划分为多个能放入 Cache 的子块,提升数据局部性。算法步骤(摘要):
- 初始化所有 axis label 为 0
- 按 dst_stride 升序排序得到 destination axis sequence
- 按 128B 粒度对 dst 方向合包(label 1=包入,label 2=拆轴)
- 按 src_stride0 升序排序得到 source axis sequence
- 按 128B 粒度对 src 方向合包
- 根据 dst & src label 表推导最终 label
- 移轴调序(Shuffling):label=0 的 “don’t care” 轴被置换到尾部
- Outstanding 合包:基于 cacheline_size 与 outstanding_size(32/64)拆分轴
- 总合包:尝试合并 axis 使子张量 < cache_size(32KB)
目的:保证每次访问的源地址范围不超过 cache 大小,提升 cache 命中率。
(2) Tag RAM 与 Cache Scrambling
为减少 cache bank 冲突,提供两种 scrambling 模式:
- Bit interleaving:对地址 bit14~bit2 做位交错哈希
- Divide-based hashing:针对 [0,2,1] 类型转置(最低 2 轴交换),按 src_stride0 计算 bank offset
启用条件(N 为单次内存访问最小连续字节数):
Dst_axis0 == src_axis1 && dst_axis1 == src_axis0
&& dst_axis0_size * src_axis0_size * len(data_format) >= N
&& src_stride0 >= N
或更一般地:Dst_axis0_size >= N/len(data_format) && src_stride0 >= N
(3) Address Coalescing
若第一目的轴 size > 128B/len(data_format),可保证每 batch 内只有相邻查询地址相同,做地址合并以减少 tag RAM 查询次数。
(4) Instruction Outstanding
支持指令拆 uop → 读 bus → 读 cache → 写 UB 4 个 stage 的前后指令 outstanding,提升并发度。
2.7 NDDMA Cache 一致性
- 2 个 AIV 共享同一 NDDMA Cache,可能跨 user 访问 → 需 DCI 指令维护一致性
- 软件 responsibility:同一 stream(同一算子)内,软件自动检查 NDDMA D-Cache 一致性,存在风险时插入 ND-DMA DCI 指令
- 由于 NDDMA 有两种 hash 映射模式(polynomial hash / division mapping),即便 stream ID 相同,指令间一致性也无法保证,必须由硬件执行以下动作:
- 每条 NDDMA 指令前硬件自动 invalidate cache
- 不同 scramble 模式切换时强制 invalidate
2.8 L2 Prefetch 限制
NDDMA 不支持 L2 prefetch 特性。若 L2 cache control 域段配置为 prefetch,会报异常。
3. NDDMA 参数配置
3.1 指令编码(关键字段)
NDDMA 指令编码, 关键字段:
| 字段 | 含义 | 配置约束 |
|---|---|---|
| src_base_addr | 源基地址(VA) | 虚拟地址,需经 SMMU 翻译 |
| dst_base_addr | 目的基地址(UB 内偏移) | UB 物理偏移 |
| loop0~4_size | 5 维循环次数 | 每轴 size ≥ 1 |
| loop0~4_src_stride | 源端每轴 stride | 设为 0 实现 broadcast |
| loop0~4_dst_stride | 目的端每轴 stride | 决定 UB 写入模式 |
| data_format | 数据类型 | B8/FP16/FP32/BF16/INT16/INT32 |
| pad_val | padding 数值 | 由 SPR 配置 |
| pad_sel | padding 来源 | 1=SPR 值,0=对应 burst 首元素 |
| L2 cache control | L2 缓存控制 | NDDMA 不可配 prefetch,否则报异常 |
| PCIE-through enable | PCIe 直通使能 | 由 SPR 或 VA 窗口配置 |
3.2 SPR 配置
NDDMA 相关 SPR 包括:
- PCIE mode enable SPR:指示是否启用 PCIe-through 模式(因 src_addr 是 VA,MTE 无法区分是否 PCIe 地址)
- pad_val SPR:padding 数值
- max burst length SPR:PCIe 模式下的最大突发长度(512B/256B/128B)
- scramble mode SPR:选择 scrambling 模式
3.3 Padding 配置
| 模式 | padding 触发条件 | pad_val 来源 |
|---|---|---|
| Normal | 只对有效 burst(OFST 有效)做 padding | pad_sel=1: SPR 值;pad_sel=0: 对应 burst 第一个 element |
| Compact | 只在最后一个 burst 有效时做 padding(尾端) | pad_sel=1: SPR 值;pad_sel=0: 最后一个 burst 的第一个 element |
注意:NDDMA 支持 nearest padding 和 SPR padding(与 Gather DMA 一致)。
3.4 轴置换算法参数(硬件自动)
硬件自动执行轴置换,软件只需配置原始 5 维参数。算法关键阈值:
N = 128B(合包目标粒度)cache_size = 32KB(子张量大小上限)outstanding_size = 32 或 64(outstanding 合包阈值)cacheline_size = 128B
4. 结合 AscendC API 的注意事项
AscendC 是基于 DaVinci C++ API 框架,本文档未直接覆盖 AscendC API 详情,但根据指令映射与硬件特性,可推导以下使用要点。
4.1 AscendC API 与 NDDMA 指令的对应关系
AscendC 中的高维数据搬运 API(如 DataCopy、DataCopyPad、CopyTile 系列)在编译时根据参数选择底层指令:
- 一维 + 简单 stride →
MOV_OUT_TO_UB_ALGN_V2或MOV_OUT_TO_UB - 多维(≥2 维有效)+ transpose/broadcast →
ND_DMA_OUT_TO_UB(NDDMA) - 离散读(IDX 索引)→
GATHER_DMA_OUT_TO_UB - 离散写(IDX 索引)→
SCATTER_DMA_UB_TO_OUT
4.2 关键使用约束
(1) Cache 一致性
- AscendC 算子内多次 NDDMA 调用,若访问相同源地址区域,软件需自动插入 ND-DMA DCI 指令
- 不同 stream 间 NDDMA 共享 cache,需通过 DCI 显式失效
- 因 2 个 AIV 共享 NDDMA-HAC,多 AIV 并行算子需考虑 cache 抢占
(2) 数据对齐
- 128B 地址对齐对大 size 搬运性能友好(cache line 对齐)
- 字节粒度读访问支持,但 4B ECC 启用时触发 read-modify-write,性能下降
- 建议源地址按
len(data_format)对齐
(3) Padding 配置
- AscendC
DataCopyPad的padMode与padValue参数映射到 NDDMA 的pad_sel与pad_val SPR padMode=CONSTANT→pad_sel=1,使用 SPR 值padMode=REPLICATE(若支持)→pad_sel=0,使用 burst 首元素
(4) Stride 配置陷阱
- src_stride=0 实现 broadcast,但若多轴 stride 都为 0,需注意 UB 写入是否冲突
- stride × repeat count 不可跨越 PCIe VA 地址窗口边界(若启用 PCIe-through)
- 不同 stride 配置可能导致硬件启用不同 scramble 模式 → 强制 cache invalidate,影响性能
(5) L2 Prefetch 不可用
- AscendC 中
DataCopy的L2Cache hint参数对 NDDMA 路径无效 - 若误配置 prefetch + pre-allocate → 报异常
- 若配置 prefetch(不带 pre-allocate)→ 报异常
- 建议:NDDMA 路径配置 L2 cache control 为
0b0000(无操作)或0b0010(no-allocate)
(6) HWTS pre_allocate
- 通过 HWTS 调度的 NDDMA 任务,SQE 中
pre_allocate global字段建议保持默认 0 - 同时使能 ND-DMA 和 ND2NZ 时若开启 pre allocate 可能挂死
(7) partial write 与 UB 端口
- NDDMA 是唯一支持 partial write 写 UB 的指令,其他指令均为 32B 粒度
- NDDMA 仅使用低 4 个写 UB port,若同时存在其他写 UB 流量,可能形成端口竞争
- 大流量 NDDMA 建议避开 UB 写高峰
(8) ECC 故障处理
- NDDMA Reqbuf 2bit ECC 故障会转化为 HWTS task timeout,需走 AIC 硬复位流程 恢复
- AscendC 应用层无法恢复,需驱动层介入
- NDDMA Cache 1bit ECC 不回写纠正(数据一次性消费)
(9) AIC : AIV = 1 : 2 共享
- NDDMA-HAC 由 2 个 AIV 共享,命令级轮询时分复用
- 单算子内连续下发 NDDMA 指令,实际吞吐受共享调度影响
- 不需要软件做特殊处理,硬件保证命令级公平
(10) GATHER DMA 与 NDDMA 共用通路
GATHER_DMA_OUT_TO_UB需先从 UB 读取 IDX 才能生成读 OUT 地址- 与 NDDMA 共享 HAC,调度上时分复用
- AscendC 中
CopyTensor类离散索引 API 可能映射到 GATHER,需注意 UB 端口竞争
5. PCIe-Through 问题
5.1 应用场景
当 AICore 需要直接访问 PCIe 空间进行数据搬运(典型场景:Host DDR ↔ Device UB),由于 PCIe 协议特性(max burst 512B、乱序返回、64B/128B 粒度)与普通 DDR 访问差异较大,MTE 提供专用 PCIE-THROUGH mode 处理。
5.2 配置方式
PCIE-THROUGH 模式有两种配置方式,不可同时启用。若同时配置,VA 空间配置优先,SPR 配置被忽略。
(1) SPR 配置模式
| 项 | 说明 |
|---|---|
| 使能方式 | SC 配置 SPR 寄存器 pcie_mode_enable=1 |
| 最大 burst | 由 SPR 配置:512B / 256B / 128B |
| 适用方向 | 仅 BUS → UB(MTE2,AIV 输入侧) |
| 不支持 | atomic 操作 |
| 适用指令 | ND_DMA_OUT_TO_UB、GATHER_DMA_OUT_TO_UB 等所有 BUS→UB DMA MOV |
(2) VA 空间配置模式
| 项 | 说明 |
|---|---|
| 使能方式 | SC 配置 PCIe-through VA 窗口寄存器(仅 boot time 配置,运行中不可改) |
| VA 窗口粒度 | 至少 1GB,按窗口大小对齐 |
| 比较位数 | 1GB→18,2GB→17,依此类推 |
| 匹配规则 | MTE 命令起始地址与窗口比较,匹配则整条指令标记为 pcie_through enabled |
| 最大 burst | 512B / 256B / 128B(由 SC nmanager 配置) |
| 适用方向 | BUS → UB(MTE2)和 UB → BUS(MTE3) |
5.3 PCIe 数据返回特性
- 数据以 64B 或 128B 粒度返回,由单 bit 指示
- 128B 数据拼接不可跨越 128B 地址边界
- 数据乱序返回(burst 内 + burst 间均乱序)
- MTE 负责数据重排与 64B 数据块拼接
5.4 MTE2 / MTE3 PCIe 模式支持矩阵
| 指令 pipe | 源 | 目的 | PCIe 模式 |
|---|---|---|---|
| AIV MTE2 | BUS | UB | 支持(输入侧 PCIe→UB) |
| AIV MTE3 | UB | BUS | 支持(输出侧 UB→PCIe) |
MTE3 PCIe 模式仅支持 UB→BUS 的 AIV DMA MOV。
5.5 PCIe Mode AxUser 信号
PCIe 模式下 AxUser 信号与普通模式不同,部分信号被复用:
| AxUser bit | 普通模式 | PCIe 模式复用 |
|---|---|---|
| [14] | TLB_UNLOCK | Relax Order (RO) |
| [13] | TLB_LOCK | TLP hint |
| [12:11] | STASH_LPID | Processing Hints |
| [10:8] | STASH_LPID | PF number |
| [7:0] | STASH_LPID | VF number |
| TH | - | PCIe 模式 AW/AR 请求时设为 1 |
| SUBSTREAMID[15] | - | PCIe 模式 AW/AR 请求时设为 1 |
参考:BIF User 域段结构.xlsx
5.6 PCIe Mode 约束
- Rdata 仅适用于 MTE destination Rdata(即只对接收到的返回数据生效)
- PCIe 模式读 burst length = 128B / 256B / 512B
- 128B 粒度时,Rdata valid 必须 128B 对齐
- MTE→PCIe 写可保持 128B 粒度,无需拆分为 2 个 64B burst
- stride × repeat count 不可跨越 PCIe VA 地址窗口边界
5.7 与 STARS PCIe Through 模式的区别
STARS 也有自己的 PCIe Through 模式,与 AICore MTE PCIe-THROUGH 不同:
| 维度 | STARS PCIe Through | AICore MTE PCIE-THROUGH |
|---|---|---|
| 作用对象 | STARS 读取 SQE / 写 CQE | AICore 数据搬运(UB↔PCIe) |
| 数据流 | 控制面(任务描述符) | 数据面(张量数据) |
| StreamID | 存储在 HBM swap buffer,RO 域段固定为 1’b1 | 由 AxUser[14] 复用 RO |
| 二级指针 | 仅 RTSQ 的 SQE / CQ 的 CQE 可存 Host 侧;二级指针指向的 SQE 只能存 Device 侧 | 不适用 |
注意:两个 PCIe Through 模式可独立启用,但需协调 PCIe 带宽资源。
5.8 PCIe-Through 使用注意事项
(1) 配置时序
- VA 空间配置由 SC 在 boot time 配置,运行中不可改
- SPR 配置可由 SC 动态配置,但若 VA 已配置则 SPR 被忽略
- 软件需保证两者不冲突
(2) 地址窗口边界
- MTE 指令的 stride × repeat count 不可跨越 PCIe VA 窗口
- 软件设计 NDDMA 参数时需校验整个访问范围是否落入同一 VA 窗口
- 跨窗口需拆分为多条 NDDMA 指令
(3) Atomic 不支持
- PCIe 模式不支持 atomic 操作
- 需 atomic 的算子需走非 PCIe 路径
(4) 数据乱序处理
- PCIe 返回数据乱序,MTE 自动重排
- 软件无需干预,但需保证 RO 配置正确(PCIe 模式 RO 通常建议 1)
- STARS PCIe Through 模式下 RO 强制为 1’b1
(5) 突发长度选择
- 512B 突发性能最高但占用 PCIe 带宽大
- 128B 突发适合小数据包,但效率较低
- 建议根据 PCIe 链路宽度和 MRRS 选择
(6) 与 NDDMA Cache 的交互
- PCIe 数据返回仍经过 NDDMA Cache(BIF/ROB → Cache → UB)
- Cache 的 scrambling、axis permutation 等优化仍生效
- 但 PCIe 模式下数据乱序返回,cache refill 顺序可能不同,可能影响 scramble 模式选择
(7) MTE3 输出侧 UB→PCIe
- 仅 VA 空间配置模式支持 MTE3 UB→BUS
- SPR 模式不支持 MTE3
- 输出侧 MTE→PCIe 保持 128B 粒度,无需拆分
(8) 4K 大包传输
- 仅
MOV UB TO OUT ALIGN V2支持 4K 大包(指令 1bit 控制信号) - 支持拆分为 4KB / 2KB / 1KB / 512B / 256B / 128B
- 对应限流同步统计 1/2/4K 写(1/2/4K 相当于 4/8/16 个 entry)
- NDDMA 是否支持 4K 大包需查 ISA 文档(FS 中仅提及 ALGN V2 支持)
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐
所有评论(0)