TileXR-SHMEM Abstractions

导言

TileXR 和 cann/shmem 都涉及昇腾设备间通信,但它们封装的不是同一层对象。TileXR 面向通信器、共享窗口和融合算子;cann/shmem 面向 PE、对称堆与单边通信原语。把二者简单画成一条“TileXR 调 SHMEM”的直线,会掩盖 TileXR 三个实际 MC2 算子的不同通信路径,也会忽略其固定 SHMEM fork 与 cann/shmem main 之间尚未闭合的 ABI。

本文只依据三个固定源码状态:TileXR 46c58f3d、它的 SHMEM gitlink b79bda38、cann/shmem main 382afa08。没有 Ascend 硬件与完整 CANN 构建验证,因此“源码存在”“设计意图”和“可编译运行”会严格分开。

核心结论

先把两层的职责压缩成一句话:

  • 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 的路由与资源生命周期。

两者当前不能合并成一层:

  1. TileXR 的独立 all_gather 使用自己的 peerMems + SyncCollectivesall_gather_addall_gather_matmul 使用 HCCL/MC2。固定树的 src/mc2 中没有 shmemUDMA 调用。
  2. TileXR 的 gitlink 指向 LingquLab/shmem b79bda38,并非 cann/shmem main 382afa08
  3. TileXR InitUDMA 调用自定义 aclshmemx_get_udma_info;该符号在固定 fork 和 cann/shmem main 的 include/src/ 中都不存在。
  4. TileXR 的 tilexr_udma.h 还引用不存在的头文件、CommArgs 不存在的字段和 SHMEM 不存在的 C++ namespace API。它只能算未接通的 AICore 内联适配草案,不能作为“当前直接兼容”的证据。

不要混成同一层

TileXR 的算子通信契约与 SHMEM 的对称内存契约可以在设计上组合,但固定源码没有证明这种组合已经闭合。下图中的虚线表示“意图或依赖声明”,不是已验证调用链。

![TileXR 与 SHMEM 分层设计和类图](https://pic.shaojiemike.top/shaojiemike/2026/08/bda051f00501c3c4f521f5e23b58be81.png){ width=100% }
自绘技术图:上半部区分 TileXR public API、runtime 与其固定 SHMEM fork;下半部给出 `TileXRCommPtr`、`TileXRComm`、`CommArgs` 和设备侧 UDMA 门面的对象关系。紫色虚线表示固定依赖或消费关系,不代表与 cann/shmem main 的 ABI 已闭合。

TileXR:算子层封装

通信器与设备描述块

TileXRComm 是 host 侧资源管理中心。它不可复制,持有 global/local rank、socket exchange、通信窗口、host/device 两份 CommArgs 和 UDMA 相关指针。普通初始化链为:

1
2
3
4
5
6
TileXRComm::Init
→ GetDev
→ InitCommon
→ InitCommMem
→ InitUDMA
→ SyncCommArgs

GetDev 收集设备 ID 并推导 local rank;InitCommon 把芯片与 topology 能力编码进 extraFlagInitCommMem 为每个 rank 分配本地 HBM 窗口、交换 IPC 信息并打开 peer mapping;最后把下面的 POD 描述块复制到 device。源码还显示两个边界:PCIe topology 只接受不超过两卡,thread init 明确跳过 UDMA。[^t-init]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct CommArgs {
int rank = 0; // attr rank_id, global rank
int localRank = -1;
int rankSize = 0; // global rank size
int localRankSize = -1; // 此参数是指fullmesh互联的卡数
uint32_t extraFlag = 0; // 32 bit map,具体每一位的含义就在此文件正上方
GM_ADDR peerMems[TILEXR_MAX_RANK_SIZE] = {}; // 传入初始化获得的buff,所有allreduce都是同一个参数
/**
* @param sendCountMatrix 大小是rankSize*rankSize的一维数组
* eg: sendCountMatrix[1] 的数值,对应二维数组的[0][1],表示 卡0 要给 卡1 发送的数据个数
*/
int64_t sendCountMatrix[TILEXR_MAX_RANK_SIZE * TILEXR_MAX_RANK_SIZE] = {}; // for all2allv
int64_t dfx[DFX_COUNT] = {};
GM_ADDR dumpAddr = nullptr;
int32_t magics[TILEXR_MAX_RANK_SIZE] = {0};
uint64_t fftsVal = 0;
GM_ADDR udmaInfoPtr = nullptr; // device-side ACLSHMEMAIVUDMAInfo*; nullptr 表示 UDMA 不可用
};

源码:TileXR 46c58f3dsrc/include/comm_args.h:85-102CommArgs。[^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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// step1:拷贝input至共享内存
shareGm.SetGlobalBuffer((__gm__ T*)(shareAddrs[rankId] + baseOffsetSize) + offsetToShare, countToShare);
if (countToShare > 0) {
CopyGM2GM(shareGm, inputAGM, countToShare);
}

// 卡内同步,确保数据已拷贝至共享内存
sync.SetInnerFlag(magic, STEP1); // 当前rank当前核的数据搬运已完成
sync.WaitRankInnerFlag(magic, STEP1, blockRank); // 等待目标rank的数据全部搬运完成
// step2:拷贝共享内存至output
// if (rankId == 1 && blockIdx == 0) {
// AscendC::DumpTensor(shareGm[0], 6541000 + rankId * 10 + blockIdx, 64);
// }
if (blockIdx >= useCoreNumToOutput) {
// 不用的核直接退出
return;
}
shareGm.SetGlobalBuffer((__gm__ T*)(shareAddrs[blockRank] + baseOffsetSize) + offsetFromShare,
countToOutput);
if (countToOutput > 0) {
CopyGM2GM(gatherOutGM, shareGm, countToOutput);
}

源码:TileXR 46c58f3dsrc/mc2/all_gather/op_kernel/all_gather.h:228-249AllGather::Process。[^t-allgather]

这里的 SyncCollectives 是 TileXR 自己的 peer-window flag 协议:它把各 rank 窗口的 flag 区绑定成地址,用 magic/value packed flag 执行 set/wait。它不是 cann/shmem team barrier 的别名。[^t-sync]

all_gather_addall_gather_matmul 则持有 HCCL device object。后者使用 template 参数表示输入/输出、bias 与 full-mesh/format 策略,通过宏实例化具体 kernel class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
classDiagram
class TileXRComm {
-rank_
-rankSize_
-socketExchange_
-commMem_
-commArgs_
-commArgsDev_
-udmaInfoDev_
+Init()
+InitThread()
+SyncCommArgs()
}
class CommArgs {
+rank
+localRank
+peerMems[128]
+extraFlag
+udmaInfoPtr
}
class SyncCollectives~T~ {
+Init()
+SetInnerFlag()
+WaitRankInnerFlag()
}
class AllGather~T~ {
+Init()
+Process()
}
class AllGatherMatmulBase~A_B_C_Bias_Flags~
class AllGatherMatmulFullMesh~A_B_C_Bias_Flags~ {
-Hccl hccl_
+Init()
+Process()
+HcclPrepare()
}
TileXRComm *-- CommArgs
AllGather --> CommArgs
AllGather *-- SyncCollectives
AllGatherMatmulFullMesh --|> AllGatherMatmulBase

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Step 5: 从 shmem 获取 UDMA 信息(设备侧指针)
void* udmaInfoPtr = nullptr;
size_t udmaInfoSize = 0;
ret = aclshmemx_get_udma_info(&udmaInfoPtr, &udmaInfoSize);
if (ret != ACLSHMEM_SUCCESS || udmaInfoPtr == nullptr) {
MKI_LOG(WARN) << "aclshmemx_get_udma_info failed: " << ret << ", UDMA disabled";
aclshmem_finalize();
return TILEXR_SUCCESS; // 优雅降级
}

// Step 6: 直接使用 shmem 返回的设备侧指针
// 注意:udmaInfoPtr 已经是设备内存地址,无需再次拷贝
udmaInfoDev_ = reinterpret_cast<uint8_t*>(udmaInfoPtr);

// Step 7: 设置 commArgs_ 字段
commArgs_.udmaInfoPtr = udmaInfoDev_;
commArgs_.extraFlag |= ExtraFlag::UDMA;

MKI_LOG(INFO) << "InitUDMA success, rank " << rank_ << "/" << rankSize_;
return TILEXR_SUCCESS;

源码:TileXR 46c58f3dsrc/comm/tilexr_comm.cpp:170-189TileXRComm::InitUDMA。[^t-udma-init]

但固定源码在这里断开:

  • .gitmodules 指向 LingquLab/shmem,git tree 固定 gitlink b79bda38;不是 cann/shmem main 382afa08
  • 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_enabledpeer_mem_ptrspeer_flag_ptrs,并调用不存在的 shmem::udma_*
  • 全仓没有 kernel 包含 tilexr_udma.h,三个 src/mc2 算子也没有 SHMEM/UDMA 调用。

下面 23 行足以复现其中两个接口矛盾:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
__aicore__ inline bool UDMAEnabled(const CommArgs& args) {
return args.udma_enabled != 0;
}

/**
* @brief Non-blocking one-sided PUT operation
* @tparam T Data type (float16, float32, int32, etc.)
* @param args CommArgs with peer memory pointers
* @param target_rank Destination rank ID
* @param local_src Local source address
* @param remote_offset Offset in remote rank's buffer (in elements of T)
* @param count Number of elements to transfer
*/
template <typename T>
__aicore__ inline void UDMAPutNbi(const CommArgs& args, int target_rank,
const T* local_src, size_t remote_offset,
size_t count) {
if (!UDMAEnabled(args)) return;

void* remote_addr = static_cast<char*>(args.peer_mem_ptrs[target_rank]) +
remote_offset * sizeof(T);
shmem::udma_put_nbi(remote_addr, local_src, count * sizeof(T), target_rank);
}

源码:TileXR 46c58f3dsrc/include/tilexr_udma.h:32-54。与同 revision 的 src/include/comm_args.h:85-102 及两个 SHMEM 固定树交叉核对。[^t-udma-wrapper]

能说与不能说

能说:TileXR 试图通过固定 SHMEM fork 初始化 UDMA,并把设备信息传给 kernel。不能说:TileXR 46c58f3d 已直接兼容 cann/shmem main,或它的实际 MC2 算子已走 SHMEM UDMA。要证明后者,至少还需要包含 getter ABI、匹配的 device header/fields、真实 kernel 调用和可复现构建的同一 revision。

cann/shmem:对称内存运行时

PE、对称堆与 team

SHMEM 的直观模型不是“发一条消息”,而是多个 PE(processing elements) 共同初始化一块布局一致的对称内存域:

  1. 每个 PE 有全局编号,并拥有自己的 local symmetric heap。
  2. 相同 collective allocation 序列让对象在各 PE 上具有可翻译的对称关系。
  3. RMA/AMO 指定本地地址、目标 PE 与操作;runtime 根据 peer heap base、topology 和 engine state 找到实际路径。
  4. team 把 world 切成 PE 子集,为 team 内 PE 映射和同步提供对象。

聚合头本身就显示它封装的是一套 primitive runtime,而非融合算子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#if defined(__CCE_AICORE__) || defined(__CCE_KT_TEST__)
#include "device/gm2gm/shmem_device_amo.h"
#include "device/gm2gm/shmem_device_cc.h"
#include "device/gm2gm/shmem_device_mo.h"
#include "device/gm2gm/shmem_device_p2p_sync.h"
#include "device/gm2gm/shmem_device_rma.h"
#include "device/gm2gm/shmem_device_so.h"
#include "device/gm2gm/engine/shmem_device_mte.h"
#include "device/gm2gm/engine/shmem_device_rdma.h"
#include "device/gm2gm/engine/shmem_device_sdma.h"
#include "device/gm2gm/engine/shmem_device_udma.h"
#include "device/ub2gm/shmem_device_rma.h"
#include "device/ub2gm/engine/shmem_device_mte.h"
#include "device/shmem_def.h"
#include "device/team/shmem_device_team.h"

源码:cann/shmem 382afa08include/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
2
3
4
5
6
7
8
aclshmemx_init_attr
→ 建立 instance context 与失败回滚 guard
→ bootstrap
→ host/device state
→ backend + symmetric heap + memory manager
→ signal + team + sync resources
→ device state update
→ barrier

固定实现对部分初始化失败使用 scope guard 逆序释放资源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
auto init_abort_guard = shm::utils::make_scope_guard(static_cast<void*>(nullptr), [&](void*) {
if (init_succeeded) {
return;
}

SHM_LOG_WARN("ACL SHMEM initialization failed; releasing partial resources without synchronization.");
memory_manager_destroy();
if (init_manager != nullptr && entity_bound) {
if (heap_reserved) {
(void)init_manager->remove_heap();
}
(void)init_manager->release_heap();
if (device_state_initialized) {
(void)init_manager->finalize_device_state();
}
(void)init_manager->release_aclshmem_entity(id);
}
if (bootstrap_initialized) {
aclshmemi_bootstrap_finalize();
}

源码:cann/shmem 382afa08src/host/init/shmem_init.cpp:922-940aclshmemi_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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
std::shared_ptr<TransportManager> TransportManager::CreateForDataOpType(uint32_t dataOpType)
{
std::vector<TransportType> order;
// SDMA STARS/AICPU initialization must run before RDMA/ROCE opens device resources.
if ((dataOpType & HYBM_DOP_TYPE_DEVICE_SDMA) != 0) {
order.push_back(TT_SDMA);
}
if ((dataOpType & HYBM_DOP_TYPE_DEVICE_RDMA) != 0) {
order.push_back(TT_HCCP);
}
if ((dataOpType & HYBM_DOP_TYPE_DEVICE_UDMA) != 0) {
order.push_back(TT_UDMA);
}

if (order.empty()) {
return nullptr;
}
if (order.size() == 1) {
return Create(order.front());
}
return std::make_shared<CompositeTransportManager>(std::move(order));
}

源码:cann/shmem 382afa08src/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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
classDiagram
class InstanceContext {
+device_state
+host_state
+bootstrap
+memory_managers
+exception_context
}
class InitBackend {
+bind_instance()
+create_entity()
+update_device_state()
}
class MemEntityDefault {
+InitTransManager()
+CanReachDataOperators()
}
class TransportManager {
<<abstract>>
+Open()
+Close()
+RegisterMem()
+UnregisterMem()
+GetDeviceInfo()
}
class SDMATransportManager
class HCCPTransportManager
class UDMATransportManager
class CompositeTransportManager {
-managers[]
}
InstanceContext *-- InitBackend
InitBackend *-- MemEntityDefault
MemEntityDefault --> TransportManager
SDMATransportManager --|> TransportManager
HCCPTransportManager --|> TransportManager
UDMATransportManager --|> TransportManager
CompositeTransportManager --|> TransportManager
CompositeTransportManager o-- TransportManager

设备侧默认 RMA 读取 global state 与目标 PE 的 topology,固定优先级是 SDMA → UDMA → MTE → RoCE。blocking 版本在选中的 engine 后执行 quiet;NBI 版本把完成责任留给后续 quiet/fence/signal 协议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ACLSHMEM_DEVICE void aclshmem_getmem(__gm__ void* dst, __gm__ void* src, uint32_t elem_size, int32_t pe)
{
/* Global State Get */
__gm__ aclshmem_device_host_state_t* device_state = aclshmemi_get_state();
if (ACLSHMEM_SDMA_TRANSPORT_ENABLED(device_state, pe)) {
/* SDMA */
uint64_t copy_ub = device_state->sdma_config.aclshmem_ub;
uint32_t copy_ub_size = device_state->sdma_config.ub_size;
uint32_t sync_id = device_state->sdma_config.sync_id;
aclshmemx_sdma_get_nbi(
reinterpret_cast<__gm__ char*>(dst), reinterpret_cast<__gm__ char*>(src),
reinterpret_cast<__ubuf__ char*>(copy_ub), copy_ub_size, elem_size, pe, sync_id);
aclshmemx_sdma_quiet(reinterpret_cast<__ubuf__ char*>(copy_ub), copy_ub_size, sync_id);
} else if (ACLSHMEM_UDMA_TRANSPORT_ENABLED(device_state, pe)) {
/* UDMA */
aclshmemi_udma_get_default_nbi<char>(
device_state, reinterpret_cast<__gm__ char*>(dst), reinterpret_cast<__gm__ char*>(src), elem_size, pe);
aclshmemx_udma_quiet(pe);

源码:cann/shmem 382afa08src/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]

性能与验证边界

本文不引用性能数字。一个可迁移的带宽、时延或加速比至少要同时给出:

  1. 硬件型号、卡数和互联 topology;
  2. TileXR、SHMEM、CANN 的 revision/版本;
  3. 模型,或 dtype、tensor shape、消息大小与并发方式;
  4. baseline 库、算法和配置;
  5. warmup、重复次数、统计指标与计时边界。

本轮没有取得同时满足这五项且与本职责直接相关的固定测量记录,也没有硬件复测。仓库中的示例和 benchmark harness 只能证明“有测试入口”,不能证明某一 transport 或融合算子在任意场景更快。

仍未解决的证据缺口是:

  1. aclshmemx_get_udma_info 的真实来源未知;固定 fork 与 main 均未实现。
  2. TileXR UDMA wrapper 的 header、字段、命名空间 API 和消费 kernel 未闭合。
  3. destroy C ABI 与 UDMA ownership/finalize 协议的运行后果未验证。
  4. all_gather_matmul_v2 固定树依赖缺失,没有完整构建产物解释其来源。
  5. 没有多卡硬件结果验证 IPC、HCCL、SHMEM transport routing 和同步成本。

因此,最稳妥的架构判断是:TileXR 与 SHMEM 分别解决算子编排和对称内存通信;它们有潜在衔接点,但固定 revision 的衔接 ABI 尚未成立。

固定源码锚点

[^t-init]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42csrc/comm/tilexr_comm.cpp:231-259,287-453InitCommonInitInitThreadEnablePeerAccess
[^t-commargs]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42csrc/include/comm_args.h:69-102ExtraFlagCommArgs
[^t-limits]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42csrc/include/tilexr_types.h:27-30src/include/comm_args.h:91
[^t-destroy]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42csrc/include/tilexr_api.h:19-45src/comm/comm_wrap.cpp:222-238src/comm/tilexr_comm.cpp:720-746
[^t-api]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42csrc/mc2/{all_gather,all_gather_add,all_gather_matmul}/op_host/op_api/*.hsrc/include/tilexr_types.h:64-122。固定 src/mc2 执行 rg -n 'UDMA|udma|shmem' 无命中。
[^t-allgather]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42csrc/mc2/all_gather/op_kernel/all_gather.h:43-172,223-250AllGather<T>
[^t-sync]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42csrc/include/tilexr_sync.h:28-105,190-394SyncCollectives
[^t-matmul]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42csrc/mc2/all_gather_matmul/op_kernel/all_gather_matmul_base.h:32-55all_gather_matmul_full_mesh.h:26-147all_gather_matmul.cpp:29-80op_host/op_tiling/all_gather_formulaic_tiling.h:29-60op_host/op_api/aclnn_all_gather_matmul.cpp:11-12
[^t-udma-init]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42csrc/comm/tilexr_comm.cpp:123-190TileXRComm::InitUDMA
[^t-udma-wrapper]: TileXR 46c58f3d0c8704f67e37bf0af322efcf2880f42c.gitmodules:10-13;gitlink b79bda38953d39e88b191e7805659298f0829d73src/include/tilexr_udma.h:9-114。LingquLab/shmem b79bda3 和 cann/shmem 382afa0include/src/aclshmemx_get_udma_info 均无命中;fork 的实际 UDMA 入口见 include/device/gm2gm/engine/shmem_device_udma.h:54-114
[^s-api]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efccinclude/shmem.h:15-50
[^s-python]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efccsrc/python/shmem/core/init_final.py:19-112memory.py:18-77rma.py:19-206
[^s-init]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efccsrc/host/init/shmem_init.cpp:895-1042aclshmemi_init_attr_impl
[^s-finalize]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efccsrc/host/init/shmem_init.cpp:1066-1173
[^s-transport]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efccsrc/host/transport/transport_manager.h:21-99transport_manager.cpp:27-69composite_transport_manager.cpp:48-106
[^s-routing]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efccsrc/device/gm2gm/shmem_device_rma.hpp:22-30,90-145,612-644,747-779
[^s-rma-contract]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efccinclude/device/gm2gm/shmem_device_rma.h:154-172
[^s-sync]: cann/shmem 382afa08efa801d7bca6c2645fd17e155111efccinclude/host/data_plane/shmem_host_cc.h:28-83include/device/gm2gm/shmem_device_cc.h:47-124src/host/data_plane/shmem_host_cc.cpp:18-61src/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 382afa08efa801d7bca6c2645fd17e155111efccdocs/quickstart.md:56-65CMakeLists.txt:207-268src/device/gm2gm/engine/shmem_device_udma.hpp:22-26

Author

Shaojie Tan

Posted on

2026-08-25

Updated on

2026-08-25

Licensed under