TileXR-SHMEM Abstractions
核心结论
先把两层的职责压缩成一句话:
- TileXR 封装怎样组织一次算子通信:rank/topology、IPC 共享窗口、设备侧
CommArgs、flag 同步,以及 AllGather 与计算融合的 kernel/tiling。 - cann/shmem 封装怎样访问另一个 PE 的对称内存:初始化、对称堆、team、RMA/AMO、signal/wait、quiet/fence、barrier/sync,以及 MTE、SDMA、RDMA、UDMA 的路由与资源生命周期。
两者当前不能合并成一层:
- TileXR 的独立
all_gather使用自己的peerMems + SyncCollectives;all_gather_add与all_gather_matmul使用 HCCL/MC2。固定树的src/mc2中没有shmem或UDMA调用。 - TileXR 的 gitlink 指向 LingquLab/shmem
b79bda38,并非 cann/shmem main382afa08。 - TileXR
InitUDMA调用自定义aclshmemx_get_udma_info;该符号在固定 fork 和 cann/shmem main 的include/、src/中都不存在。 - TileXR 的
tilexr_udma.h还引用不存在的头文件、CommArgs不存在的字段和 SHMEM 不存在的 C++ namespace API。它只能算未接通的 AICore 内联适配草案,不能作为“当前直接兼容”的证据。
TileXR:算子层封装
通信器与设备描述块
TileXRComm 是 host 侧资源管理中心。它不可复制,持有 global/local rank、socket exchange、通信窗口、host/device 两份 CommArgs 和 UDMA 相关指针。普通初始化链为:
1 | TileXRComm::Init |
GetDev 收集设备 ID 并推导 local rank;InitCommon 把芯片与 topology 能力编码进 extraFlag;InitCommMem 为每个 rank 分配本地 HBM 窗口、交换 IPC 信息并打开 peer mapping;最后把下面的 POD 描述块复制到 device。源码还显示两个边界:PCIe topology 只接受不超过两卡,thread init 明确跳过 UDMA。[^t-init]
1 | struct CommArgs { |
源码:TileXR 46c58f3d,src/include/comm_args.h:85-102,CommArgs。[^t-commargs]
这个结构说明 TileXR 暴露给 kernel 的核心不是“SHMEM handle”,而是拓扑元数据、peer window 地址和同步/调试状态的扁平描述块。默认窗口由 200 MiB 数据区与 4 MiB flag 区组成,每 rank 204 MiB;peerMems 固定容量对应最大 128 ranks。[^t-limits]
资源回收的意图是关闭 peer IPC mapping、释放本地窗口、host/device CommArgs 并终结可选 SHMEM 实例。但固定代码的 UDMA ownership 协议存在静态矛盾:wrapper destroy 会 finalize 并 aclrtFree(commArgs->udmaInfoPtr),TileXRComm 析构又根据成员 udmaInfoDev_ finalize;同时公开头声明 LcclCommDestroy,实现定义的是 TileXRCommDestroy。没有链接产物和运行日志,本文不推断具体故障,只把它列为待修 ABI/生命周期缺口。[^t-destroy]
三个实际算子,不是一个 transport
固定 revision 中能从目录、host API 与 kernel 共同确认的 MC2 算子只有三个:
| 算子 | 用户 API | 实际通信对象 | 计算关系 |
|---|---|---|---|
all_gather |
aclnnAllGatherGetWorkspaceSize + aclnnAllGather |
CommArgs.peerMems、IPC 共享窗口、SyncCollectives |
纯 AllGather |
all_gather_add |
aclnnAllGatherAddGetWorkspaceSize + aclnnAllGatherAdd |
Hccl<HCCL_SERVER_TYPE_AICPU> |
AllGather 后逐轮 Add |
all_gather_matmul |
aclnnAllGatherMatmulGetWorkspaceSize + aclnnAllGatherMatmul |
HCCL tiled AllGather | AllGather 与 Matmul 流水融合 |
三者都采用 ACLNN 的 workspace/executor 两阶段 host API,但 kernel 内部不是同一种通信实现。TileXRType 枚举还列出更多 collective/fused 名称,枚举不能当成交付算子集。[^t-api]
独立 all_gather 的 host wrapper 取出 device CommArgs pointer,tiling 将它写入 commDataPtr。kernel 初始化时读取 local rank 与 peerMems,为每个 peer 计算 ping-pong window 地址,再初始化 SyncCollectives。一次核心搬运是:输入写入本 rank 的共享窗口,写 flag 并等待目标 rank,最后从目标窗口拷到输出。
1 | // step1:拷贝input至共享内存 |
源码:TileXR 46c58f3d,src/mc2/all_gather/op_kernel/all_gather.h:228-249,AllGather::Process。[^t-allgather]
这里的 SyncCollectives 是 TileXR 自己的 peer-window flag 协议:它把各 rank 窗口的 flag 区绑定成地址,用 magic/value packed flag 执行 set/wait。它不是 cann/shmem team barrier 的别名。[^t-sync]
all_gather_add 与 all_gather_matmul 则持有 HCCL device object。后者使用 template 参数表示输入/输出、bias 与 full-mesh/format 策略,通过宏实例化具体 kernel class:
1 | classDiagram |
AllGatherPlusMM : OneCalcOneCommBase 是 host tiling/性能模型扩展点;新增 dtype、bias 或 full-mesh 策略主要通过 OpDef、tiling class、kernel template 和 dispatch 宏完成。它不是 runtime transport plugin。固定树的 all_gather_matmul 还引用不存在的 all_gather_matmul_v2 目录;没有完整构建日志,本文只能标记为固定 revision 的源码缺口。[^t-matmul]
TileXR 与 SHMEM 的 ABI 断点
TileXR 的 InitUDMA 展示了清晰的设计意图:生成 SHMEM UID、经 socket AllGather 广播、请求 UDMA engine,再把 SHMEM 返回的设备信息指针塞入 CommArgs。失败路径全部返回 TileXR success,意图是让 UDMA 不可用时降级。
1 | // Step 5: 从 shmem 获取 UDMA 信息(设备侧指针) |
源码:TileXR 46c58f3d,src/comm/tilexr_comm.cpp:170-189,TileXRComm::InitUDMA。[^t-udma-init]
但固定源码在这里断开:
.gitmodules指向 LingquLab/shmem,git tree 固定 gitlinkb79bda38;不是 cann/shmem main382afa08。aclshmemx_get_udma_info在这两个 SHMEM revision 的include/、src/均无定义或声明。main 内部虽有TransportDeviceInfo.udmaInfoAddress,但没有 public getter ABI。- TileXR 的
tilexr_udma.h包含不存在的shmem/include/device/udma.h;固定 SHMEM 的 UDMA API 位于device/gm2gm/engine/shmem_device_udma.h,名称为全局aclshmemx_udma_*。 - 该 wrapper 读取
CommArgs不存在的udma_enabled、peer_mem_ptrs、peer_flag_ptrs,并调用不存在的shmem::udma_*。 - 全仓没有 kernel 包含
tilexr_udma.h,三个src/mc2算子也没有 SHMEM/UDMA 调用。
下面 23 行足以复现其中两个接口矛盾:
1 | __aicore__ inline bool UDMAEnabled(const CommArgs& args) { |
源码:TileXR 46c58f3d,src/include/tilexr_udma.h:32-54。与同 revision 的 src/include/comm_args.h:85-102 及两个 SHMEM 固定树交叉核对。[^t-udma-wrapper]
cann/shmem:对称内存运行时
PE、对称堆与 team
SHMEM 的直观模型不是“发一条消息”,而是多个 PE(processing elements) 共同初始化一块布局一致的对称内存域:
- 每个 PE 有全局编号,并拥有自己的 local symmetric heap。
- 相同 collective allocation 序列让对象在各 PE 上具有可翻译的对称关系。
- RMA/AMO 指定本地地址、目标 PE 与操作;runtime 根据 peer heap base、topology 和 engine state 找到实际路径。
- team 把 world 切成 PE 子集,为 team 内 PE 映射和同步提供对象。
聚合头本身就显示它封装的是一套 primitive runtime,而非融合算子:
1 |
源码:cann/shmem 382afa08,include/shmem.h:15-29。[^s-api]
公开 API 可以按对象分组:
| 对象 | 主要 API | 语义边界 |
|---|---|---|
| runtime/instance | UID、init attr、user-buffer init、finalize、instance context | collective 初始化;多个 PE 的参数必须一致 |
| symmetric heap | malloc/calloc/align/free、heap base、user-buffer pointer translation |
runtime 管理的对称分配域 |
| RMA | put/get、NBI、strided、scalar | 目标 operand 必须满足对称内存规则 |
| AMO | add/inc、bitwise、fetch/set/swap/CAS | 面向远端 PE 的原子更新 |
| signal/order | put-with-signal、wait/test、quiet/fence | 数据可见性、完成与顺序 |
| team/sync | split、2D split、translate、destroy、barrier/sync | PE 子集与 collective synchronization |
| explicit engines | MTE、SDMA、RDMA、UDMA、UB↔GM | 绕过或细化默认路由的设备 API |
Python 高层 facade 只覆盖 UID init/finalize、buffer、peer buffer、put/get/signal/wait/quiet,而且其 RMA 文档标记为 MTE-only;不能把 C++/AICore 的 team、多 transport 能力直接投射到 Python API。[^s-python]
初始化与资源管理
host 侧不是单个全局裸指针,而是 per-instance context:它聚合 host/device state、bootstrap、heap/memory managers、exception context 和实例映射。初始化大致执行:
1 | aclshmemx_init_attr |
固定实现对部分初始化失败使用 scope guard 逆序释放资源:
1 | auto init_abort_guard = shm::utils::make_scope_guard(static_cast<void*>(nullptr), [&](void*) { |
源码:cann/shmem 382afa08,src/host/init/shmem_init.cpp:922-940,aclshmemi_init_attr_impl。[^s-init]
正常 finalize 以 barrier 为边界,依次释放 team、signal、memory manager、heap/entity/device state、stream 与 bootstrap;最后一个实例才清理共享 backend 和进程级 QP 状态。这里的“对称”不仅描述地址,还约束多 PE 的初始化、分配和释放顺序。[^s-finalize]
transport 组合与自动路由
TransportManager 是内部多态生命周期接口,负责 open/close、register/unregister、reachability 和 device info。factory 根据编译能力与 init options 选择 SDMA、HCCP(RDMA)、UDMA;多个 transport 用 CompositeTransportManager 组合:
1 | std::shared_ptr<TransportManager> TransportManager::CreateForDataOpType(uint32_t dataOpType) |
源码:cann/shmem 382afa08,src/host/transport/transport_manager.cpp:48-68。[^s-transport]
Composite 正向 open/register,失败时回滚,close/unregister 逆序。不过它不是公开的 runtime transport plugin:新增 transport 仍需修改 enum、factory/编译条件、reachability、device state/address translation 和 AICore dispatch。
1 | classDiagram |
设备侧默认 RMA 读取 global state 与目标 PE 的 topology,固定优先级是 SDMA → UDMA → MTE → RoCE。blocking 版本在选中的 engine 后执行 quiet;NBI 版本把完成责任留给后续 quiet/fence/signal 协议。
1 | ACLSHMEM_DEVICE void aclshmem_getmem(__gm__ void* dst, __gm__ void* src, uint32_t elem_size, int32_t pe) |
源码:cann/shmem 382afa08,src/device/gm2gm/shmem_device_rma.hpp:108-125;后续 126-143 是 MTE 与 RoCE 分支。[^s-routing]
RMA 公共契约要求远端 operand 属于 symmetric allocation;启用 RDMA 时,两个 operand 都必须在 symmetric allocations 中,并限制对同一 PE 的 RMA/AMO 并发。也就是说,transport 能力不会取消内存语义约束。[^s-rma-contract]
同步语义
需要区分三组概念:
- signal/wait/test:围绕地址值建立生产者—消费者条件。
- quiet/fence:管理调用域内未完成通信的完成和顺序;CPU 与 NPU domain 相互独立。固定硬件实现中
fence当前与quiet同实现。 - team sync/barrier:面向 PE 子集的 collective synchronization。公开契约中 barrier 强于 sync,但固定 host 实现让 sync 调 barrier,device 侧二者也进入同一
aclshmemi_sync。
最后一点不表示两个 API 名称可以随意混用;它只说明在 382afa08 上,不能从名称推断两条不同的成本路径。TileXR 的 window flag 同步也不能替换成这个结论。[^s-sync]
横向对比
| 维度 | TileXR 46c58f3d |
cann/shmem 382afa08 |
|---|---|---|
| 抽象中心 | 通信器、peer window、kernel tiling、融合算子 | PE、对称堆、team、单边原语 |
| 用户入口 | TileXR comm C API、三组 ACLNN API | C/C++ host API、AICore device API、有限 Python facade |
| 数据定位 | CommArgs.peerMems[rank] + offset |
symmetric operand + target PE,经 peer heap/topology 翻译 |
| 实际通信路径 | 独立 AG:IPC window;AG+Add/AG+MM:HCCL/MC2 | MTE/SDMA/RDMA/UDMA 自动路由或显式 engine API |
| 同步 | TileXR packed flags,或 HCCL wait | signal/wait、quiet/fence、team sync/barrier |
| 资源管理 | 每通信器窗口、IPC mapping、CommArgs;UDMA ownership 尚有静态矛盾 | per-instance context、回滚 guard、heap/entity/transport/team/signal 生命周期 |
| 扩展点 | OpDef、tiling class、kernel template/dispatch、communicator flags | primitive API、team/heap、transport factory、reachability、device dispatch |
| 固定限制 | 128 ranks;204 MiB/rank 默认窗口;PCIe 两卡;thread init 无 UDMA | 16384 PEs、2048 teams、40 GiB local symmetric memory、1–32 QPs;engine 受 SoC/构建限制 |
当前 quickstart 支持矩阵把 UDMA 限在 Ascend 950,设备实现又以 NPU arch 3510 编译条件保护。这个平台边界只适用于 382afa08,不能反推 TileXR fork 的私有分支能力。[^s-platform]
性能与验证边界
本文不引用性能数字。一个可迁移的带宽、时延或加速比至少要同时给出:
- 硬件型号、卡数和互联 topology;
- TileXR、SHMEM、CANN 的 revision/版本;
- 模型,或 dtype、tensor shape、消息大小与并发方式;
- baseline 库、算法和配置;
- warmup、重复次数、统计指标与计时边界。
本轮没有取得同时满足这五项且与本职责直接相关的固定测量记录,也没有硬件复测。仓库中的示例和 benchmark harness 只能证明“有测试入口”,不能证明某一 transport 或融合算子在任意场景更快。
仍未解决的证据缺口是:
aclshmemx_get_udma_info的真实来源未知;固定 fork 与 main 均未实现。- TileXR UDMA wrapper 的 header、字段、命名空间 API 和消费 kernel 未闭合。
- destroy C ABI 与 UDMA ownership/finalize 协议的运行后果未验证。
all_gather_matmul_v2固定树依赖缺失,没有完整构建产物解释其来源。- 没有多卡硬件结果验证 IPC、HCCL、SHMEM transport routing 和同步成本。
因此,最稳妥的架构判断是:TileXR 与 SHMEM 分别解决算子编排和对称内存通信;它们有潜在衔接点,但固定 revision 的衔接 ABI 尚未成立。
固定源码锚点
[^t-init]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,src/comm/tilexr_comm.cpp:231-259,287-453,InitCommon、Init、InitThread、EnablePeerAccess。
[^t-commargs]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,src/include/comm_args.h:69-102,ExtraFlag、CommArgs。
[^t-limits]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,src/include/tilexr_types.h:27-30;src/include/comm_args.h:91。
[^t-destroy]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,src/include/tilexr_api.h:19-45,src/comm/comm_wrap.cpp:222-238,src/comm/tilexr_comm.cpp:720-746。
[^t-api]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,src/mc2/{all_gather,all_gather_add,all_gather_matmul}/op_host/op_api/*.h;src/include/tilexr_types.h:64-122。固定 src/mc2 执行 rg -n 'UDMA|udma|shmem' 无命中。
[^t-allgather]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,src/mc2/all_gather/op_kernel/all_gather.h:43-172,223-250,AllGather<T>。
[^t-sync]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,src/include/tilexr_sync.h:28-105,190-394,SyncCollectives。
[^t-matmul]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,src/mc2/all_gather_matmul/op_kernel/all_gather_matmul_base.h:32-55、all_gather_matmul_full_mesh.h:26-147、all_gather_matmul.cpp:29-80;op_host/op_tiling/all_gather_formulaic_tiling.h:29-60;op_host/op_api/aclnn_all_gather_matmul.cpp:11-12。
[^t-udma-init]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,src/comm/tilexr_comm.cpp:123-190,TileXRComm::InitUDMA。
[^t-udma-wrapper]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c,.gitmodules:10-13;gitlink b79bda38953d39e88b191e7805659298f0829d73;src/include/tilexr_udma.h:9-114。LingquLab/shmem b79bda3 和 cann/shmem 382afa0 的 include/、src/ 对 aclshmemx_get_udma_info 均无命中;fork 的实际 UDMA 入口见 include/device/gm2gm/engine/shmem_device_udma.h:54-114。
[^s-api]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efcc,include/shmem.h:15-50。
[^s-python]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efcc,src/python/shmem/core/init_final.py:19-112、memory.py:18-77、rma.py:19-206。
[^s-init]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efcc,src/host/init/shmem_init.cpp:895-1042,aclshmemi_init_attr_impl。
[^s-finalize]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efcc,src/host/init/shmem_init.cpp:1066-1173。
[^s-transport]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efcc,src/host/transport/transport_manager.h:21-99,transport_manager.cpp:27-69,composite_transport_manager.cpp:48-106。
[^s-routing]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efcc,src/device/gm2gm/shmem_device_rma.hpp:22-30,90-145,612-644,747-779。
[^s-rma-contract]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efcc,include/device/gm2gm/shmem_device_rma.h:154-172。
[^s-sync]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efcc,include/host/data_plane/shmem_host_cc.h:28-83、include/device/gm2gm/shmem_device_cc.h:47-124、src/host/data_plane/shmem_host_cc.cpp:18-61、src/device/gm2gm/shmemi_device_cc.h:489-502,632-646;memory order 见 include/device/gm2gm/shmem_device_mo.h:23-48。
[^s-platform]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efcc,docs/quickstart.md:56-65,CMakeLists.txt:207-268,src/device/gm2gm/engine/shmem_device_udma.hpp:22-26。