Data-as-Flag Communication

导言

我最初在 Ascend 内网看到 Data-as-Flag 时,直觉上把它理解为三种省掉独立完成通知的方法:把 flag 塞进数据块、用数据校验值确认整批到达,或者先用特殊值填满接收区,再观察它是否被真实数据覆盖。

顺着这三个方向检查 NVIDIA 的公开资料后,答案很明确:NVIDIA 不但有相同思路,NCCL 的 LL/LL128 已经长期使用内嵌 flag;NCCL 2.31.2 的 LLA2A 又把它做成了面向低时延 All-to-All 的 payload + epoch 原子槽位。不过,公开实现更偏好显式 epoch,而不是让任意 payload 或 checksum 单独承担正确性。

先说结论

Data-as-Flag 最容易被误解成“不要 flag”。更准确的说法是:

它没有删除同步,而是删除了 flag 的独立因果链。

传统的单边写入通常需要建立以下顺序:

1
写 payload → fence / quiet / completion → 写 flag → 接收方轮询 flag → 读取 payload

Data-as-Flag 则尝试把“数据已经可安全读取”的证明放进同一个数据面事务:

1
原子写入 {payload, proof} → 接收方轮询 proof → 读取同一原子单元中的 payload

这里的 proof 可以是内嵌 flag、epoch、checksum,也可以是“某段数据已经不再等于 sentinel”这一谓词。优化目标不是少传几个字节,而是减少一次独立写、一次顺序约束或一次完成队列往返,并把完成粒度从整批消息缩小到 DataBlock、cache line,甚至单个 token。

调研得到的 NVIDIA 对应关系如下:

机制 NVIDIA 对应物 是否属于严格的 Data-as-Flag 核心边界
数据块内嵌 flag NCCL LL、LL128、LLA2A 依赖传输原子性或可见顺序
payload 后更新 signal NVSHMEM put-with-signal、NCCL ncclPutSignal 否,属于绑定式通知 signal 仍是独立对象
数据附带立即数 RDMA Write-with-Immediate 否,属于带外通知 immediate 进入接收完成路径
checksum 证明整批到达 未找到 NVIDIA NCCL/NVSHMEM 公开对应实现 未确认 链路 CRC 只证明完整性,不等于应用完成
sentinel 被覆盖 未找到 NVIDIA 公开对应实现 未确认 必须排除碰撞并处理重置与 ABA

证据范围

“未找到”只表示截至 2026 年 9 月能检索到的 NVIDIA 官方文档与开源代码中没有对应证据,不等于 NVIDIA 的闭源硬件、固件或内部库绝对没有这两种方案。

完成到底指什么

讨论 flag 之前,必须先把“完成”拆开。一次通信至少有四种不同的完成:

  1. 源端完成:传输引擎已经不再读取源 buffer,发送方可以复用它。
  2. 远端到达:字节已经写入远端目标内存。
  3. 消费者可见:接收侧计算单元读取时,能够看到与完成标志同一代的完整 payload。
  4. 协议完成:credit、错误状态和循环 buffer 生命周期已经更新,可以开始下一轮。

Data-as-Flag 主要压缩的是第 2、3 项之间的通知路径。它不能自动替代源 buffer 复用、流控、超时或错误恢复。NVIDIA 在介绍 NCCL 2.24 的 optional receive completion 时也保留了这个边界:LL/LL128 可以让 GPU 根据数据中的 flag 开始处理,不必等待网络栈发出 receive completion;但网络插件的请求仍会被测试,以便清理跟踪状态。NVIDIA NCCL 2.24 技术博客

换句话说,省掉的是热路径上的“数据到了吗”,不是整个协议状态机。

UBEP 的三种证明

UBEP 论文把 Data-as-Flag 分为 TFF、DC 和 SP 三种变体。它们都依赖 CM384 Unified-Bus 对 512 B DataBlock 原子写入的保证,但把确定性、带宽和流水粒度交换到了不同位置。论文 Section 3.4 与 Figure 6

Flag 与数据同块

Token-Flag Fusion(TFF)把一个 512 B DataBlock 切成 32 B flag + 480 B payload。发送方把两者拼好后执行一次 512 B 原子写;接收方一旦观察到 flag 已更新,就能由同一原子事务推知其余 480 B 也已经可见。

它的优点是确定性强、每个 DataBlock 都可以独立进入下游流水,而且不再需要发送侧 payload → barrier → flag。代价同样直接:flag 占用 6.25% 线速容量,发送侧还要 pack,接收侧要 unpack。

数据生成批次证明

Data Checksum(DC)不在每个 DataBlock 里放 flag。发送方取各块的 32 B marker 计算累计 checksum,整批数据发完后再发送 checksum;接收方对已到达的 marker 做同样计算,匹配后把这一批判为完成。

DC 把逐块控制字节换成了一次批量证明,payload 比例更高,但接收方要等待整批 checksum,token 级流水退化为 batch 级流水。此外,checksum 方案的安全性取决于校验函数、位宽、旧数据分布和重复计算过程;若存在碰撞,就可能把未完成状态误判为完成。

数据覆盖初始哨兵

Sentinel Polling(SP)把编码与检查都移到接收端:接收 buffer 先填入特殊 sentinel,发送方原样写 payload,接收方只检查每个 DataBlock 中指定的 32 B 是否已经不等于 sentinel。

这让线上字节全部都能承载 payload,理论有效带宽最高。但它把成本转移成了三项约束:

  • 每轮使用前必须重置接收 buffer;
  • 被检查的数据域必须保证不会合法地产生 sentinel;
  • 若真实 payload 恰好等于 sentinel,接收方会一直等待。

UBEP 为 SP 预留了普通 BF16/FP16 计算不能产生的 bit pattern,并在模型初始化时检查权重和激活不会生成该模式。论文还给出均匀分布下 32 B sentinel 偶然碰撞为 $2^{-256}$ 的估计,但也明确承认理论概率不为零,SP 仍可能因碰撞发生罕见死锁。论文第 8、11 页

NCCL 已经走过这条路

LL:用 50% 带宽买低时延

NCCL LL 的 FIFO line 把每个 32 bit 数据紧跟一个 32 bit flag。一个 16 B line 实际只携带 8 B payload,另 8 B 都是 flag:

1
2
3
4
5
6
7
8
union ncclLLFifoLine {
struct {
uint32_t data1;
uint32_t flag1;
uint32_t data2;
uint32_t flag2;
};
};

接收端反复读取整行,只有 flag1flag2 都等于当前 step 对应的期望值,才把 data1data2 拼回 64 bit payload。发送端则用同一次向量 store 写入 {data1, flag, data2, flag}NCCL 2.31.2 device.h NCCL 2.31.2 prims_ll.h

源码注释还给出了它的正确性假设:socket 路径连续接收,或者 IB/RDMA 路径至少保证 8 B 写入原子性;flag 必须排在对应 data 后面,避免不完整接收先暴露 flag。

这与 UBEP TFF 的物理直觉完全一致,只是原子粒度更小。LL 的 payload 效率只有 50%,因此适合以固定延迟为主的小消息,而不适合追求大消息峰值带宽。

LL128:同样的 6.25% 开销

LL128 把线宽扩大到 128 B,其中 15 个 64 bit word 是数据,最后 1 个 word 承担 flag,理论 payload 效率为:

$$
\eta_{LL128}=\frac{120\ \mathrm{B}}{128\ \mathrm{B}}=93.75%.
$$

巧合但很有启发性的是,UBEP TFF 的 $480/512$ 也是 **93.75%**。两者选择了不同原子粒度,却都用 1/16 的线上容量换取细粒度完成证明。NCCL 接收端由 flagThread 检查每条 128 B line 的 flag,只有当前 warp 观察到期望 step 才继续处理;源码中的 NCCL_LL128_DATAELEMS = NCCL_LL128_LINEELEMS - 1 正对应 120 B payload + 8 B flag。NCCL 2.31.2 device.h NCCL 2.31.2 prims_ll128.h

LL128 也说明了这种技巧为什么不能只靠软件模仿。它依赖平台对 128 B 写入可见顺序的支持;NCCL 官方文档明确警告,强制在不支持的平台启用 LL128 可能造成数据损坏。NCCL NCCL_PROTO 文档

LLA2A:payload + epoch 的原子槽位

NCCL 2.31.2 源码中的 ncclLLA2ASession 是与 UBEP 最接近的 NVIDIA 实现。它面向 symmetric memory 上的低时延 All-to-All,把 8 B 数据和两个 32 bit epoch 组成一个 16 B uint4

1
2
3
4
5
// 发送关键路径:{data_lo, epoch, data_hi, epoch}
st.relaxed.sys.v4.u32 [dst], {data_lo, epoch, data_hi, epoch};

// 接收关键路径:两个 epoch 都属于当前轮次才消费 data
ready = slot.y == epoch && slot.w == epoch;

这是从发送与接收模板中抽出的关键路径,省略了 peer 地址计算、类型分片、循环展开和 abort 检查;完整实现见 发送端第 39–62 行接收端第 154–217 行。NCCL 仓库中的 GIN/Symmetric Memory 说明进一步把这项机制概括为:利用 NVLink 16 B 原子 store,一次操作同时交付数据并发布完成。NCCL LLA2A 说明

LLA2A 没有让任意 payload 值直接决定 ready,而是保留了两个 epoch。epoch 回答“这是不是当前轮的数据”,双 buffer 与跨 session 的 epoch 跳变则避免旧槽位被下一轮误认。它仍然付出 50% 线上容量,却换来了无碰撞的完成谓词和逐槽消费能力。

这些 NCCL 公开实现呈现出共同取舍:只要延迟收益足够大,宁愿花固定元数据字节,也不把正确性押在 payload 的统计性质上。

相邻机制为何不等价

Put-with-Signal 绑定操作但不合并对象

NVSHMEM 提供 nvshmem_putmem_signal:复制 source → dest 后,再更新远端 64 bit sig_addr;远端观察到 signal,就表示与这次调用对应的 dest 数据已经交付。这已经把 put + quiet + signal 封装成一项语义明确的操作,但官方文档要求 sig_addrdest 不得重叠,因此它不是数据块内嵌 flag。NVSHMEM Signaling Operations

NCCL 2.29 起提供的 ncclPutSignalncclWaitSignal 也属于这一类:同一 peer、同一 context 的数据交付和 signal 更新按程序顺序执行,但 signal 仍由 sigIdx 标识。NCCL One-sided Communication

它们的价值是把顺序责任交给库,而不是让应用自己插 fence。相较 Data-as-Flag,它更通用、payload 无需重排,但仍维护独立 signal 空间和完成顺序。

Write-with-Immediate 是带外通知

RDMA Write-with-Immediate 将一个 32 bit immediate value 与 RDMA write 关联,远端在预先提交 receive job 后从完成结果中取得该值。NVIDIA DOCA 文档明确称 immediate 为 out-of-band 数据,因此它更像“payload 到达时顺便生成一个 CQ 事件”,而不是“轮询 payload 自身”。NVIDIA DOCA RDMA Write with Immediate

这条路径适合需要事件分派、长度、序号或类型信息的协议,但它没有消除接收队列与 completion processing。

CRC 证明没传坏,不证明该消费了

NVIDIA 的 NVLink 确实存在 CRC Data、CRC FLIT、Replay 与 Recovery 等链路可靠性机制。NVIDIA DCGM NVLink Counters 但链路 CRC 回答的是“某个 flit/packet 是否损坏”,不是“应用期待的全部 DataBlock 是否已经到齐、属于哪一轮、现在能否复用 buffer”。

要让 checksum 真正承担完成证明,协议还必须定义:

  • 应校验哪些 block,以及期望 block 数量;
  • checksum 属于哪个 generation;
  • 部分旧数据与部分新数据会不会碰巧得到相同结果;
  • checksum 自身何时可见,接收方如何重试;
  • 失败时是重传、超时还是终止。

因此,链路 CRC 可以是 Data Checksum 的底座,却不能直接替代 Data Checksum 的应用层批次协议。NCCL 2.24 只在 LL/LL128 的内嵌 flag 路径上把 receive completion 标为 optional,也侧面印证了这层区别。

一套统一设计框架

把不同名字拿掉后,这类方案都在设计一个函数:

1
ready(generation, slot) -> true / false

一个可用的 ready 必须同时回答“完整性”和“新鲜度”。可以沿六个问题检查设计是否成立:

  1. 原子单元多大? 如果接收方看到 proof 时,payload 仍可能被撕裂或乱序到达,方案就不正确。TFF 依赖 512 B,LL 依赖 8 B 对,LLA2A 依赖 16 B 槽位。
  2. 完成粒度多细? 每个 block 一个 proof 能立即流水;每批一个 checksum 节省元数据,却要等待整批。
  3. 如何区分代际? epoch、sequence number 或双 buffer 用来防止旧数据被误认,这本质上是循环队列里的 ABA 问题。
  4. 碰撞意味着什么? checksum 碰撞可能产生 false-ready;sentinel 与合法 payload 相等通常产生 false-not-ready,最终表现为死锁。
  5. buffer 何时复用? 远端 ready 不等于源端可复用,也不等于接收槽位已被消费;仍需要 credit、head/tail 或本地 completion。
  6. 异常如何退出? 轮询循环必须保留 abort、timeout 与错误传播,否则“极低延迟”会以不可诊断的永久自旋为代价。

这六项可以进一步压缩成三种基本交换:

方案 用什么换掉独立 flag 路径 主要收益 主要风险
内嵌 flag / epoch 线上 payload 比例 最细粒度、确定性强 带宽损失,绑定原子粒度
checksum 计算与批量等待 元数据比例低 碰撞、批次延迟、校验开销
sentinel 接收区初始化与数据域约束 接近 100% payload 碰撞死锁、重置、ABA
独立 signal 额外控制状态与顺序操作 语义通用、易恢复 固定通知延迟和状态管理

如何选择

Data-as-Flag 并非越“没有 flag”越先进。实际选择更适合遵循下面的顺序:

  1. 先找硬件保证。 明确 remote store 的原子粒度、写入顺序、cache 可见性和 acquire/release 语义;没有这些保证时,退回显式 fence/signal 才是正确实现。
  2. 再看消息粒度。 小消息、token 级流水和固定延迟占主导时,TFF、LL、LLA2A 即使牺牲带宽也可能更快;大消息受链路带宽限制时,额外 flag 字节的代价更明显。
  3. 最后决定容错预算。 不能接受概率性错误的基础通信库,应优先使用 epoch 或序号;只有 payload 域可严格约束、sentinel 可形式化排除时,SP 才能从概率技巧变成协议保证。
  4. 保留回退路径。 NVIDIA 会按拓扑与平台能力选择 LL、LL128 或 Simple,并警告不要在不支持的平台强开 LL128。可移植实现也应在原子性不满足时回退到 checksum 或显式通知。

不要把 microbenchmark 结论直接外推

UBEP 的 Data-as-Flag 消融在 CM384、CANN EP baseline 和特定 MoE dispatch 粒度下得到相对收益。它证明“同步税在该环境中值得优化”,但不能证明把 NCCL LL128、LLA2A 或 SP 搬到另一种 GPU/NIC 拓扑后会得到相同加速。报告收益时必须同时固定硬件、传输路径、消息大小、并发度、数据类型和 baseline。

总结

回到最初的问题,NVIDIA 的答案可以概括成三层:

  • 严格同类:NCCL LL、LL128 和 LLA2A 都把完成 proof 放进数据传输单元,接收 GPU 直接轮询数据 buffer;其中 LLA2A 的 8 B payload + 双 epoch 与 UBEP TFF 最接近。
  • 语义近亲:NVSHMEM/NCCL PutSignal 与 RDMA Write-with-Immediate 把数据和通知绑定为一次 API 或事务,但仍保留独立 signal、immediate 或 completion。
  • 没有公开对应证据:NVIDIA 的链路 CRC 不是 UBEP DC;也没有找到 NCCL/NVSHMEM 采用 payload sentinel 作为完成条件的公开实现。

真正可复用的设计思路不是某一种编码,而是:让“数据可见”与“完成证明可见”共享同一个最小硬件保证,再用 generation 管理复用,用 timeout 管理失败。数据不能凭空变成 flag;它必须携带一个接收方能够无歧义验证的证明。

参考资料

  1. Yipeng Liu et al., UBEP: Re-architecting Expert Parallelism Communication Library for Production Superpods, ACM SIGCOMM 2026.
  2. NVIDIA, Networking Reliability and Observability at Scale with NCCL 2.24.
  3. NVIDIA NCCL 2.31.2, ncclLLFifoLine, ProtoLL, ProtoLL128ncclLLA2ASession.
  4. NVIDIA, NVSHMEM Signaling Operations.
  5. NVIDIA, NCCL One-sided Communication.
  6. NVIDIA, DOCA RDMA Programming Guide.
  7. NVIDIA, DCGM NVLink Counters.
Author

Shaojie Tan

Posted on

2026-09-04

Updated on

2026-09-04

Licensed under