跳转至

Mooncake Ascend Transports

导言

我看到 Mooncake 为 Ascend 提供了三个编译开关:USE_ASCENDUSE_ASCEND_DIRECTUSE_UBSHMEM。最直接的问题是:它们是不是三套并列的通信 engine?特别是后两个名字里已经有 DirectSHMEM,是否意味着数据传输已经由 AIV 直驱?

沿着合入 PR 和源码调用链看下去,答案逐渐清楚:这不是三套同层方案,而是 Mooncake 先后解决“能传”“通用地传”和“把远端内存映射后再传”三个问题留下的三条路径。更重要的是,按当前可见源码,三者都不能直接称为 AIV 直驱。

本文以 Mooncake main 在 2026-08-25 的提交 43365d45 为代码截面。后文沿已合入 PR、关联 Issue、Mooncake 文档、CANN API、HiXL 与 CANN SHMEM 开源代码展开,但不把不同强度的证据混在一起。

证据边界

事实由 PR、Issue、文档或源码直接支持;推断来自多处事实的合并,但项目没有直接宣告;判断用于选型和未来演进,只有在给定前提下成立。

先别急着比较开关

三个名字摆在 common.cmake 里,很容易让人把它们理解成三个可以自由叠加的后端:

USE_ASCEND         → HCCL 低层内存传输 → 先让 Ascend 能接入 Transfer Engine
USE_ASCEND_DIRECT  → ADXL/HiXL 一边引擎 → 统一多链路、多内存方向和异步请求
USE_UBSHMEM        → CANN VMM/Fabric    → 把远端物理内存映射成专用快路

但这三个箭头回答的并不是同一个问题。第一条更靠近 HCCL 内部 transport,第二条把能力收敛成通用传输 API,第三条则从传输协议进一步下沉到内存分配与映射。

构建方式也印证了这一点。Mooncake 的 common.cmake 同时声明三个开关,但 ascend_transport/CMakeLists.txt 使用 if / elseif / else 选择 HCCL、异构 HCCL、UBShmem 或 Direct 源文件;multi_transport.cpp 再把运行时协议映射到具体类。Direct 与 HCCL 都使用 ascend 协议名,只有 UBShmem 使用独立的 ubshmem

独立选项不等于可叠加

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

既然不是三条平行线,它们为什么会先后出现?要回答这个问题,最好不要从参数表开始,而是回到每一阶段遇到的具体困难。

三条路径怎样长出来

USE_ASCEND:先解决能不能传

第一阶段的约束很现实。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

因此,USE_ASCEND 虽然依赖 HCCL,却不是为每个 KV block 调一次 AllReduce。它使用的是 HCCL 的低层内存传输能力,为 Transfer Engine 暴露一边读写。

推断:这是一条最快接通既有 HCCL 软硬件生态的桥梁,代价是 Mooncake 自己需要管理较多 HCCL 低层对象、版本差异和边界条件。随着支持矩阵扩大,这套实现的维护成本会逐渐高于专门的一边传输产品接口。

PR #619 随后增加批量同步传输、Debian 支持和一批修复。PR 报告,在其测试条件下,128 KB 非连续块使用 batch 接口,相比逐次 transferSync 的带宽提升超过 100%。这说明第一阶段很快从“接通”进入了性能和可部署性修整。

USE_ASCEND_DIRECT:再解决怎样通用地传

Issue #719 把下一阶段的目标写得很具体:同时覆盖 HBM/DDR、Device RDMA、SDMA、Host RDMA、同构与 A2/A3 异构部署。这样的组合已经不适合由 Mooncake 针对每条链路分别拼装。

PR #740 因此引入 Ascend Direct,把接口收敛为一条更稳定的生命周期:

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 提交起点、终点和长度,ADXL/HiXL 负责处理 HCCS、RDMA、SDMA 或中转 buffer 等具体路径。

随后,PR #764PR #856 分别处理 ADXL 错误码、CANN 版本与 TCP 端口问题。HiXL 开源后,Mooncake 又通过 PR #1037PR #1049 短暂引入 hixl transport 名称,再改回面向用户的 Ascend Direct

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

USE_UBSHMEM:再把问题下沉到内存语义

通用一边传输仍然遵循一个熟悉的模型:注册本地和远端内存,然后提交一条同时包含两端地址的传输描述符。Fabric Memory 想再往前走一步——让远端物理内存先被导出和映射,之后本地代码可以用映射地址表达远端读写。

远端物理内存
    → 导出 Fabric shareable handle
    → 本地导入 handle
    → 映射到本地保留的虚拟地址
    → 对映射地址提交 read/write

PR #1170 先让 Store 的 Ascend Direct 支持 Fabric Memory 模式。Issue #1312 随后把目标描述为基于 CANN VMM API 的 “NVLink-like Transport”,作为 Ascend Direct 的补充;PR #1399 最终把它实现为独立的 UBShmemTransportUSE_UBSHMEM 开关。

这里的 “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 的批量传输。

PR #1519 又增加 MC_USE_UBSHMEM_IPC=1、Fabric allocator 和 Python NPU pluggable allocator,把能力扩展到同机跨进程 IPC。PR #3214 则用 100%、90% 一直回退到 50% 的 best-effort 分配改善启动成功率,并处理 1 GiB 对齐问题。

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

走到这里,三条路径的演进关系已经形成:

HCCL 低层能力解决“能不能传”
    → ADXL/HiXL 解决“怎样统一地传”
    → VMM/Fabric Memory 解决“能否先映射远端内存,再走专用快路”

下一步需要停下来解释 VMM。否则,UBShmem 很容易被误读成“远端地址已经像本地指针一样可用”,进而又被误读成 AIV 直驱。

CANN VMM 到底做了什么

先用货架理解

传统 aclrtMalloc 像是一次性拿到“货架 + 仓库地址”的组合。VMM 把它拆成多个可分别管理的对象:

  1. 查询粒度:先确认物理内存最小按多大单位申请。
  2. 申请物理内存aclrtMallocPhysical 真正获得物理内存,返回的是 handle,不是普通指针。
  3. 预留虚拟地址aclrtReserveMemAddress 在当前进程留下连续地址,此时地址后面还没有内存。
  4. 建立映射aclrtMapMem 把虚拟地址绑定到物理内存。
  5. 设置权限:指定哪些 Device 可以访问这段映射。
  6. 导出凭证:把物理内存 handle 转成跨进程或跨 Fabric 传递的 shareable handle。
  7. 远端导入:另一进程恢复 handle,在自己的地址空间重新 Reserve、Map 和 SetAccess。

可以继续用两个仓库来理解其他容易混淆的术语:

  • One-sided / RMA:A 仓库发出“把货放到 B 的 3 号货架”,不要求 B 的管理员同步调用一次 recv
  • Zero-copy:货物尽量从源货架直接运到目标货架,中间不再落到临时仓库倒一次。
  • Direct transport:运输公司根据条件选择内部高速通道或跨园区道路,用户只提交起点、终点和长度。
  • Fabric Memory:B 把某些货架通过共享凭证开放给 A,A 在自己的地址簿里为它们安排地址。
  • AIV 直驱:A 的现场工人自己填写硬件能识别的工作单并提交,不必为每一批货回到 Host/AICPU 调度员。

这五件事可以组合,却不互相蕴含。货架出现在本地地址簿里,不代表 AIV 获得了提交通信任务的权限;数据没有经过中转 buffer,也不代表 Host 没有参与下发。

地址为什么需要重定位

两边的虚拟地址不必相同。因此,发送端告诉接收端的不能只是一枚裸指针,而应包含共享 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 的完整生命周期是:

查询 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 的导入范围。共享能力越强,凭证分发与隔离越重要。

把类比和真实对象对齐后,关系如下:

比喻 技术对象 对应 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

VMM 的责任到这里就结束了:它让一段物理内存可以被分配、共享和映射,却没有回答“谁来提交通信任务”。这正是 AIV 直驱要回答的另一个问题。

Direct 为什么不等于 AIV 直驱

Direct 之所以容易误导,是因为它同时出现在数据路径和控制路径的讨论里。真正的分界线其实只有一个:谁在提交通信任务。把术语放在同一张坐标表中,会更容易看清它们各自保证什么:

概念 它真正回答的问题 它不保证什么 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 侧准备并提交通信任务 不代表 AIV 亲自搬字节,也不保证峰值带宽更高 当前三条 Mooncake 路径均缺少这一证据

判断 AIV 直驱,可以检查四件事:

  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 直驱的强证据。更完整的概念说明可参考 AIV Direct Drive

HCCL 路径

Mooncake 的可见调用链是:

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?因为 Mooncake 在这条路径中没有调用已声明 AIV expansion 的 AllReduce/AlltoAll 等 collective,也没有设置可见的 AIV expansion mode 或启动 AIV 通信 Kernel。TransportMem 内部可能随闭源库版本选择不同机制,但“可能”不能作为架构归类的证据。

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

Ascend Direct 路径

Mooncake 的调用链是:

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。

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

UBShmem 路径

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

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。

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

三条路径放在同一套判据下,结果如下:

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

性能数字能说明什么

#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/驱动版本、预热和重复次数也不充分。

#1591:Fabric 与并行度才是主变量

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. 结果没有呈现“因为 AIV 直驱而额外领先”的形状。UBShmem 事实上不是 AIV 直驱,优化后的曲线与 Direct Fabric 很接近。
  4. 证据只覆盖单机单 workload。跨节点、不同 block size、并发租户、芯片和 CANN 版本仍需重新测量。

换句话说,这些性能数据更支持“Fabric Memory + 并行度”的解释,而不是“AIV 直驱”的解释。

实际应该怎样选择

理解演进和 AIV 判据后,再做横向比较就不会只盯着名字:

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

落到部署选择,可以按问题而不是按名字判断:

  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 机器上工作的通用共享内存。

如何做同条件 A/B

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

证据还缺在哪里

现在仍有七个问题不能从现有材料中确定:

  1. aclrtMemcpyAsync 的物理执行 engine:在不同芯片、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 做原子回滚,仍需故障注入验证。

回到最初的问题

现在可以重新回答开头的两个问题。

USE_ASCENDUSE_ASCEND_DIRECTUSE_UBSHMEM 不是三个并列的 HCCL engine,而是三次能力下沉留下的路径:HCCL 先解决可用性,ADXL/HiXL 收敛通用直传,CANN VMM/Fabric Memory 再提供专用映射快路。它们的配置入口独立,当前构建产物却基本按 flavor 二选一。

它们也都不能仅凭 one-sided、zero-copy、Direct 或远端内存映射,被称为 AIV 直驱。当前能看到的是 Host worker、AdxlEngine::Transfer*aclrtMemcpyAsync;真正改变结论所需的证据,是 AIV Device Kernel 准备 WQE/SQE、提交 doorbell 并在 Device 侧推进完成状态。

至于底层 runtime 在特定芯片和 CANN 版本中最终选择哪种物理搬运 engine,现有公开材料还不能覆盖所有组合。部署时最稳妥的做法仍然是:新环境优先验证 Ascend Direct,Fabric 域内再对 Direct Fabric 与 UBShmem 做同条件 A/B;如果目标真的是算子内 AIV 发起通信,就把它当成另一项独立设计,而不是从这三个开关的名字反推。

附录:完整时间线

主线只保留了推动架构变化的节点。完整合入过程如下:

时间 事件 直接变化 动机与意义
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 曾引入 hixl transport 名称,随后改回 Ascend Direct 底层产品向 HiXL 演进,对外名称保持稳定
2025-12-05 至 12-27 PR #1170 合入 Store 的 Ascend Direct 支持 Fabric Memory 模式与特殊 Host 分配 Fabric Memory 先作为 Direct 的能力进入 Store,早于独立 UBShmem
2025-12-31 Issue #1312 提出 建议用 CANN VMM 支持 Fabric Memory,作为 Direct 的 NVLink-like 补充 目标下沉到远端内存可映射的内存语义
2026-01-18 至 01-26 PR #1399 合入 新增 USE_UBSHMEM、VMM Fabric handle 与准确性测试 Fabric Memory 成为独立协议和专用数据路径
2026-02-09 至 02-14 PR #1519 合入 增加 IPC mode、Fabric allocator 和 Python NPU allocator 扩展到同机跨进程,并解决上层怎样获得可共享内存
2026-03-02 PR #1591 合入 8 个 worker、每请求 4 个 stream;接入 Store 修补串行同步和单 stream 的并行度不足
2026-07 至 08-05 PR #3214 合入 Fabric 内存从 100% 逐步回退到 50%,1 GiB 对齐,优先 ADXL 分配 处理大页粒度、连续容量、碎片和启动成功率

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

附录:可能的演进

以下都是判断,不是 Mooncake 已经宣布的 roadmap。

Direct 迁移到 HIXL 新接口

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

  • 成立前提:HIXL 新接口覆盖注册内存、异步 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 直驱未必是终点

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

附录:误解与自检

四个常见误解可以作为快速检查:

  1. “用了 HCCL 就是集合通信。”这里主要复用 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 能力、并行度和提交者身份的贡献分开?

参考文献

评论