关卡阅读材料 // 03
多 GPU 扩展
当单张 GPU 放不下工作负载时,必须显式决定每张卡拥有什么数据、执行什么局部计算,以及何时交换结果。
建议边读边写下答案;时长包含代码推演与练习。
进入互动关卡→- 01导读与目标05 MIN
- 02心智模型08 MIN
- 03概念深挖15 MIN
- 04代码推演12 MIN
- 05历史生态08 MIN
- 06练习复盘12 MIN
把单 GPU 加速扩展成多 GPU 应用,并把数据划分、通信与系统拓扑纳入同一个性能模型。
关卡先解决容量、Shard 所有权与 Collective 语义;实验进一步要求观察 Rank、拓扑与 All-Reduce 时间,而不是把多张 GPU 当成自动合并的设备。
- 课程 00–02
- 至少理解一个单 GPU Kernel
- 基本分布式 Rank 概念
- NCCL
- nvidia-smi topo -m
- Nsight Systems
- MPI 或 torchrun(任选)
导读与目标
先记住这一句
多 GPU 编程的核心不是卡的数量,而是所有权、均衡与必要通信。
完成后你应该能够
- 01
区分复制、数据并行切分、模型切分与内存超额订阅。
- 02
为多 GPU 工作负载定义明确且均衡的数据所有权。
- 03
根据下一步所需结果选择 All-Reduce、Reduce、All-Gather 等通信语义。
- 04
从计算、通信、拓扑与 Straggler 分析扩展效率。
建立心智模型
- 01切分
先把模型或数据分成每张 GPU 能容纳、工作量相近的 Shard。
- 02局部
每个 Rank 只在自己的 Shard 上计算,尽可能延长独立工作区间。
- 03通信
只有下一步需要全局状态时,才用 Collective 组合局部结果。
概念深挖
显存不会自动合并
四张 16 GB GPU 不是一块透明的 64 GB 内存。程序仍要定义分片、地址可达性和通信。
最慢 Rank 决定同步点
即使所有 Shard 都能放下,不均衡的计算或通信也会制造 Straggler。
All-Reduce 是语义
它对所有 Rank 的输入执行归约,并让每个 Rank 得到同一个结果;具体算法与拓扑可由通信库选择。
容量问题首先是所有权问题
当 24 GB 状态放不进 16 GB 显存时,增加线程或 Stream 都无法解决。多 GPU 方案必须回答:哪些参数、激活或数据属于哪个 Rank?是否有状态被复制?谁负责更新?从一开始写清所有权,才能判断容量是否真的下降。
Data Parallel 通常复制模型并切分 Batch,因此不一定解决单个模型过大;Tensor 或 Pipeline Parallel 会切模型的宽度或深度。Unified Memory 可以提供地址与迁移机制,但也不等于把所有显存无成本地融合。
停下来想一想模型本身就大于单卡显存,仅增加标准 Data Parallel Rank 能解决吗?+
参考答案通常不能。每个 Rank 仍需完整模型副本;应考虑模型状态切分、Tensor/Pipeline Parallel 或其它 Sharding。
Collective 选择来自消费者需求
通信原语应该从下一步需要什么结果倒推。只有一个 Root 需要总和时可用 Reduce;所有 Rank 都需要总和时用 All-Reduce;每个 Rank 持有不同片段且所有 Rank 都需要完整拼接时用 All-Gather。语义选错会搬运不必要的数据。
NCCL Communicator 定义参与 Rank,Collective 通常在 CUDA Stream 上异步排队。通信 Buffer 的生命周期、Stream 依赖和每个 Rank 的调用顺序都必须一致,否则可能读到未完成数据或造成集体等待。
停下来想一想所有 Rank 只需保留归约结果的一部分,哪种原语可能比 All-Reduce 更匹配?+
参考答案Reduce-Scatter:它完成归约,同时把结果分片分发给各 Rank,避免每个 Rank 保存完整结果。
扩展效率由最慢路径决定
理想情况下四张 GPU 把局部计算缩短到四分之一,但真实时间还包含通信、同步、启动和不均衡。若一个 Rank 处理 12 GB、其它 Rank 只处理 6/4/2 GB,所有人都会在 Collective 等待最慢 Rank。
拓扑决定 Rank 间路径:同一 NVLink 域、跨 PCIe Switch 或跨节点网络的成本不同。好的库会做拓扑感知,但程序仍需要选择并行组、分片形状与通信频率。强扩展到局部任务过小时,通信比例会持续上升。
停下来想一想四卡都未满载,为什么增加第五张卡仍可能变慢?+
参考答案新增 Rank 会增加协调与通信,局部任务又变小;若通信与启动成本超过减少的计算时间,总时间会增加。
把概念放回代码
01local = shard(dataset, rank, world_size);02grad = backward(local);03ncclAllReduce(grad, grad, count, ncclFloat,04 ncclSum, communicator, stream);05optimizer.step(grad);代码逐段推演
- 01SHARDRank 只加载自己的数据
分片函数应可重复、无重叠或有意复制,并让工作量与内存接近均衡。
- 02LOCAL延长无通信计算区间
backward(local) 只访问当前 Rank 拥有的状态,避免在细粒度操作间频繁交换。
- 03REDUCE匹配全局语义
本例每个 Rank 都要更新同一模型副本,因此 All-Reduce 让所有 Rank 得到梯度和。
- 04STREAM通信也有依赖边界
NCCL 调用排入 Stream;优化器必须在通信完成后读取 Buffer,可通过同 Stream 顺序或 Event 保证。
知识图谱
补充参考 · 不要求一次读完,也不计入核心 60 分钟
核心术语
- Rank
- 分布式程序中的逻辑参与者,通常绑定一张 GPU;Rank 编号不等同于固定物理设备编号。
- Shard
- 按明确规则切分后由某个 Rank 拥有的数据、参数或激活子集。
- Collective
- 所有参与 Rank 按共同顺序调用的通信操作,如 All-Reduce、All-Gather 与 Reduce-Scatter。
- Topology
- GPU 之间经 PCIe、NVLink、交换芯片或网络形成的实际连接关系。
- Straggler
- 在同步点最后到达的 Rank;它可能由计算不均、通信路径或系统噪声产生。
带数字推演
- 01先看容量
14/10 和 12/12 都小于每卡 16 GB,因此容量上都可行。
- 02再看均衡
14/10 会让一个 Rank 工作更多;12/12 更接近同步程序所需的均衡所有权。
- 03计入通信
若两卡计算 200 ms、通信 50 ms,总时间 250 ms;加速比 400/250 = 1.6×。
诊断手册
增加 GPU 后几乎没有加速
- 先检查
- 每 Rank 计算量、Collective 占比、消息大小与拓扑路径
- 需要的证据
- 逐 Rank 时间线、通信带宽和强/弱扩展曲线
Collective 挂起
- 先检查
- 所有 Rank 是否以相同顺序调用、Count/类型是否一致、错误 Rank 是否已退出
- 需要的证据
- 逐 Rank 日志、NCCL 调试日志与最后成功的 Collective 序号
同步点总在等同一张卡
- 先检查
- Shard 大小、输入分布、热降频、NUMA 和链路差异
- 需要的证据
- 逐 Rank 计算/通信时间分布,而不是全局平均值
从硬件到生态
- 01PCIe 多 GPU
应用显式管理设备、Peer 访问和复制。
容量可以切分,但通信容易成为新瓶颈。 - 02NVLink / 交换互连
GPU 间带宽和拓扑选择空间扩大。
并行策略必须开始理解物理邻接关系。 - 03NCCL + 框架并行
Collective 算法、拓扑发现与 Stream 集成被库封装。
开发者关注通信语义和切分策略,同时仍需用 Profiler 验证代价。
硬件与生态坐标
P100 把 HBM2 与第一代 NVLink 带入数据中心 GPU 系统,改变了本地带宽与 GPU 间数据移动的代价。NCCL 则把 All-Reduce 等 Collective 变成可复用的软件原语。互连更快,但拓扑与通信仍不会消失。
练习与复盘
四个 Rank 都需要梯度总和并继续更新,哪种语义最直接?
- A. 每张卡保留自己的局部梯度
- B. All-Reduce
- C. 把完整数据复制四份后不通信
查看答案+
All-Reduce 同时完成归约与结果分发,让每个参与 Rank 得到同一个全局结果。
四张 16 GB GPU 完整复制 24 GB 模型,为什么总显存 64 GB 仍然失败?
提示+
每张卡实际要拥有多少?
参考答案+
每张卡都需要 24 GB,单卡仍溢出。总容量只有在程序明确切分所有权时才有意义。
四个 Shard 为 12/6/4/2 GB,显存都放得下。同步训练的主要风险是什么?
提示+
Collective 何时开始?
参考答案+
12 GB Rank 的局部计算更久,其他 Rank 会在同步点等待,形成 Straggler。应重新分片或按真实计算成本均衡。
每个 Rank 产生不同长度的特征片段,随后每个 Rank 都需要完整序列。选择什么 Collective?
提示+
需要拼接而不是求和。
参考答案+
All-Gather(长度不同时可能用 All-Gatherv 或先交换尺寸)。All-Reduce 会错误地对值做归约。
多 GPU 效率从 8 卡到 16 卡显著下降,应收集哪些证据?
提示+
拆分计算、通信、等待和拓扑。
参考答案+
比较局部 Kernel 时间、Collective 时间、各 Rank 到达时间、消息大小与链路拓扑,并检查并行组与分片是否均衡。
可选实践实验
不计入核心 60 分钟 · 需要相应 CUDA / GPU 环境
实验目标
验证两张 GPU 上的数据所有权与 All-Reduce
让每个 Rank 处理不同输入并通过 All-Reduce 得到相同全局结果,同时说明消息路径与同步成本。建议步骤
- 01
打印 Rank、设备、局部输入与局部结果,先确认每个 Rank 只拥有预期 Shard。
- 02
运行 NCCL All-Reduce,逐 Rank 验证归约结果,并检查 Buffer 与 Stream 生命周期。
- 03
记录 nvidia-smi topo -m,说明两个 Rank 是否在同一高速互连域。
- 04
改变消息大小并记录计算、Collective 与等待时间;避免从一个规模外推通用结论。
提交逐 Rank 输出、拓扑摘要和至少三个消息规模的时间表,并写出扩展效率受限于哪一段。
把 All-Reduce 替换为 Reduce-Scatter + All-Gather,比较语义、内存占用与通信时间。