CUDA系统拆解-18-NCCL、多GPU与通信隐藏:规模扩展怎么不被通信拖垮
CUDA系统拆解-18-NCCL、多GPU与通信隐藏:规模扩展怎么不被通信拖垮
本文是「CUDA系统拆解」系列第 18 篇。
系列导读:CUDA系统拆解-00-导读:从编程模型到 AI 推理系统的学习路线
上一篇:CUDA系统拆解-17-vLLM、TensorRT-LLM 与 Continuous Batching:CUDA 为什么最终连到推理系统
1. 这篇解决什么问题
这一篇讲的是:当系统从单 GPU 走向多 GPU 之后,性能问题为什么会突然变成“通信问题”。
核心要回答 5 件事:
- 多 GPU 新增的核心矛盾到底是什么。
NCCL到底处在什么位置,为什么它几乎是 NVIDIA 多 GPU 系统的默认基础设施。Broadcast、AllReduce、AllGather、ReduceScatter这些 collective 为什么重要。- 为什么
ring、拓扑感知和链路选择会直接影响扩展效率。 - 为什么
overlap、pipeline、通信隐藏常常决定大模型系统最终能跑多快。
如果这篇只记住一句话,那就是:
单卡优化主要在回答“数据怎么在一张卡里少搬”,多卡优化主要在回答“数据怎么在多张卡之间尽量少搬、尽量晚搬、尽量边搬边算”。
2. 先记住的核心结论
- 多 GPU 引入的新核心矛盾通常不是“算力不够”,而是“跨卡通信太贵”。
NCCL是 NVIDIA 的高性能 GPU collective communication 库,重点不是只提供 API,而是把拓扑感知、通信算法和 CUDA 执行模型结合起来。Broadcast、AllReduce、AllGather、ReduceScatter是多 GPU 系统里最常见的 collective,分别对应不同的数据分发、聚合和收集需求。AllReduce是最经典的多 GPU 同步原语之一,因为它代表了“大家先规约,再都拿到最终结果”这类高频需求。ring常见是因为它对大消息传输带宽利用率很好;但并不存在永远最优的单一算法,拓扑和消息规模会影响选择。overlap的本质是让通信时间和计算时间重叠,尽量把等待藏进已有计算里,而不是让通信成本真的消失。pipeline的本质是分阶段并行;bubble是流水线没被填满带来的空闲。- 在大模型训练和推理里,很多最终性能差距都来自通信组织质量,而不是单个 kernel 的峰值。
3. 正文讲解
3.1 多 GPU 的本质矛盾是什么
一张 GPU 上,性能问题主要集中在:
- 算子组织
- 访存层级
- launch 开销
- 同步和调度
到了多 GPU,问题突然多出一层:
每张卡本地算得很快,但卡和卡之间交换数据很慢。
这就是多 GPU 最核心的新矛盾。
从代价层级看,可以粗略理解成:
- registers / shared memory 最快
- 本地 HBM 也很快
- 同机其他 GPU 更慢
- 跨机 GPU 更慢
所以多 GPU 优化和单 GPU 优化在逻辑上其实是一脉相承的:
- 单 GPU:尽量少访问慢层级
- 多 GPU:尽量少做跨卡交换
3.2 NCCL 到底是什么
NCCL 是 NVIDIA 提供的高性能 GPU collective communication 库。它要解决的不是“怎么写一个 kernel”,而是“多张 GPU 怎么高效交换数据”。
它最重要的价值不只是接口,而是三件事:
- 提供常见 collective communication 原语
- 感知硬件拓扑并选择更合适的通信路径
- 和 CUDA stream、异步执行模型配合,方便做 overlap
所以理解 NCCL 时,不要把它只看成“多卡 API 集合”。更准确地说,它是 GPU 世界里的通信执行基础设施。
3.3 什么是 collective communication
所谓 collective,可以先理解成:
一组 GPU 按某种固定规则一起交换和重组数据。
最常见的几类是:
Broadcast
- 一个 GPU 把数据发给所有 GPU
- 常见于参数分发、初始化、共享配置同步
AllReduce
- 每个 GPU 各有一份数据
- 先按元素规约,比如
sum - 再把最终结果发回所有 GPU
- 这是最经典的 collective 之一
AllGather
- 每个 GPU 提供自己的一块数据
- 所有 GPU 最终都拿到拼接后的完整结果
- 常见于张量并行后的结果收集
ReduceScatter
- 先做规约
- 再把规约后的结果分块散给不同 GPU
- 很适合那些不需要所有 GPU 都拿完整结果的场景
这些 collective 之所以重要,是因为多 GPU 系统几乎总要在“本地算一部分”和“全局拼结果”之间来回切换。
3.4 为什么 AllReduce 这么重要
如果只记一个 collective,那通常先记 AllReduce。
原因很简单:它代表了多 GPU 协作里最经典的一类需求。
它同时做两件事:
- 聚合
- 分发
所以它经常很贵,也经常是扩展瓶颈。
训练里它典型对应梯度同步;推理里在某些张量并行和中间结果合并路径上,也会遇到类似问题。
面试里如果问“为什么多卡不线性加速”,一个高频原因就是:
本地计算虽然分摊了,但每一层或每一步都可能新增 collective 成本。
3.5 为什么 ring 这么常见
ring 是最常见的 collective 实现直觉之一,尤其适合大消息场景。
直观上可以理解成:
- GPU 组成一个环
- 每轮每张卡只和相邻卡交换一块数据
- 数据一边转、一边规约或收集
它的优势主要是:
- 链路利用比较均衡
- 更容易把所有链路都忙起来
- 对大消息时的带宽利用通常不错
但不要把它神化成唯一正确答案。
真实系统里还会有:
- tree
- hierarchical
- 拓扑感知的混合策略
选择和这些因素有关:
- 消息大小
- GPU 数量
- NVLink / PCIe / IB 拓扑
- 单机还是跨机
所以 NCCL 的强点之一,就在于它不是死板地用一种算法,而是会结合拓扑和场景做更合理的选择。
3.6 为什么拓扑感知非常关键
多 GPU 性能不只取决于“用了几张卡”,还取决于“这些卡之间到底怎么连”。
例如:
- 有的 GPU 之间有 NVLink
- 有的只能走 PCIe
- 跨机要走 IB 或其他网络
- 某些链路可能共享交换资源
如果通信路径选得不好,就会出现:
- 热点链路
- 带宽利用不均
- 某些 GPU 长时间等待
所以 NCCL 的价值很大一部分在于:
它在做 topology-aware 的通信组织,而不是只在做“把字节发出去”。
3.7 overlap、pipeline、通信隐藏是什么意思
这几个词经常一起出现,但不是一回事。
overlap
- 指通信和计算重叠
- 理想目标是让总时间更接近
max(计算时间, 通信时间),而不是两者简单相加
pipeline
- 指把系统拆成多个阶段,让不同阶段并行推进
- 常见于 pipeline parallel,也常见于更一般的数据流分阶段组织
communication hiding
- 指尽量把通信等待藏进已有的计算时间里
- 它依赖 overlap,但不等于“通信成本不存在”
这三者的重要性在于:
在多 GPU 系统里,最怕的不是“有通信”,而是“通信裸露在关键路径上,所有卡都在等”。
3.8 pipeline bubble 是什么
一旦谈 pipeline,就绕不开 bubble。
bubble 可以理解成:
- 流水线没有被填满时产生的空闲
- 或者不同 stage 不平衡导致的等待
典型来源包括:
- stage 切分不均衡
- micro-batch 太少
- 某些阶段明显更慢
所以 pipeline 的关键不只是“分阶段”,还包括:
- 阶段怎么切
- 每阶段负载是否均衡
- 是否有足够多的 micro-batch 来填满流水线
3.9 为什么多 GPU 常常不线性加速
这是最常见的系统问题之一。
多卡扩展不线性的典型原因包括:
- 通信占比上升
- 通信无法被完全隐藏
- 切分过细,导致本地计算太碎
- launch 和同步开销比例上升
- 拓扑不理想
- 负载不均衡
所以多 GPU 扩展效率的本质问题是:
卡虽然变多了,但“等待”的部分也变多了。
3.10 和并行策略的关系
通信模式不是独立存在的,它通常由并行切分方式决定。
常见直觉是:
data parallel更容易出现梯度同步类通信tensor parallel经常需要AllGather、ReduceScatter、AllReducepipeline parallel更强调相邻 stage 之间的传递和流水线组织expert parallel / MoE会更敏感于 token 分发和跨设备交换
这意味着真正分析一个多 GPU 系统时,不应该先问“用了什么 collective”,而应该先问:
- 模型怎么切
- 数据怎么切
- 每一步的通信到底发生在哪里
4. 和 AI 推理的关系
对大模型推理来说,这一篇非常关键,因为推理尤其容易暴露通信问题。
原因之一是 decode 阶段往往本地计算时间短:
- 每步新增计算量小
- kernel 更碎
- launch 更频繁
- 于是通信更难被隐藏
所以在大模型推理里,很多工程动作最终都在围绕同一个目标:
- 减少每步必须做的跨卡同步
- 尽量让通信和计算重叠
- 让切分、调度、KV locality 和通信路径尽量一致
这也是为什么 AI infra / 推理岗位会非常看重你对 NCCL、collective、overlap、pipeline bubble 的理解。它们直接决定多卡系统能不能真正跑出吞吐。
5. 常见误区
NCCL不只是“多卡 API 库”,它的真正价值在于 topology-aware 通信和与 CUDA 执行模型的集成。overlap不是让通信成本消失,而是尽量把通信等待藏进已有计算里。ring不是永远最优,只是它在很多大消息场景下带宽利用很好。- 多 GPU 不线性加速不一定是 kernel 太慢,很多时候是通信、同步或负载不均衡在拖后腿。
- pipeline 不等于自动高效;如果 stage 切分差或 bubble 大,流水线本身也会浪费很多时间。
6. 复习自测
- 为什么说多 GPU 新增的核心矛盾通常是通信成本,而不是单纯算力不足?
NCCL解决的核心问题是什么?为什么不能只把它理解成一组 API?Broadcast、AllReduce、AllGather、ReduceScatter各自更适合哪类数据流场景?- 为什么
AllReduce经常成为多 GPU 扩展瓶颈? ring为什么常见?它的优势和局限分别是什么?- 为什么拓扑感知会直接影响多 GPU 性能?
overlap、pipeline、communication hiding、bubble分别在讲什么?- 为什么 decode 阶段的多 GPU 推理往往比 prefill 更容易暴露通信问题?

