Mooncake Ascend Transports

导言

截至 2026-08-25,Mooncake 中的 USE_ASCENDUSE_ASCEND_DIRECTUSE_UBSHMEM 不是三个并列的“HCCL engine”,而是三次不同层次的演进:先复用 HCCL 的低层内存传输能力接通 Ascend,再用 ADXL/HiXL 收敛成通用的一边直传引擎,最后为 Fabric Memory 增加基于 CANN VMM 的专用映射快路。

最重要的结论是:这三条 Mooncake 路径按当前可见源码都不能直接称为 AIV 直驱。Direct 描述的是一边、零拷贝或更短的数据路径;VMM 描述的是内存分配、导出与映射;AIV 直驱描述的则是“谁在 Device 侧构造并提交通信工作”。它们处在不同维度。

本文以 Mooncake main 在 2026-08-25 的提交 43365d45 为代码截面,并沿已合入 PR、关联 Issue、Mooncake 当前文档、CANN API 文档、HiXL 与 CANN SHMEM 开源代码交叉核验。为避免把不同强度的证据混在一起,正文使用以下标记:

  • 事实:PR、Issue、文档或源码能够直接支持。
  • 推断:由多个事实推出,但项目没有直接宣告。
  • 判断:面向选型或未来演进的分析,依赖给定前提。

核心结论

先把容易混乱的名称拆开:

  1. USE_ASCEND 是第一代 HCCL 低层传输实现。它不是用 AllReduce 等集合通信搬 KV,而是复用 HCCL 内部的 TransportMem、内存注册、建链和 Read/Write 能力,给 Transfer Engine 提供一边读写。Mooncake 当前文档已明确把它标为待废弃路径。
  2. USE_ASCEND_DIRECT 是第二代 ADXL/HiXL 抽象。Mooncake 把内存注册、连接和同步/异步传输委托给 adxl::AdxlEngine,由库选择 HCCS、RDMA 等链路。当前 Mooncake 文档推荐新部署使用这条路径。
  3. USE_UBSHMEM 是 Fabric Memory 专用路径。它用 CANN VMM API 分离物理内存、虚拟地址和共享句柄,把对端 Fabric Memory 映射进本地虚拟地址空间,再通过 ACL 异步拷贝读写。它是对 Ascend Direct 的补充,而不是 HCCL 的第三种 engine。
  4. 三者在构建上基本是替代关系。公共选项看起来可以分别打开,但 Ascend transport 子目录用 if / elseif / else 选择一套源文件;运行时 ascend 也会在 Direct 与 HCCL 实现之间二选一,ubshmem 才拥有独立协议名。不要把“独立 CMake 选项”误解为“同一进程可同时叠加三种后端”。
  5. 三者都不是当前源码意义上的 AIV 直驱。Mooncake 可见提交点分别在 Host worker 或 Host API:HCCL 路径调用 TransportMem::Write/Read,Direct 路径调用 AdxlEngine::TransferSync/TransferAsync,UBShmem 路径调用 aclrtMemcpyAsync。没有看到 AIV Kernel 在 Device 侧准备 WQE/SQE、敲 doorbell 并推进完成队列。

可以先用一张结论表定住坐标:

构建选项 Mooncake 角色 主要抽象 可见提交者 当前定位 是否可据此称为 AIV 直驱
USE_ASCEND 旧 Ascend transport HCCL TransportMem RMA Host worker + ACL stream 兼容旧环境,待废弃 否;至少没有直接证据
USE_ASCEND_DIRECT 推荐的通用 Ascend transport ADXL/HiXL 一边传输引擎 Host 调用 AdxlEngine::Transfer* 通用主路径 否;Direct 不等于 AIV Direct
USE_UBSHMEM Fabric Memory 专用 transport CANN VMM + Fabric/IPC handle + ACL copy Host worker 调用 aclrtMemcpyAsync 特化补充路径 否;是远端映射,不是 AIV 提交

命名中的 Direct

Ascend DirectDirect 强调注册内存之间的一边、零拷贝或链路直达;AIV 直驱直驱强调 AIV 是否绕开 Host/AICPU 的高频提交环节。两者共享一个“直”字,但回答的是不同问题。

关键时间线

这条时间线不是简单罗列版本,而是展示每次引入解决了上一阶段的什么问题。

时间 事件 直接变化 动机与意义
2025-06-16 至 07-01 PR #502 合入 引入 USE_ASCEND、HCCL 相关依赖、内存注册、连接与 D2D 传输 先让 Transfer Engine 在 Ascend 上可用;复用 HCCL 的 HCCS/RoCE 能力,而不是从零实现传输栈
2025-07-12 至 07-18 PR #619 合入 增加批量同步传输、Debian 支持与修复 早期路径进入性能与可部署性修整;PR 报告 128 KB 非连续块批传带宽较逐次 transferSync 提升超过 100%
2025-08-06 Issue #719 提出 要求原生高性能零拷贝 P2P,覆盖 Device RDMA、SDMA、Host RDMA 与 A2/A3 异构场景 说明项目需要的不只是“Ascend 可用”,而是一个更完整、稳定的直传产品抽象
2025-08-13 至 08-18 PR #740 合入 引入 USE_ASCEND_DIRECT 与 Ascend Direct transport 将链路选择、内存注册、同步/异步请求等交给 ADXL,减少 Mooncake 自己维护 HCCL 私有式传输拼装
2025-08 至 09 PR #764PR #856 适配 ADXL 错误码、CANN 版本并修复 TCP 端口问题 Direct 从原型进入版本兼容和连接可靠性修复阶段
2025-10 至 11 HiXL 开源;PR #1037PR #1049 Mooncake 曾引入 hixl transport 名称,随后改回对外名称 Ascend Direct 表明底层产品从 ADXL 向 HiXL 演进,但 Mooncake 希望稳定用户面对的 transport 名称
2025-12-05 至 12-27 PR #1170 合入 Store 的 Ascend Direct 支持 Fabric Memory 模式与特殊 Host 分配 Fabric Memory 先作为 Direct 的一种能力进入 Store,早于独立 UBShmem transport
2025-12-31 Issue #1312 提出 建议用 CANN VMM API 支持 Fabric Memory,作为 Ascend Direct 的 NVLink-like 补充 目标从“通用直传 API”进一步下沉到“远端内存可映射”的内存语义
2026-01-18 至 01-26 PR #1399 合入 新增 USE_UBSHMEMUBShmemTransport、VMM Fabric handle 与准确性测试 将 Fabric Memory 明确成独立协议和专用数据路径,并暴露独立构建开关
2026-02-09 至 02-14 PR #1519 合入 MC_USE_UBSHMEM_IPC=1、Fabric allocator 和 Python NPU pluggable allocator 从 Fabric handle 扩展到同机跨进程 IPC,并解决上层框架如何获得可共享内存的问题
2026-03-02 PR #1591 合入 8 个 worker、每请求 4 个 stream 的 stream pool;接入 Store 的 ubshmem 协议 修补单 stream/串行同步带来的并行度不足,并把独立 transport 变成 Store 可用能力
2026-07 至 08-05 PR #3214 合入 Fabric 内存从 100% 逐步回退到 50% 容量申请,1 GiB 对齐,优先 ADXL 分配能力 Fabric Memory 的现实瓶颈不只在带宽,还包括大页粒度、连续容量、碎片和启动成功率

两个 Issue 的状态容易制造误读:#719#1312 后来都因 stale 流程被标记为 not_planned 或关闭,但其核心能力分别已通过 #740 和 #1399 合入。Issue 的最终状态是项目管理状态,不是“功能从未实现”的证据。

三次演进的动机

先解决可用性

第一阶段的约束很现实:Mooncake Transfer Engine 已经有统一的内存注册、segment metadata、batch transfer 和状态轮询接口,但 Ascend 端缺少一个可以直接接上的公开后端。PR #502 选择复用 HCCL 的低层传输组件:

  • 同 HCCS 域内可建立 IPC 类路径,跨 HCCS 域使用 RoCE 类路径。
  • 注册本地内存并把可访问信息传播给远端。
  • 把 Transfer Engine 的读写切片翻译为 TransportMem::Read/Write
  • 用 ACL stream 和同步接口管理执行顺序与完成状态。

事实:当前旧实现仍能在 hccl_transport.cpphccl_transport_mem_c.cpp 中看到:worker 创建 ACL stream,内存层初始化 HCCL dispatcher,根据拓扑创建 TransportMem,最终把请求落实到 Write/Read

推断:它适合作为最快接通既有 HCCL 软硬件生态的桥梁,但 Mooncake 需要自己管理较多 HCCL 低层对象、版本差异和边界条件。随着支持范围扩大,这套实现的维护成本会高于使用专门的一边传输产品接口。

再解决通用抽象

Issue #719 期望同时覆盖 HBM/DDR、Device RDMA、SDMA、Host RDMA、同构和异构部署。这样的矩阵已经不适合由 Mooncake 针对每条链路分别拼装。

Ascend Direct 因此把接口收敛为:

1
2
3
4
5
6
Initialize engine
→ RegisterMem
→ Connect peer
→ TransferSync / TransferAsync
→ Query completion
→ Disconnect / DeregisterMem / Finalize

在当前 Mooncake 源码中,transfer_executor_base.cpp 创建 adxl::AdxlEngine,负责初始化、注册内存与连接;async_transfer_executor.cpp 组装 adxl::TransferOpDesc 并调用 TransferAsync。Mooncake 不再直接决定每一次 HCCS、RDMA 或中转 buffer 细节,而是消费 ADXL 的一边通信能力。

当前 HiXL 仓库把旧接口放在“待废弃 ADXL 接口”下,同时提供新的 HIXL API。这表示 ADXL 是可见 API 的旧名字,HiXL 是正在演进的产品与接口层。Mooncake 的构建选项仍叫 USE_ASCEND_DIRECT,源码仍使用 adxl::AdxlEngine,所以不能仅凭上游仓库名称就声称 Mooncake 已完成 HIXL 新 API 迁移。

最后解决内存语义

通用一边传输通常仍然遵循“注册本地与远端内存,提交一条包含两端地址的传输描述符”的模型。Fabric Memory 希望进一步提供类似统一内存窗口的体验:

1
2
3
4
5
远端物理内存
→ 导出 Fabric shareable handle
→ 本地导入 handle
→ 映射到本地保留的虚拟地址
→ 本地代码以映射地址表达远端读写

这就是 Issue #1312 所称的 “NVLink-like Transport”。这里的 “like” 更准确地说是 远端内存的可映射性和地址使用方式相似,并不自动承诺与 NVIDIA NVLink 相同的缓存一致性、拓扑、指令集、带宽或故障语义。

独立 UBShmem path 的实际价值包括:

  • 数据路径更专用:不再为每次传输调用 Mooncake 中的 ADXL Transfer*,而是先完成映射,再用 ACL runtime 对映射地址做异步 copy。
  • 元数据更直接:传递的是 Fabric/IPC shareable handle、基址和长度,接收端导入后按 offset 重定位。
  • Allocator 可配套:上层必须从一开始就分配可导出的物理内存,不能把普通 aclrtMalloc 的任意 buffer 事后变成 Fabric Memory。
  • 可独立优化并行度:PR #1591 用 worker 和 stream pool 改善大量 KV block 的批量传输。

推断:UBShmem 并不是为了证明 ADXL/HiXL 做不到 Fabric Memory。PR #1170 已证明 Direct 也有 Fabric 模式。它更像是把 Fabric Memory 从“通用引擎的一种内部能力”提取成 Mooncake 能显式选择、单独分配和单独调优的快路。

横向对比

架构差异

维度 USE_ASCEND USE_ASCEND_DIRECT USE_UBSHMEM
对外 protocol ascend ascend ubshmem
Mooncake 类 HcclTransport AscendDirectTransport UBShmemTransport
建链抽象 HCCL socket、dispatcher、TransportMem AdxlEngine::Connect 元数据通道分发 handle;导入与映射远端物理内存
内存准备 HCCL memory registration/export/grant AdxlEngine::RegisterMem aclrtMallocPhysical、Reserve、Map、SetAccess、Export/Import
单次提交 TransportMem::Write/Read TransferSync/TransferAsync aclrtMemcpyAsync
完成方式 ACL stream 同步与 Mooncake slice 状态 ADXL request/同步接口 stream pool 同步后标记 slice 完成
链路选择 Mooncake/HCCL 低层逻辑处理 IPC、RoCE 等 ADXL/HiXL 根据能力与配置选择 HCCS/RDMA 等 ACL/Fabric Memory runtime;公开 Mooncake 层不直接说明物理搬运 engine
Host 内存支持 取决于旧实现能力 文档明确覆盖 H2D、D2H、D2D 核心目标是可导出/映射的 Device Fabric Memory,不是通用 Host RDMA
跨机通用性 可用但维护负担较高 三者中最通用 依赖 Fabric Memory 可达域、芯片与 CANN/驱动能力
当前定位 文档提示废弃 推荐主路径 特化补充与实验/优化路径

Mooncake 的 common.cmake 同时声明三个开关,但 ascend_transport/CMakeLists.txt 使用条件分支选择 HCCL、异构 HCCL、UBShmem 或 Direct 源文件;multi_transport.cpp 再把运行时协议映射到具体类。

独立选项不等于可叠加

PR #1399 的作者在 review 中确认 USE_UBSHMEM 应是 independent option,意思是它不必藏在 USE_ASCEND_DIRECT 之下,能够被单独选择和构建。当前 CMake 的 elseif 又表明 Ascend transport 的实现源文件按 flavor 选择。两句话并不冲突:配置入口独立,产物中的实现仍基本互斥。

使用场景

可以按问题而不是按名字选后端:

  1. 新部署需要跨节点、Host/Device 多种方向和通用容错:优先 Ascend Direct,除非当前 CANN/驱动组合只验证过旧 HCCL path。
  2. 必须兼容已有旧版本环境:保留 USE_ASCEND,但应把迁移 Direct 纳入计划,因为 Mooncake 当前 Ascend Transport 文档 已明确提示废弃。
  3. A3 Fabric Memory 域内大量 KV block 搬运,能够控制 allocator 与进程模型:可以评估 UBShmem,并与 Direct Fabric mode 做同硬件 A/B,而不是只和非 Fabric Direct 对比。
  4. 目标是让算子 Kernel 自己发起细粒度通信:这三个开关都不是充分条件,应调研 CANN SHMEM/URMA 的 Device API 或 HCCL AIV 通信 engine,并重新设计 Transfer Engine 的 Device 侧队列与完成机制。

当前 Mooncake 构建文档 对 UBShmem 给出的环境门槛包括 CANN 9.0.0 及以上、Driver 26.0.0 及以上和 Lingqu 1.5 及以上。它不是仅打开一个 CMake 开关就能在任意 Ascend 机器上工作的通用共享内存。

概念坐标

这部分先用小白语言建立直觉,再用专业定义校正。

小白版

把两张 NPU 卡想成两个仓库:

  • 一边通信:A 仓库发出“把这批货放到 B 的 3 号货架”,不要求 B 的管理员为这一次请求同步调用一个 recv
  • 零拷贝:货物尽量从注册的源货架直接运到目标货架,中间不再落到临时仓库倒一次。
  • Direct transport:运输公司根据两地条件选择内部高速通道或跨园区道路,用户只提交起点、终点和长度。
  • Fabric Memory:B 仓库把某些货架以安全凭证共享给 A;A 在自己的地址簿里给这些货架安排一个可用地址。
  • AIV 直驱:A 仓库的现场工人不再每搬一小批货都去找办公室调度员,而是自己填写运输队能识别的工作单并按门铃提交。

这五件事可以组合,却不互相蕴含。货架能出现在本地地址簿里,不代表现场工人拥有提交运输任务的权限;运输不落临时仓库,也不代表 Host 没有参与下发。

专业版

概念 严格问题 不保证什么 Mooncake 对应
One-sided / RMA 一次远端读写是否要求对端 CPU 同步参与匹配操作 不保证没有 Host 发起,不保证零拷贝 HCCL TransportMem、ADXL、Fabric 映射都可表现为一边访问
Zero-copy 数据是否避免额外 bounce buffer 或 CPU staging copy 不保证没有内存注册、描述符和控制面 Direct 在满足注册与链路条件时可直传;小块或未注册内存可能走 buffer pool
Direct transfer 已注册的源/目的内存是否通过 HCCS/RDMA/SDMA 等直接搬运 不保证提交者是 AIV USE_ASCEND_DIRECT 的核心语义
VMM 物理内存、虚拟地址、映射、权限和共享 handle 是否可分别管理 不定义传输协议,也不定义完成同步 USE_UBSHMEM 的内存基础
Fabric Memory 远端或共享物理内存是否能被导出、导入并映射到参与者地址空间 不自动提供缓存一致性或任意拓扑可达性 Direct Fabric mode 与 UBShmem 都涉及
AIV 直驱 AIV Kernel 是否在 Device 侧准备并提交通信任务,绕开 Host/AICPU 高频中介 不代表 AIV 亲自搬字节,也不保证链路峰值更高 当前三条 Mooncake 路径均缺少这一证据

最常见的偷换

“对端 CPU 不参与”只能推出 one-sided;“没有中转 buffer”只能推出 zero-copy;“远端内存映射成本地 VA”只能推出 VMM/Fabric Memory;只有看到 AIV Device 代码、通信描述符/WQE/SQE 构造、doorbell 或等价提交动作,才能把控制路径认定为 AIV 直驱。

CANN VMM 双层解释

小白版:货架与地址簿

传统 aclrtMalloc 像是一次性拿到“货架 + 仓库地址”的组合。VMM 把这件事拆成多个可控制对象:

  1. 查询粒度:先问仓库一排货架最小要按多大单位租。
  2. 申请物理内存aclrtMallocPhysical 真正租下一批货架,返回的不是普通指针,而是物理内存 handle。
  3. 预留虚拟地址aclrtReserveMemAddress 在本进程地址簿里留出一段连续门牌号,此时门牌后面还没有货架。
  4. 建立映射aclrtMapMem 把门牌号绑定到物理货架。
  5. 设置权限:指定哪些 Device 可以读写这段映射。
  6. 导出凭证:把物理内存 handle 转成可跨进程或跨 Fabric 传递的 shareable handle。
  7. 远端导入:另一进程拿到凭证后恢复物理内存 handle,在自己的地址簿里预留地址并映射。

两边的虚拟地址不必相同。因此,发送端告诉接收端的不应只是一枚裸指针,而应包含:共享 handle、原始基址、长度、设备与协议属性。接收端导入后根据偏移重定位:

$$
remote_mapped_addr = local_mapping_base + (requested_addr - exported_base)
$$

一个地址为什么能指向远端内存

假设对端导出一段 1 GiB 物理内存,原始基址为 B_remote。Mooncake 请求读取其中偏移 64 MiB 的 KV block。接收端把相同物理内存导入并映射到本地虚拟基址 B_local,实际提交给 ACL copy 的地址是 B_local + 64 MiB,而不是直接使用对端进程的裸指针。

这个比喻在三个地方会失效:

  • 映射不是普通 CPU 共享内存,不应假设硬件缓存自动一致。
  • 地址可表达不等于任意节点都物理可达;拓扑、芯片、驱动和 Fabric 域仍有限制。
  • copy API 返回或入队不等于数据已经完成;必须使用 stream/event/request 等完成机制建立生命周期边界。

专业版:对象与生命周期

CANN 官方 aclrtMallocPhysical 文档明确说明:接口申请 Device 物理内存并返回 handle,可与 Reserve/Map 配合获得连续虚拟地址,也可与 Export/Import 配合实现多进程物理内存共享。Mooncake UBShmem 在此基础上增加了远端 metadata、地址重定位、worker 与完成状态。

一段 Fabric Memory 的完整生命周期可写成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
查询 allocation granularity
→ 填写 aclrtPhysicalMemProp
→ aclrtMallocPhysical 得到 physical handle
→ aclrtReserveMemAddress 得到本地 VA range
→ aclrtMapMem 建立 VA→physical 映射
→ aclrtMemSetAccess 设置访问权限
→ aclrtMemExportToShareableHandleV2 导出 Fabric handle
→ 通过 Mooncake metadata 分发 handle、base、size
→ 对端 aclrtMemImportFromShareableHandle 导入
→ 对端 Reserve + Map + SetAccess
→ 按 offset 计算 mapped remote address
→ aclrtMemcpyAsync 提交 read/write
→ 同步 stream 或检查 event 后标记 slice 成功
→ Unmap / FreeAddress / ReleasePhysical 清理

这条路径中至少有五类对象不能混为一谈:

对象 作用 生命周期错误的后果
Physical handle 代表一段实际 Device 物理内存 过早 release 会使所有映射失效
Virtual address range 当前进程的地址表达 不能跨进程直接复用裸地址;需要重定位
Shareable handle 把物理内存能力传给其他参与者 泄漏会扩大未授权访问面
ACL stream/event 建立 copy 顺序与完成边界 入队即标成功会造成上层复用或释放未完成 buffer
Mooncake segment metadata 连接协议名、engine、handle、base 与 size 过期或拓扑变化会导致错误导入、越界或不可达

PR #1399 的 review 恰好暴露了两个关键工程边界:

  1. 初版在 aclrtMemcpyAsync 入队后过早 markSuccess();review 后改为同步 stream 再标记完成。这说明 VMM 解决寻址,不能替代完成语义
  2. 导出使用 ACL_RT_VMM_EXPORT_FLAG_DISABLE_PID_VALIDATION,review 指出它可能扩大 handle 的导入范围。这说明 可共享性越强,能力凭证的分发与隔离越重要

PR #1519 增加 IPC mode,又进一步说明 Fabric 与 IPC 是 handle 类型和可达域的选择,不是单一的“共享内存开关”。PR #3214 则通过 100%、90% 逐级回退到 50% 的 best-effort 分配,说明大页对齐、连续容量和碎片会直接影响系统是否能启动。

映射关系

比喻 技术对象 对应 Mooncake 行为
物理货架 aclrtDrvMemHandle 背后的 Device physical memory Fabric allocator 申请可导出的大页物理内存
本地门牌 reserved virtual address 每个进程分别保留地址,数值不要求相同
门牌绑定货架 aclrtMapMem 使本地 VA 指向导入的本地或远端物理内存
仓库通行证 Fabric/IPC shareable handle 经 Mooncake metadata 交给对端导入
访问名单 aclrtMemSetAccess 授予目标 Device 对映射区域的访问权限
搬运单 aclrtMemcpyAsync 参数 指定 read/write 的本地地址、映射地址和长度
确认回执 stream/event/request completion 完成后才能让上层复用、释放或消费 KV block

是否属于 AIV 直驱

判定标准

本仓库已有文章 AIV Direct Drive 对概念做过完整说明。这里把判据压缩成四个可检查问题:

  1. 是否存在运行在 AIV/Vector Core 上的 Device Kernel?
  2. 通信描述符、WQE 或 SQE 是否由该 Kernel 在 Device 侧准备?
  3. 是否由 AIV 执行 doorbell 或等价提交,而不是每次回到 Host/AICPU?
  4. 完成状态是否能在 Device 侧被观察并继续推进计算/通信流水?

满足 one-sided、zero-copy、VMM 或 Fabric Memory 都不能代替这四项。

真正的对照证据可以在 CANN SHMEM 开源代码中看到。以 2026-08-25 的 dca9886a 提交为截面,SDMA Device helper 明确写有 AIV direct STARS、准备 SQE 并 ring doorbell;UDMA Device helperRDMA Device backend 则明确出现准备 WQE 与 ring doorbell。这类代码才是 AIV 直驱的强证据。

USE_ASCEND

结论:不能认定为 AIV 直驱,按 Mooncake 可见实现应归为 Host 驱动的 HCCL 低层 RMA。

调用链大致是:

1
2
3
4
5
6
Mooncake Host worker
→ 选择 slice
→ TransportMem::Write / Read
→ ACL stream
→ HCCL/transport 执行与同步
→ markSuccess

HCCL 本身支持 AIV communication engine;例如 HCCL_OP_EXPANSION_MODE=AIV 可让特定通信算子在 AI Vector Core 展开。vLLM Ascend 的调优文档 也把 AIV engine 描述为 Vector Core 直接调度 RoCE、减少 AICPU 中介。但这不能反向证明 Mooncake 的 TransportMem::Write/Read 自动走 AIV:

  • Mooncake 不是在此路径调用已声明 AIV expansion 的 AllReduce/AlltoAll 等 collective。
  • 当前源码未设置 AIV expansion mode,也未启动可见的 AIV 通信 Kernel。
  • TransportMem 内部可能随闭源库版本选择不同执行机制,但“可能”不能作为架构归类证据。

因此更严谨的说法是:HCCL path 可能复用某些与 HCCL engine 共用的底层能力,但没有证据表明它是 AIV 发起的传输。

USE_ASCEND_DIRECT

结论:不是 Mooncake 接口层的 AIV 直驱;它是 Host 调用 ADXL/HiXL 的一边直传。

1
2
3
4
5
Mooncake Host executor
→ AdxlEngine::RegisterMem / Connect
→ AdxlEngine::TransferSync / TransferAsync
→ ADXL/HiXL 内部选择 HCCS、RDMA、SDMA 或 buffer path
→ Host 查询 request 或等待完成

ADXL 的旧接口文档还明确指出,小于 256 KiB 或存在未注册内存时可能启用中转 buffer pool。这再次说明 Direct 是目标抽象,不保证每个请求在所有条件下都严格零中转

对当前上游 HiXL 源码的旁证也要谨慎解释:2026-08-25 的 499e6c33 版本中,Fabric Memory engine 默认可启用 FabricMemAicpuTransferService,Host service 路径则调用 aclrtMemcpyAsync。这说明至少当前公开实现中存在 Host 与 AICPU 展开路径,不能把 HiXL/Fabric 自动等同于 AIV。由于 Mooncake 所链接的具体 CANN/ADXL 版本可能不同,这一证据只用来否定“必然 AIV”,不能宣称所有 ADXL 内部实现永远不可能增加 AIV backend。

USE_UBSHMEM

结论:当前明确不是 AIV 直驱。

ubshmem_transport.cpp 的关键动作是:导入/映射 Fabric 或 IPC handle,计算映射后的地址,Host worker 在若干 ACL stream 上调用 aclrtMemcpyAsync,最后同步 stream 并更新 slice 状态。

1
2
3
4
5
Host metadata/import
→ CANN VMM 映射远端物理内存
→ Host 调用 aclrtMemcpyAsync(mapped_addr)
→ runtime / DMA path 搬运
→ Host stream synchronization

这里没有 CANN SHMEM Device API,没有 AIV Kernel,没有由 AIV 准备 WQE/SQE 和 ring doorbell 的代码。UBShmemTransport 这个名字也容易造成第二次误解:它使用的是 UB/Fabric Memory 语义,但当前 Mooncake 实现并不是对 CANN shmem Device 编程库的直接封装。

至于 aclrtMemcpyAsync 最终在某款芯片、某个 CANN 版本、某种映射类型下由 SDMA、HCCS 还是其他 runtime engine 完成,Mooncake 公开层没有给出足以覆盖所有组合的答案。可以确认提交者是 Host API,不能越过证据声称特定物理 engine。

最终判决

检查项 HCCL path Ascend Direct UBShmem 真正 AIV SHMEM/URMA 路径
一边远端访问
可实现零拷贝 条件满足时 条件满足时 映射后可避免传统中转
VMM/Fabric 映射 不是核心 可选 Fabric mode 是,核心机制 可以组合使用
AIV Device Kernel 可见
AIV 准备 WQE/SQE
AIV ring doorbell
AIV 直驱结论 否/无证据

性能证据

PR #1399 的带宽

PR #1399 使用 transfer-engine-bench、12 个 initiator thread、batch size 1 测 D2RD,作者给出的结果如下:

Block size Write GB/s Read GB/s
64 KiB 7.76 8.34
128 KiB 15.77 15.73
256 KiB 31.86 30.27
512 KiB 60.49 58.31
1 MiB 108.83 108.57
2 MiB 118.57 148.85
4 MiB 131.45 158.17
8 MiB 134.60 162.70
12 MiB 135.69 164.20

应使用 PR 作者原表,而不是 bot summary 中的 “199.14 GB/s”;后者与原始表格不一致。这个结果能够支持“UBShmem 在大块下达到较高吞吐”,但不能独立证明它优于 Direct,因为 PR 没有给出同环境的三后端对照,硬件拓扑、CANN/驱动版本、预热和重复次数也不充分。

PR #1591 的延迟对比

PR #1591 在单机 16 NPU 的 Store 场景中比较非 Fabric Direct、Direct Fabric、原始 UBShmem 和 stream-pool UBShmem:

Key 数量 Direct Direct Fabric UBShmem UBShmem stream pool
32 62.78 ms 21.29 ms 28.49 ms 21.10 ms
64 123.90 ms 40.86 ms 56.04 ms 41.66 ms
128 262.77 ms 78.27 ms 115.94 ms 80.22 ms
256 518.35 ms 156.23 ms 234.38 ms 164.27 ms
512 1017.84 ms 311.96 ms 463.01 ms 326.15 ms

在 512 keys 点上,Direct Fabric 相对非 Fabric Direct 约为 3.26 倍,stream-pool UBShmem 约为 3.12 倍;Direct Fabric 只比 stream-pool UBShmem 快约 **4.35%**。32 keys 时 UBShmem stream pool 甚至略快于 Direct Fabric。

由此更合理的解释是:

  1. Fabric Memory 能力本身贡献了主要差距。非 Fabric Direct 与另外两条 Fabric path 的差距最大。
  2. 并行提交与同步结构是第二个关键因素。原始 UBShmem 到 stream pool 的提升说明单 stream/串行 worker 会浪费 Fabric 带宽。
  3. UBShmem 并没有显示出“因为是 AIV 直驱而额外领先”的形状。事实上它不是 AIV 直驱,优化后的曲线与 Direct Fabric 很接近。
  4. 这是单机单 workload 证据。跨节点、不同 block size、并发租户、不同芯片和 CANN 版本仍需重新测量。

正确的 A/B 方式

如果要决定生产上是否启用 UBShmem,应在同一机器、同一 allocator、同一 KV block 分布下至少比较 ascendascend + Fabricubshmem 三组,并同时记录小块延迟、聚合带宽、CPU/AICPU/AIV 占用、内存注册时间、Fabric 大页申请成功率和错误恢复。只拿 #1399 的峰值数字与另一台机器上的 Direct 数字比较没有意义。

纵横合并后的判断

纵向看,Mooncake 的路线是:

1
2
3
复用 HCCL 低层能力解决“能不能传”
→ ADXL/HiXL 解决“如何统一支持多链路、多内存方向和异步请求”
→ VMM/Fabric Memory 解决“能否把远端内存变成可映射的专用快路”

横向看,三条路径分别占据不同抽象层:

  • HCCL path 更靠近通信库内部 transport 对象。
  • Ascend Direct 更像通用一边传输产品 API。
  • UBShmem 更靠近内存虚拟化、共享 handle 和 runtime copy。
  • AIV 直驱则位于 Device 侧控制与提交层,和前三者不是同一条横轴。

这解释了为什么项目会出现看似重叠的选项:演进不是简单地把旧类重命名,而是在不同时间把责任从 Mooncake、HCCL、ADXL/HiXL、CANN runtime 和 Fabric allocator 之间重新划分。

后续演进

以下属于判断,不是项目已宣布的 roadmap。

Direct 迁移到 HIXL 新接口

判断:中期最自然的方向是保留 Ascend Direct 用户概念,但把 Mooncake 内部从待废弃的 adxl::AdxlEngine 迁到 HIXL 新 API。

  • 成立前提:HIXL 新接口覆盖 Mooncake 所需的注册内存、异步 batch、错误码、连接恢复和 Fabric Memory。
  • 领先信号:Mooncake 出现 hixl::Hixl 头文件与对象、构建依赖不再使用 ADXL compatibility API、Direct 文档开始区分 HIXL 版本。
  • 反向信号:上游长期维护 ADXL 兼容层,Mooncake 实测迁移收益不足或新接口缺少关键异步能力。

Fabric 能力向 Direct 收敛

判断:Direct Fabric 与 stream-pool UBShmem 的性能接近、allocator 逻辑又在 PR #3214 中趋于共享,因此 Fabric Memory 未来可能更像 Direct 的 capability,而不是长期维护完全平行的 transport。

  • 成立前提:Direct 能暴露和 UBShmem 一样可控的 allocator、IPC/Fabric mode、stream 并行度和错误恢复。
  • 领先信号:构建系统不再用独立源文件 flavor,运行时根据 topology/capability 自动选择 Fabric path,ubshmem protocol 被兼容映射到 ascend
  • 反向信号:独立 VMM path 在部署体积、依赖、调优自由度或新硬件适配速度上持续明显优于通用 HIXL。

真正 AIV transport 以新后端出现

判断:如果 Mooncake 要服务算子内细粒度 KV/EP 通信,真正 AIV 直驱更可能以 CANN SHMEM/URMA/TENT/UB Device backend 或新的 Device queue 进入,而不是悄悄把现有三个开关中的某一个改名为 AIV。

  • 成立前提:Transfer Engine 能把远端地址、队列、权限和完成状态安全地交给 Device Kernel,并支持 persistent kernel 或 kernel 内批量提交。
  • 领先信号:源码出现 shmem_device_*、AIV kernel、WQE/SQE、doorbell、Device-side completion;基准重点转向小消息控制时延与通算重叠。
  • 反向信号:Mooncake 的主工作负载继续是 Host 调度的大块 KV bulk copy,Host 提交成本相对链路时间很小,额外占用 AIV 反而挤压计算资源。

AIV 直驱未必是所有 KV 传输的终点

AIV 直驱主要缩短细粒度控制路径并改善通算流水。对于数 MiB 以上的大块 KV,一次 Host 提交的固定开销可能已被数据传输时间摊薄;此时 Fabric 映射、并行 stream、批处理、拓扑路由和内存分配成功率可能比“由谁敲 doorbell”更重要。

仍待确认

  1. aclrtMemcpyAsync 的物理执行 engine:在不同 Ascend 芯片、Fabric 映射类型和 CANN 版本下究竟使用 SDMA、HCCS 还是其他路径,需要对应版本的官方实现说明或 profiler trace,不能从函数名推断。
  2. 三开关组合的正式支持矩阵:当前 CMake 表明它们基本互斥,但文档没有显式列出所有非法组合及配置时报错行为。
  3. #1399 基准环境:缺少完整芯片型号、拓扑、CANN/Driver/Lingqu、NUMA、预热、重复次数和误差条,峰值数字只适合作为开发者自测。
  4. Fabric handle 的多租户隔离DISABLE_PID_VALIDATION 的使用边界、容器隔离和 handle 分发授权需要安全设计,不应只依赖 metadata 不泄漏。
  5. ADXL 到 HIXL 的迁移时间:上游已经把 ADXL 文档标为待废弃,但 Mooncake 尚未给出公开完成日期。
  6. A2/A3/950 的能力差异:VMM API 的存在不等于 Fabric Memory transport 在所有产品上等价可用,需把 API 支持、Fabric handle 支持、跨卡拓扑和性能分别验证。
  7. 失败恢复语义:远端进程退出、handle 失效、Fabric 映射断开或 stream 超时时,上层 Store 对 segment、replica 和正在消费的 KV block 如何原子回滚,仍需结合故障注入验证。

常见误解

  1. “用了 HCCL 就是集合通信。”HCCL path 在这里主要复用低层 TransportMem 做一边读写,不是在为每个 KV block 调 AllReduce
  2. “Ascend Direct 就是 AIV Direct。”前者是传输产品/transport 名,后者是 Device 侧控制路径;Mooncake 当前 Direct 由 Host 调 ADXL。
  3. “VMM 映射后就是缓存一致的全局内存。”VMM 提供地址与物理内存映射,不自动提供 CPU 式缓存一致性、任意拓扑可达或完成顺序。
  4. “UBShmem 已经接入 CANN SHMEM Device API。”当前 Mooncake 类直接使用 CANN VMM 与 ACL copy,未出现 CANN SHMEM 的 AIV Device 调用链。

检查理解

以下问题不附答案,用于检查是否真正分清了五个维度:

  1. 一个 transport 同时满足 one-sided 和 zero-copy,但每次请求都由 Host 调用异步 API 提交,它是否属于 AIV 直驱?需要哪类新增证据才能改变结论?
  2. 为什么 aclrtMemImportFromShareableHandle 成功后仍不能直接使用导出进程的原始虚拟地址?Mooncake metadata 至少需要保留哪些字段才能正确重定位?
  3. 如果同一环境下 Direct Fabric 与 UBShmem stream pool 的延迟接近,但非 Fabric Direct 慢三倍,最应该优先验证的性能假设是什么?哪些指标能够把 Fabric 能力、并行度和提交者身份的贡献分开?

参考文献

Author

Shaojie Tan

Posted on

2026-08-25

Updated on

2026-08-25

Licensed under