DMA Communication Terminology
一张图建立边界
下面这张图只回答一个问题:UDMA 与 IPC/MTE 分别如何建立地址关系、搬运数据并确认完成?
读图时应注意三点:
- IPC 不搬数据。它只导出、交换和打开设备内存句柄,最终形成
peerMems[]一类可寻址映射。 - MTE 才是 IPC 路径上的搬运引擎。数据通常经过 GM、UB 和远端映射 GM。
- UDMA 走独立的队列化路径。AICore 提交 WQE,由 UDMA 引擎完成远端访问,再通过 CQ 或
quiet()确认完成。
先把层级摆正
DMA 与 xDMA
DMA(Direct Memory Access)首先是一种机制:由专用硬件执行数据传输,通用计算单元不必逐字节参与搬运。CPU、Scalar 或 AICore 仍然可能负责初始化、地址计算和命令提交;“Direct”不等于“完全没有软件参与”。
从广义硬件角度,可以画成:
1 | DMA |
但在 SHMEM 的项目术语中,经常使用另一种分类:
1 | MTE 后端 vs. xDMA 后端族 |
这里的 xDMA 只是高速 DMA 类引擎的统称,不是 TileXR 中一个名为 xDMA 的具体接口,也不要与其他厂商名为 XDMA 的控制器混为一谈。MTE 广义上属于 DMA 单元,但 SHMEM 为了区分数据路径,会把 MTE 和 xDMA 分开描述。[^shmem-glossary]
UDMA 的命名边界
当前 SHMEM 术语表把 UDMA 展开为 Unified Direct Memory Access,即统一直接内存访问。TileXR 的 README 和 SHMEM_INTEGRATION.md 写成了 “User-space Direct Memory Access”,而集成总结又采用 “Unified Direct Memory Access”。
结合 TileXR 设计文档中的 UB/URMA 语境,本文采用上游 SHMEM 的 Unified Direct Memory Access。其中 “user-space” 可以描述部分控制方式,但不宜作为这里唯一可信的正式全称。
IPC 与 MTE
IPC(Inter-Process Communication)是进程间通信的总称。在 TileXR 中,它不是传统印象里的 CPU 共享内存拷贝,而是 NPU Runtime 提供的设备内存导出与映射机制。
MTE(Memory Transfer Engine)是 AI Core 的数据搬运单元:
- MTE1:主要负责 L1 到 L0 等核内路径;
- MTE2:负责 GM 到 UB、L1、L0A/L0B 等路径;
- MTE3:负责 UB 到 GM 的路径。[^ascend-mte]
所以 “IPC/MTE” 中的斜杠不是同义词连接符,而是表示一条组合路径:IPC 建立可寻址关系,MTE 执行实际数据搬运。
IPC/MTE:映射后搬运
TileXR 初始化 IPC 通路时,大致经历以下过程:
- 每个 Rank 分配自己的 NPU 通信缓冲区,前部作为同步 Flag 区,后部作为数据区。
- 调用
rtIpcSetMemoryName()导出本 Rank 的设备内存。 - 通过 Socket AllGather 交换 PID、SDID 和内存名称。
- 调用
rtIpcOpenMemory()将对端内存映射进本 Rank 的设备地址空间。 - 将映射地址写入
CommArgs.peerMems[i]。 - Kernel 使用 MTE 对这些地址执行搬运,并通过共享 Flag 完成 Rank 间同步。[^tilexr-comm]
一次典型的 Put/Get 可以抽象为:
1 | Put:本端 GM → MTE2 → 本端 UB → MTE3 → 对端映射 GM |
MTE 指令通常异步执行,需要使用 SetFlag/WaitFlag、EnQue/DeQue 或 PipeBarrier 协调 AI Core 内部流水;跨 Rank 的“数据是否已经可以消费”还需要 IPC Flag 等同步协议。
UDMA:队列化远端访问
TileXR 的 UDMA 控制面大致是:
- Rank 0 生成 SHMEM UID,并通过 Socket 交换给所有 Rank。
- 初始化 SHMEM,指定
ACLSHMEM_DATA_OP_UDMA。 - 建立 SQ、RQ、CQ、QP、远端内存注册信息和 Token。
- 取得设备侧
ACLSHMEMAIVUDMAInfo指针。 - 设置
udmaInfoPtr和ExtraFlag::UDMA。 - Kernel 通过 Put、Get、Atomic 或 Put-Signal 等接口提交 WQE。
- 使用 CQ、
quiet()或相应顺序语义等待非阻塞操作完成。[^tilexr-udma-design]
数据面可以抽象为:
1 | AICore 生成并提交 WQE |
某些 UDMA 接口会使用 UB/MTE3 暂存并下发一条 WQE,但这只是控制描述符的下发过程;大块 Payload 仍由 UDMA 引擎搬运,不能据此把 UDMA 路径误判为 MTE Payload 路径。
与 IPC 地址映射不同,SHMEM/UDMA 通常围绕对称或已注册内存、远端 Rank 和访问 Token 组织地址。因此,IPC 的 peerMems[] 地址与 UDMA 的对称内存操作数不能在没有适配层时直接互换。
两条路径的异同
| 维度 | UDMA | IPC/MTE |
|---|---|---|
| 本质 | 远端 DMA 数据引擎 | IPC 地址映射与 MTE 搬运的组合 |
| 寻址 | 对称或注册内存、Peer Rank、Token | 本地地址空间中的 peerMems[rank] |
| 数据路径 | 通常由 UDMA 完成 GM-to-GM | 通常通过 MTE2、UB、MTE3 中转 |
| 提交机制 | WQE、SQ/RQ、Doorbell | Ascend C DataCopy/MTE 指令 |
| 完成机制 | CQ、quiet()、Fence |
MTE Pipeline Event 加 IPC Flag |
| 远端原子 | 可提供 Atomic、Signal 等语义 | 通常另行设计 Flag 或原子同步协议 |
| 初始化成本 | SHMEM、QP、注册内存和队列状态 | 导出、交换并打开 IPC 设备内存 |
| 适用环境 | 依赖相应 UDMA 硬件、组网和软件构建 | 依赖对端内存可通过 IPC/HCCS/SIO 等路径映射 |
二者的共同点是:
- 都依赖 Host 侧先完成资源和地址准备;
- 都由硬件承担主要 Payload 搬运,而不是 CPU 逐字节复制;
- 都通常具有异步语义,需要显式处理完成、顺序和可见性;
- 都不能只凭“零拷贝”三个字推断端到端性能。
UDMA 也不保证在任何情况下都更快。同节点、可直接 HCCS 访问的小数据可能更适合 IPC/MTE;UDMA 更适合需要队列化 GM-to-GM、远端原子操作或 UB/URMA 互联的路径。最终选择仍取决于拓扑、数据规模、同步方式和硬件支持。
自动降级的真实边界
TileXR 当前进程模式的初始化顺序可以简化为:
1 | InitCommMem() // 先建立 IPC 通路 |
InitUDMA() 的多个失败分支会记录 Warning,保持 udmaInfoPtr == nullptr,不设置 ExtraFlag::UDMA,然后返回 TILEXR_SUCCESS。这保证了 UDMA 是附加能力,其初始化失败不会破坏已经建立的 IPC/MTE 通路。[^tilexr-init]
但 UDMA-aware Kernel 正确的结构仍然应该是显式分支:
1 | if (UDMAEnabled(args)) { |
TileXR 的设计文档也明确说明:当 UDMAEnabled() 为 false 时,由调用方决定走 MTE 还是报错。所以 README 中的 “Automatic fallback” 应理解成初始化级兼容与旧路径保留,而不是以下几种更强语义:
- 不是某条 UDMA 指令失败后的逐包重试;
- 不是
UDMAPutNbi()内部自动改写成 MTE Copy; - 不是跨不同地址模型的无条件透明切换;
- 也不表示所有既有算子都会自动获得 UDMA 加速。
当前源码的完成度
以 2026 年 8 月 25 日检查的 TileXR master HEAD 46c58f3 为准,README 中的自动降级更适合作为设计意图,而不是已经完全验证的透明传输层:
tilexr_udma.h使用了udma_enabled、peer_mem_ptrs、peer_flag_ptrs,但当前CommArgs的字段是extraFlag、peerMems、udmaInfoPtr;[^tilexr-wrapper][^tilexr-args]- Wrapper 引用的 SHMEM 头文件和函数名与锁定的 SHMEM 子模块接口并不完全一致;
InitThread()明确跳过 UDMA,线程模式继续使用进程内共享内存;- 集成测试对
CommArgs中 UDMA 字段的检查仍保留为 TODO。[^tilexr-test]
这些现象不改变前面的概念关系,但会影响工程判断:当前源码尚不能证明所有 UDMA-aware 算子都已经具备完整、经过验证的 IPC/MTE 等价回退。
常见误解
- 把 IPC 当成慢速 CPU 拷贝。TileXR 的 IPC 主要用于设备内存句柄交换与映射,Payload 可以继续由 NPU 的 MTE 搬运。
- 把 MTE 排除在 DMA 之外。从硬件分类看,MTE 是 AI Core 的 DMA 单元;只是 SHMEM 在后端分类中常把 MTE 与 xDMA 分开。
- 把 xDMA 当成具体引擎。xDMA 是家族名,UDMA 才是这里的具体后端之一。
- 把 Direct 理解成完全没有控制开销。UDMA 仍需要 UID、QP、队列、注册内存、WQE 和完成状态。
- 把自动降级理解成单次 API 透明替换。TileXR 当前保证的是 UDMA 初始化失败不破坏旧路径;Kernel 仍需显式实现等价分支。
总结
理解这些术语的关键不是背缩写,而是区分四个问题:
- 谁建立地址关系?IPC 或 SHMEM 注册内存与 QP 上下文。
- 谁搬运 Payload?IPC/MTE 路径中的 MTE,或 UDMA 路径中的 UDMA 引擎。
- 谁报告完成?MTE Event、IPC Flag、CQ、
quiet()等同步机制。 - 谁选择路径?Host 初始化暴露能力,Kernel 或上层传输封装显式分派。
因此,可以把全文压缩成一句话:DMA 是机制,xDMA 是家族名,UDMA 是具体远端搬运后端,IPC 负责映射,MTE 负责搬运,而 TileXR 的自动降级是“保留并选择旧路径”,不是“同一条 UDMA 指令自动变成 MTE”。
参考资料
[^shmem-glossary]: CANN SHMEM 术语表
[^ascend-mte]: Ascend C Storage Units and DMA Units
[^tilexr-comm]: TileXR tilexr_comm.cpp
[^tilexr-udma-design]: TileXR UDMA 能力扩展设计
[^tilexr-init]: TileXR UDMA 初始化实现
[^tilexr-wrapper]: TileXR tilexr_udma.h
[^tilexr-args]: TileXR comm_args.h
[^tilexr-test]: TileXR UDMA 集成测试
DMA Communication Terminology