补充:Symmetric Buffer 的工作原理
DeepGEMM 的 Mega MoE 用了一个叫 Symmetric Buffer 的精巧设计,把多 GPU MoE 从"先通信再计算"变成了"边通信边计算"。
传统 MoE 通信的问题
MoE 推理中,token 需要根据路由结果分发到不同专家所在的 GPU。传统做法:
GPU 0 的 token → NCCL all-to-all → GPU 1 的专家
这涉及:GPU 0 把数据拷到 NCCL 缓冲区 → NCCL 通过 NVLink 发送 → GPU 1 从 NCCL 缓冲区拷贝出来。两次拷贝 + 通信延迟。
Symmetric Buffer 的做法
利用 NVIDIA TMA (Tensor Memory Accelerator) + NVLink 的对称地址映射:
1. 所有 GPU 分配一块相同大小、相同虚拟地址的显存(这就是 "symmetric" 的含义) 2. 每张卡往自己的那块区域写数据 3. 其他卡通过 NVLink 直接读这块区域——不需要 NCCL,不需要数据搬运
从 DeepGEMM 的代码可以看到关键结构:
struct SymBuffer {
int64_t base; // 本卡缓冲区的基地址
int64_t offsets[72]; // 其他 72 张卡的偏移量
uint32_t rank_idx; // 自己是第几张卡
};
GPU kernel 里要读其他卡的数据时:
ptr_t map(ptr, dst_rank_idx) {
return offsets[dst_rank_idx] + ptr; // 一个加法就拿到远程地址
}
为什么这么快
从 sglang 的 benchmark 数据看(8×H100 NVLink):
| Payload | NCCL | DeepEP | Symmetric Memory |
|---|---|---|---|
| 2MB | 28μs | 13μs | 45μs |
| 64MB | 210μs | 418μs | 44μs |
DeepGEMM Mega MoE 怎么用的
在 fp8_fp4_mega_moe 中,Symmetric Buffer 被用来做通信-计算完全融合:
1. Dispatch 阶段:每个 token 的路由结果写入 Symmetric Buffer 对应位置
2. L1 GEMM 阶段:GPU kernel 直接通过 SymBuffer::map() 读取其他卡的 token,边读边算,不需要等 all-to-all 完成
3. L2 GEMM 阶段:同理,输出也写回 Symmetric Buffer,其他卡直接读
整个 MoE 前向传播变成了一个巨大的融合 kernel,通信被完全隐藏在计算中。
依赖的硬件/软件
- 硬件:NVLink(跨卡 P2P 直接访问)+ TMA(SM100/H100 的异步内存拷贝引擎)
- 软件:PyTorch 的
torch.distributed._symmetric_memory(基于 NVSHMEM),2025 年 GTC 发布,PyTorch 2.9+ 支持 - 限制:只支持同节点内(NVLink 范围),跨节点 RDMA 还不行
一句话总结
Symmetric Buffer 把多 GPU MoE 从"先通信再计算"变成了"边通信边计算"——每张卡直接读其他卡的显存,省掉了 NCCL 的两次拷贝和同步开销,延迟从 O(payload) 降到 O(1)。
#DeepSeek #DeepGEMM #SymmetricBuffer #NVLink #MoE #GPU