每次看到有人说“某某团队又开源了一个大模型,我下载个权重跑跑看”,我都有点无奈。模型只是整个系统最上面那一层,真正决定一个万卡集群能不能把理论算力跑出来的,是底下那层几乎没人注意的“地基”。这次 DeepSeek 开源的,恰恰不是模型,而是这层算力地基——一套面向 MoE 模型的专家并行通信库和配套的显存调度机制。换句话说,它把让模型在几千张卡上高效协同工作的“物流系统”整个端了出来。这篇文章我围绕“为什么说这是算力地基”“通信库到底解决了什么问题”“实操落地怎么看”“坑在哪里”这几个角度展开,给真正关心分布式训练和算力基建的同学做个参考。
1. 为什么说这次开源的是“算力地基”而不是模型
1.1 大模型系统的三层结构
一个能跑起来的大模型系统,表面看是模型架构和权重,底子其实是三层东西。
最上层是模型本身。包括 Transformer 结构、注意力机制、MoE 里有多少个专家、激活函数用什么、权重怎么排布。这一层大家天天讨论,也是开源社区最热闹的部分。
中间层是并行策略和框架。数据并行、张量并行、专家并行、流水线并行、序列并行,这些策略决定了一笔计算任务怎么切分到不同卡上,以及不同卡之间如何同步和交换数据。常见的训练框架、推理框架基本都在这层干活。
最底下那层是硬件和系统软件的结合部。GPU 驱动、集合通信库、网络协议栈、拓扑感知调度、显存管理、IO 路径优化。这层负责把“在 8 张卡上能跑”变成“在 8000 张卡上能高效地跑”。
模型开源了,你可以在单卡上做推理、做微调,感受一下模型生成的质量。但如果你想把训练规模从 8 卡推到 64 卡、512 卡、2048 卡,瓶颈不在模型层,而在最底下那层。这次 DeepSeek 拿出来的,就是这层里最难啃的一块:MoE 模型在专家并行场景下的通信和调度基础设施。
1.2 MoE 模型的性能瓶颈早就不在单卡算力
MoE 模型的好处很多人知道:FFN 层拆成多个专家,每个 Token 只激活其中一小部分专家,用更少的算力换来更大的参数量。听起来很完美,但工程实现上有个很尴尬的问题——Token 在哪个专家上算,不是由本地数据决定的。
举个例子,一条样本里可能有 100 个 Token。路由机制告诉你,其中 30 个要去专家 3,20 个要去专家 7,另外 50 个要去专家 12。如果专家 3 在 1 号卡的显存里,专家 7 在 4 号卡里,专家 12 在 8 号卡里,那么当前这张处理样本的卡,就必须把不同 Token 分别发往 1、4、8 号卡。同时,其他卡上的 Token 也可能发到你这张卡上来。
这就是 All-to-All 通信模式。别小看这个模式,它和传统数据并行里的 AllReduce 完全不是一回事。AllReduce 的通信量是固定的,和 batch size 线性相关,而且通信拓扑规整。而 MoE 的 All-to-All 分发量随专家数量、Token 数量、路由分布剧烈变化,每一轮都在变。
当集群规模变大,这种分发的通信总量会涨得非常快。很多人以为大模型训练慢是算力不够,实际上到了万卡规模,很长一段时间卡在通信等待上——要么是在等某个专家上的 Token 全部到位,要么是在等远端计算完把结果传回来。单卡算力再强,也填不满网络等待的空洞。
1.3 通信栈一旦开源,受益的不只是某一个模型
过去商业闭源的集合通信库把底层实现包得严严实实,开发者只能调用高层 API。遇到性能问题时,能看到的就是一个黑盒:数据进去,结果出来,中间为什么慢、哪条链路拥堵、是不是路由策略不对,一概不知。
这次开源把通信栈内部的核心机制放了出来,包括 All-to-All 分发怎么调度、在途 Token 怎么控制、机内高速互连和机间网络怎么同时利用、显存缓冲区怎么管理。这些实现细节以前是各家大厂压箱底的东西,现在直接摊开给大家看。你拿到的不是“别人调好的参数表”,而是整套可以自己改、自己适配、自己排查问题的源码。
2. 专家并行通信库的核心机制拆解
2.1 计算核心:显存管理与长序列切边
先聊很多人不太注意的计算核心部分。MoE 模型训练和推理时,会长序列的激活值驻留在 GPU 显存里。序列越长、专家越多,激活值常常比模型权重还占地方。显存不够用是个持续存在的痛点,尤其当多个专家并行时,每张卡不仅要存自己负责的专家权重,还要临时存储从其他卡涌过来的 Token 的激活值。
这套基础设施里做了一件事:把长序列的激活值切边,必要时从 HBM(显存)换到临时缓冲区,等要计算时再取回来。这个过程不是简单粗暴地“溢到内存里”,而是有调度策略的。它会让通信过程与显存换入换出过程重叠,尽可能不产生额外的等待。
实际操作中这个机制的价值很大。很多人以为 OOM 只能靠调小 batch size 解决,但显存管理的粒度可以细化到单个 Token 的激活值生命周期。该留的在显存里留着,该挪走的按优先级挪走,空闲出来的显存空间立刻可以被其他卡发来的数据用上。这套东西对一个集群的实际吞吐影响,不亚于换一张更贵的卡。
2.2 通信核心:All-to-All Token 分发的高扩展实现
通信核心是这套地基里最硬核的部分。它做的不是简单的“调一下网卡发送缓冲”这种事,而是把 Token 分发整个过程重新实现了一遍。
一般的实现里,每个节点要把自己算好的输出 Token 发往其他节点,然后从其他节点接收发往本节点的 Token。最简单的做法是一次性把所有数据塞进网卡发送队列,发完再等收。问题是,网络是有带宽上限和延迟的。当 Token 数量达到百万甚至千万级时,一次性塞进去,要么把网卡队列打满,要么在交换机和中间链路上造成拥塞,最终结果是整体吞吐不升反降。
这里引入了一个很关键的参数概念:在途 Token 数量上限。系统会控制同一时刻正在网络上传输、尚未到达目的地的 Token 数量。带宽充足的场景下,加大这个上限能把管道填满,让每一跳都在干活;带宽紧张或者对延迟敏感的场景下,就要调小这个上限,避免排队加剧延迟抖动。
高扩展 All-to-All 内核还承担了调度任务。它会感知当前各个下游节点的接收能力、中间链路状态、还有没有空闲缓冲,按优先级安排发送顺序。相当于在每张卡里都放了一个懂交通调度的交警,不让一个方向的流量把整条路堵死。
2.3 通信与计算重叠:把时间轴塞满
分布式训练吞吐低的核心原因,是通信和计算没有重叠。数据并行里,梯度要等反向传播结束才能 AllReduce,这期间 GPU 可能闲着;MoE 的 Token 分发同样存在这个问题——如果先等所有 Token 到位,再开始计算,那通信阶段 GPU 算力就白空转。
这套基础设施的做法是把时间轴切成流水线。当前 batch 的 Token 在 GPU 上做矩阵乘法时,下一批 Token 的分发已经在网络上跑了。再进一步,同一批数据内部也可以分层重叠:哪些 Token 本地专家就能处理,就直接算;哪些 Token 要去远端,提前发出,不等全量到齐就开算本地部分。
实际效果是,GPU 的利用率可以明显提升,尤其当专家数量多、Token 分发量大的时候。通信和计算的重叠程度,是衡量一个分布式系统是否成熟的关键指标。开源出来的这套实现,把重叠逻辑做了很细的控制,而不是简单地在代码里加两个异步流。
3. 多机多卡环境下的调度策略
3.1 机内互连与机间网络的路径选择
一个训练集群很少是单机多卡,通常是几十台甚至上百台机器通过高速网络连起来。这就有个现实问题:机内互连带宽通常远大于机间网络带宽,而且拓扑不是均匀的。
节点内几张卡之间走的是私有高速互连通道,延迟极低、带宽极高。节点之间走的是 RDMA 网络,可能是 InfiniBand,也可能是 RoCE。如果通信库不考虑这两种路径的区别,把去往同一个节点内另一张卡的数据也绕到外部网络上,那就是浪费。
这套基础设施里有个很实用的设计:同时利用机内高速互连和机间网络,也就是所谓双路并行。Token 分发时,去往本机卡的数据走机内通道,去往远端节点的数据走外部网络,两条路径同时工作。而不是简单地在机间网络上排队。
3.2 带宽受限与延迟受限的调优方向
同一个通信参数,在不同场景下的最优值是两回事。
带宽受限的场景,比如训练集群,节点间的总吞吐决定了整体速度。这时要把在途 Token 上限调大,让网络每条链路都满载,同时开启双路并行,让机内和外网都干活。通信量越大,这种激进策略收益越明显。
延迟受限的场景,比如在线推理服务,端到端时延是用户直接感知的。这时在途 Token 过多会导致网络排队,平白增加几十微秒的延迟。要适当压小上限,甚至限制某些非关键路径上的并发度,换取更稳定的低延迟响应。
很多同学在集群上做调优,只盯着模型侧的 batch size、学习率、专家数量,忽略了通信侧还有一组同样关键的旋钮。集群一旦多了,通信参数的变化对整体吞吐的影响,往往会大到出乎意料。
3.3 负载均衡与拥塞控制
MoE 模型的专家负载天然不均衡。路由机制可能让某些热门专家收到大量 Token,另一些专家闲着。通信库要做的是在分发阶段尽量平滑负载,把多余的 Token 在时间和空间上打散,避免同一时刻某条链路被打爆。
拥塞控制也是关键。真实集群里,网络不可能是理想状态。交换机队列可能积压,某些链路可能承载了别的任务。通信库如果能感知拥塞信号,比如收到显式拥塞通知,它会主动调整发送速率或切换数据路径,而不是傻乎乎地继续往堵住的路上灌数据。
这就需要通信库和网络设备之间有协作机制,而不是把它单纯当成一个“发送数据的库”来用。把拥塞处理逻辑做进通信库里,是这套开源实现比较贴近生产环境的地方。
4. 实操参考:在自建集群上验证这套通信方案
4.1 环境摸底:先搞清楚自己的集群是不是“均匀网络”
很多人在自建集群上跑分布式训练,上来就搬默认配置,结果吞吐上不去,到处找原因。我的习惯是,先花半天时间把集群的物理拓扑摸清楚,再动任何参数。
需要摸底的信息至少有这几项:
- 机器数量,每台机器上有多少张卡。
- 卡之间的互连拓扑,是不是每张卡到其他卡都有等价的直连,还是要经过跳转。
- 网卡型号、速率、挂载在哪个 PCIe 通道上。
- 节点间网络是 InfiniBand 还是 RoCE,有没有开 PFC 流控、ECN 拥塞通知。
- 集群里是否有其他任务在占用网络,造成带宽竞争。
这些信息决定了后面参数怎么调。一个“机内卡间全互联、机间网络无拥塞”的集群,和一个“机内拓扑不对称、机间偶尔拥塞”的集群,最优配置完全是两套。
4.2 关键参数与配置建议
下面这些参数是我在实际调优中会重点关注的,以伪代码形式给出,方便理解每一项的含义。具体默认值以你使用的开源仓库文档为准:
# 伪代码:专家并行通信库关键配置 config = { "expert_parallel_size": 8, # 专家并行度,取决于专家数跨卡分布 "inflight_tokens_limit": 4096, # 在途Token上限,带宽受限可调大,延迟敏感调小 "overlap_comm_compute": True, # 是否开通信与计算重叠,一般建议开 "use_dual_path": True, # 是否启用机内互连+机间网络双路发送 "mem_buffer_size": 4096, # 显存管理器预分配缓冲区大小 "load_balance_strategy": "top_balanced", # 专家负载均衡策略 "congestion_window": 64, # 拥塞窗口,出现网络排队时调小 }要注意,inflight_tokens_limit 并不是越大越好。实验时可以从 1024 开始,每翻一倍观察一次吞吐曲线,找到拐点。拐点出现的位置通常在网络满载但还没排队的时候。此时吞吐最高、延迟可控,再往上调只会徒增内存压力。
mem_buffer_size 也是一样。预分配太大会占用显存,挤占正常计算的空间;太小会导致 Token 到达时没有缓冲,不得不等待显存释放。需要根据序列长度和 token 总量估算一个合理区间,再通过实测微调。
4.3 性能观测指标与基准测试方法
验证这套通信方案的效果,不能只看训练 loss 降没降。我建议固定模型、固定数据、固定优化器,只改变通信配置,做几组对照实验,重点看以下指标:
- 单步训练时间:最直观、最综合的指标。同样配置下步长越短,说明系统越快。
- 每秒吞吐 Tokens / 卡:更能反映真实效率。
- MFU(Model FLOPs Utilization):模型算力利用率,理想值接近 1,实际能到 0.5 以上就很不错了。
- 通信开销占比:统计每步训练里通信相关 Kernel 的时间占比。如果这个值超过 40%,通信就是头号瓶颈,调模型参数没用。
- All-to-All 分发延迟:单独测 Token 从发出到全部到达的时间,判断通信内核是否高效。
具体操作时,先把所有重叠和双路功能都关掉,跑一组基线,记录步长和吞吐。然后逐步打开通信计算重叠、双路发送、显存切换,每次只改一个变量。这样最终性能提升来自哪些设置,一清二楚。
我实际踩过的坑是,有人直接照搬网上一个万卡集群的配置,跑在 32 卡集群上,结果步长反而比默认配置慢了一倍。原因很简单,小集群网络没那么拥堵,激进的双路和超大在途 Token 反而增加了额外的协议开销。配置必须针对自己的集群规模重新测。
5. 实测中的常见问题与排查心得
5.1 吞吐上不去:别急着调 Batch Size
分布式训练吞吐低,第一反应往往是调大 batch size,加大计算量,想把卡“喂饱”。但很多时候问题根本不在计算侧,而在通信侧。
排查方法很简单:打开 profiler 工具,看每个 step 的时间线。如果发现大部分时间 GPU Kernel 都在等待远端数据,或者通信 Kernel 占据了一条很长的条形,那就说明通信已经成了瓶颈。这时候调 batch size 只会加剧通信压力,正确做法是调整通信参数,比如增大在途 Token 上限、开启双路发送、检查是不是单路径把所有数据都压在一个网络接口上。
5.2 跨节点通信拥塞:流控与拥塞窗口
真实环境中,跨节点通信拥塞是最常见的。表现是单步训练偶尔卡顿,延迟抖动明显,短时间吞吐骤降,然后恢复。
这种问题往往不是通信库代码的 bug,而是网络层丢包或排队导致的。RoCE 网络尤其明显,如果 PFC 流控配置不当,一个节点的发送队列积压会把拥塞扩散到整个网络中。调通信库的拥塞窗口参数,让它对拥塞信号更敏感,经常能缓解问题。
更彻底的做法是,确认交换机的流控策略是否合理,避免把丢包重传的负担全扔给上层。用 ECN 标记拥塞,让通信库感知后主动降速,比等 TCP 重传被动反应优雅得多。
5.3 长序列训练时的显存碎片与 OOM
长序列训练出现 OOM,很多人都遇到。但我要提醒一个容易被忽略的点——显存碎片。
当 Token 持续被切边、换入换出,显存里会出现很多不连续的小空闲块。新来的大块 Tensor 找不到连续空间,即使总剩余显存还够,也直接 OOM。显存管理器的缓冲区预分配策略在这里很关键。预分配的缓冲区能减少频繁申请和释放导致的外部碎片。如果跑长序列频繁 OOM,先把 mem_buffer_size 调大一点,看问题是否缓解。还不行,再考虑降低单卡 batch size,但一定要先排除碎片的因素。
5.4 多路径不均衡:从拓扑视角找原因
有时双路发送已经开了,但性能提升不明显。检查一下是不是两条路径都走了同一个出口。
比如机内互连的流量和 RDMA 的流量最终都汇聚到同一个 PCIe switch 上,或者同一个网卡驱动上,那“双路”只是逻辑上的,物理上仍是一条独木桥。这时需要看物理拓扑,调整数据路由,让不同目标走不同的物理通道,才能真正把带宽用起来。
6. 开源“算力地基”给国产生态带来的变化
6.1 从依赖商业闭包到自主可控的软件栈
商业闭源通信库最大的问题,不是不好用,而是不可见、不可改。当你的集群规模扩大,遇到一个只在特定拓扑和负载下出现的通信性能问题,拿到闭源库里排查往往是束手无策的,只能等厂商发新版,或者给一个不痛不痒的 workaround。
这套开源基础设施把核心通信逻辑完整暴露出来,意味着自研硬件团队、集群运维团队、算法工程团队,都可以对照自己的硬件和业务场景去修改、适配、优化。不用再看闭源黑盒的脸色。这是从“能用某个库”到“掌握某类技术”之间的一步实质跨越。
6.2 硬件与系统的适配空间更大了
国产芯片、国产网卡、国产互连方案要真正进入大模型训练和推理的主战场,除了要有足够强的硬件指标,还必须有一层好用的系统软件支撑。过去很多新硬件适配大模型集群时,最大的成本就是花在闭源通信库的支持上——能不能支持、支持到什么程度、性能释放是否充分,都不可控。
现在这套开源通信栈提供了适配层,新硬件团队可以对照源码做移植,验证自己的网卡和互连是否能跑通 MoE 场景的高效通信。它让系统软件不再成为国产硬件进入大模型生态的拦路石,反而变成可以主动去啃的技术路线。
6.3 后续可以怎么延展
从这套通信库出发,能看到几个明确的技术延展方向。
一是和推理引擎做深度集成。通信库解决的问题在训练场景和推理场景都成立,尤其实时推理的延迟优化更需要通信层的配合。
二是自动并行策略。通信库暴露的调度信息可以反馈给上层的并行策略规划模块,让系统自动选择最优的专家分布和通信路径,而不是靠人工去调。
三是跨集群的资源调度。当多集群并行时,通信库不仅要感知节点内拓扑,还要感知跨集群的网络条件,做出更聪明的路径决策。
这些方向不是空想,而是只要有源码在手、有真实的集群负载做验证,就可以一步步做出来的实在优化。
最后说点我个人在实际操作中的体会。折腾底层通信这类东西,最大的感悟就是别把它当黑盒。以前我在小型集群上碰到吞吐问题,第一反应也是怀疑模型并行切分方式,后来用源码把通信流程完整跟了一遍,才发现是网络路径选择不合理。这类底层组件的调优,经验值积累得很快,但前提是你能看到源码、能改源码、能按自己的集群重新测量。开源这套东西最值钱的地方,是给了大家一张可以自己改、自己验证的“系统图纸”。建议所有在做大规模分布式训练和推理的朋友,哪怕你现在的集群还不大,也把它纳入视野。等集群规模真正上去之后,你会明白这层地基省下了多少事。