MCCL over ACE
1. 概述
异步通信引擎 Async Copy Engine (ACE) 是 MTGPU 的一个独立硬件单元,用于在不同内存域之间实现高带宽、低延迟的异步数据搬运。

运行原理
在典型的多芯片(Multi-Die)GPU 结构中,每个 GPU 包含多个计算芯片,ACE 的任务是为这些芯片之间及 GPU 之间提供高效的数据通路,主要包括:
- Host 内存 ↔ 显存(H2D/D2H)
- 本地 GPU 显存 ↔ 远程 GPU 显存
- 芯片内部 Die 间数据搬移(D2D - Die to Die)
对称内存 (Symmetric Memory)
MCCL over ACE 使用对称内存机制,允许每个 GPU 直接访问其他 GPU 的内存地址空间。
Rank 0: [Base + 0*stride] ───┐
Rank 1: [Base + 1*stride] ───┼─→ 对称内存窗口
Rank 2: [Base + 2*stride] ───┘
关键函数:
mcclMemAlloc(): 分配对称内存mcclCommWindowRegister(): 注册对称内存窗口
图执行 (Graph Execution)
MCCL over ACE 预先构建 MUSA Graph,包含所有通信节点(同步、拷贝、原子操作),运行时动态更新参数后执行。
优势:
- 减少 API 调用开销
- 硬件级流水线优化
- 更低的通信延迟
2. 支持的集合通信原语
AllReduce
AllReduce 操作在设备间对数据(例如,求和、最小值、最大值)进行归约,并将结果存储在每个 rank 的接收缓冲区中。
以 sum 为例,在 k 个 rank 之间的求和 AllReduce 操作中,每个 rank 将提供一个包含 N 个值的数组,并在包含 N 个值的数组 out 中接收相同的结果,其中 out[i] = in0[i] + in1[i] + ... + in(k-1)[i]。

AllGather
AllGather 操作从 k 个 rank 中收集 N 个值到大小为 k*N 的输出缓冲区,并将该结果分发到所有 rank。输出按 rank 索引排序。因此,AllGather 操作会受到不同 rank 到设备映射的影响。

ReduceScatter
ReduceScatter 操作执行与归约相同的操作,但结果在 rank 之间以等大小的块分散,每个 rank 根据其 rank 索引获得一块数据。由于 rank 决定数据布局,ReduceScatter 操作会受到不同 rank 到设备映射的影响。

AlltoAll
在 k 个进程组(rank)之间的 AllToAll 操作中,每个进程组会提供一个大小为 k×N 个值的输入缓冲区:其中第 j 个包含 N 个值的数据块(chunk)会发送至目标进程组 j;每个进程组会接收一个大小为 k×N 个值的输出缓冲区:其中第 i 个包含 N 个值的数据块源自源进程组 i。
ACE 版本的 mcclAllToAllv 接口支持非对称输入。

3. API 参考
初始化与销毁
mcclAceCommInitRank
初始化 MCCL over ACE 通信器。
mcclResult_t mcclAceCommInitRank(
mcclComm_t* comm, // [out] 通信器句柄
int nranks, // [in] 进程总数
mcclUniqueId commId, // [in] 唯一 ID
int rank // [in] 当前进程 rank
);
与 SHADER 版本的区别:
mcclAceCommInitRank 和 mcclCommInitRank 的主要区别在于是否启用 ACE。
// SHADER 版本
mcclResult_t mcclCommInitRank(mcclComm_t* newcomm, int nranks,
mcclUniqueId commId, int myrank) {
...
// isAceComm 默认为 false
MCCLCHECK(mcclCommInitRankDev(...));
...
}
// ACE 版本
mcclResult_t mcclAceCommInitRank(mcclComm_t* newcomm, int nranks,
mcclUniqueId commId, int myrank) {
...
// 显式传递 isAceComm = true
MCCLCHECK(mcclCommInitRankDev(..., true));
...
}
示例:
mcclUniqueId id;
if (rank == 0) {
mcclGetUniqueId(&id);
}
MPI_Bcast(&id, sizeof(id), MPI_BYTE, 0, MPI_COMM_WORLD);
mcclComm_t comm;
mcclAceCommInitRank(&comm, worldSize, id, worldRank);
mcclCommDestroy
销毁通信器。
mcclResult_t mcclCommDestroy(mcclComm_t comm);
内存管理
mcclMemAlloc
分配通信显存。
mcclResult_t mcclMemAlloc(
void** ptr,
size_t size
);
mcclMemFree
释放通信显存。
mcclResult_t mcclMemFree(void* ptr);
mcclCommWindowRegister
注册为对称内存。
mcclResult_t mcclCommWindowRegister(
mcclComm_t comm, // [in] 通信器
void* localPtr, // [in] 本地内存指针
size_t size, // [in] 内存大小
void** symmetricHandle, // [out] 对称内存句柄
int flags // [in] 标志
);
flags 参数支持:
/* Window Registration flags */
#define MCCL_WIN_DEFAULT 0x00 // 普通注册,一般不用
#define MCCL_WIN_COLL_SYMMETRIC 0x01 // 对称内存注册(ACE 集合操作必需)