Overlap
在大模型(LLM)分布式训练和 AI Infra 的世界里,Overlap(计算与通信重叠) 不是一个具体的软件参数,而是一种所有大厂 SRE 和架构师都在极致追求的“完美运行状态”。
用一句话来概括它的核心本质:让 GPU 在疯狂做矩阵乘法(干计算正事)的同时,底层的网卡和 NCCL 已经在异步、悄悄地把下一步需要的数据传完了(干通信杂活),让“网络传输的时间”完美隐藏在“芯片计算的时间”里。
它是提升集群 MFU(算力利用率)、不让昂贵显卡“带薪摸鱼”的绝对核心魔法。
一、 为什么要 Overlap?(拒绝走走停停)
大模型分布式训练(比如 DDP、FSDP2、ZeRO)因为要把参数或者梯度分给不同的显卡,每算完一步,卡与卡之间都必须调用 NCCL 发起网络通信(如 AllReduce、AllGather)来对答案。
如果没有做 Overlap,整个训练流水线会变成极其低效的“串行卡顿状态”:
【没有 Overlap 的糟糕状态】:
GPU: [ 闷头计算 100ms ] ──> [ 功耗掉到几瓦,干等网络 80ms ] ──> [ 再计算 100ms ]
网卡: [ 闲置、毫无流量 ] ──> [ NCCL 疯狂传数据 80ms ] ──> [ 闲置、毫无流量 ]
▲
这就是算力的巨大浪费!
而在完美的 Overlap 状态下,流水线会变成这样:
【完美的 Overlap 状态】:
GPU: [ 闷头计算层 100ms (算第10层) ] ──>[ 毫无卡顿,直接算第9层 100ms ]
│
▼ (异步悄悄触发)
网卡: [ 异步发起第9层的 NCCL AllGather 通信 80ms ] ──> [ 传第8层的数据... ]
在第二种状态下,整个训练由于没有任何“死等网络”的空白期,GPU 的轰鸣声一刻不停(功耗死死拉满),多出来的 80ms 通信时间被完全“藏”进了 100ms 的计算时间里。
二、 工业界是如何在底层实现 Overlap 的?
你在第一阶段学到的那些硬核工具(DDP、FSDP2、ZeRO),在代码底层之所以牛,就是因为它们各自发明了极其巧妙的 Overlap 手法:
1. DDP 的“梯度分桶 (Gradient Bucketing)”
DDP 在跑反向传播(Backward)算梯度时,绝对不会傻傻地等整张网络全部算完才去发起 NCCL 通信。
- 它在底层把模型的参数倒序编排成一个一个的“桶 (Buckets)”(默认大小一般为 25MB)。
- 当反向传播从输出端往回算,只要后面几层算出的梯度刚好填满了一个 25MB 的桶,DDP 就会立刻、悄悄地启动一个背景线程,调用 NCCL 异步发起这个桶的
AllReduce梯度同步。 - 在这个桶在网卡里传输的同时,GPU 还在继续往前算前面几层的梯度! 这种精妙的机制把网络通信的时间几乎完美地“隐形”了。
2. FSDP2 / ZeRO-Stage 3 的“异步预取 (Prefetching)”
我们在前一节刚聊过,FSDP2 连模型参数都切碎了,前向传播算每一层时都要向别人要参数。它是怎么做 Overlap 的呢?
- 当 GPU 正在计算模型第 10 层的矩阵乘法时。
- FSDP2 的底层调度器会看一眼后面的执行流,提前给网卡下达指令:“趁 GPU 现在正忙,立刻发起第 9 层参数的
NCCL AllGather!” - 等到第 10 层一算完,第 9 层的参数已经通过无损 RDMA 网络提前躺在显存里了,GPU 零延迟直接开算第 9 层。
三、 SRE 在监控大盘里怎么判断 Overlap 成功了?
作为 AI Infra SRE,你不需要去写底层的异步线程代码,但你必须在 Grafana 监控盘上拥有一双能看透 Overlap 的透视眼:
1. 完美的 Overlap(算力回报率高)
- 监控表现:
GPU Power (功耗)是一条平稳高耸的直线(比如持续稳定在 400W 以上)。同时,RDMA / Net Traffic (网卡流量)也是一条平稳的直线(比如一直稳定在 180Gbps)。 - 大白话: 显卡在疯狂震荡计算,网卡在持续疯狂传数据,两者各司其职,互不耽误。此时集群的
MFU(算力利用率)会非常漂亮(通常 >50%)。
2. 失败的 Overlap(网络或存储阻塞)
- 监控表现:
GPU 功耗和网卡流量呈现“完美的交替波峰波谷”——功耗高的时候流量是 0,流量飙上去的时候功耗瞬间掉到十几瓦。 - 大白话: 典型的一步一停。GPU 算完开始摸鱼,等网络传完;网络传完轮到网卡摸鱼,等 GPU 算。
四、 如果 Overlap 失败了,SRE 该怎么调优?
当你用 Profiler 工具拉出火焰图,发现计算和通信是死死的串行、完全没有重叠时,你有以下几大调优手段:
- 加大 Gradient Accumulation Steps (GAS / 梯度累积步数):
让显卡在本地多闷头算几步再触发一次通信。这虽然没有真正重叠,但它大幅稀释了通信在整个训练时间里的占比,变相拉高了 MFU。 - 检查并调大 DDP 的桶大小 (
bucket_cap_mb):
如果你们模型的层特别大,默认的 25MB 分桶可能一瞬间就填满了,导致异步线程频繁启动产生冲突。可以尝试将其调大到 50MB 甚至 100MB,让通信更具连贯性。 - 确认跨机是否真的走满了 RDMA (RoCEv2 / IB):
如果网络回退到了慢速的普通 TCP Socket 通信,原本 10ms 就能传完的数据现在要传 100ms。由于通信时间(100ms)远大于计算时间(40ms),计算根本“藏”不住通信,Overlap 会彻底宣告破产。
总结口诀:
大模型训练要跑快,计算通信要合拍。网卡在传卡在算,Overlap 好 MFU 迈!
这个概念可以说是第一阶段分布式训练的“灵魂”。你现在对 DDP 为什么要把梯度分桶、FSDP2 为什么要提前预取,是不是有了极其通透的闭环理解了?
