1. 从一线视角理解AI-Infra的真实含义
1.1 为什么这个方向值得投入精力
AI-Infra这个词这两年出现的频率越来越高,但很多人对它的理解还停留在“搞GPU集群”或者“搭训练平台”的层面。我刚开始接触这个方向的时候也是这么想的,觉得无非就是把卡插上、把驱动装好、把任务跑起来。真正在一线摸爬滚打一段时间之后才发现,这个领域的深度远超表面看到的东西。
所谓AI-Infra,拆开来看就是“为人工智能负载提供底层支撑的基础设施体系”。它涵盖的范围非常广:从最底层的芯片选型和服务器上架,到中间层的分布式通信、存储编排、资源调度,再到上层面向算法团队的训练框架适配、推理服务部署、监控告警体系搭建。每一层都有大量的工程细节和踩坑空间。
为什么这个方向值得投入?原因很直接。当前AI模型的参数规模从几亿膨胀到几千亿甚至更大,单卡根本放不下,单机也扛不住。一个千亿参数级别的模型,光是权重就需要几百GB的显存来承载,加上优化器状态、梯度、激活值,实际需求可能是权重体积的十几倍。这就意味着你必须把几十张甚至上百张加速卡通过高速互联组成一个协同工作的整体。而这个“组成整体”的过程,涉及到的技术栈横跨硬件、网络、操作系统、分布式系统、编译优化等多个领域,不是随便拉一个后端工程师就能搞定的。
我个人的判断是,未来三到五年内,AI-Infra方向的人才缺口会持续扩大。算法岗的竞争已经非常激烈了,但真正能把大规模训练集群跑稳、把推理延迟压下来、把GPU利用率提上去的工程师,始终是稀缺的。这个方向的门槛在于它要求你既懂底层系统,又理解上层AI负载的特点,两者缺一不可。
1.2 这个系列适合什么样的读者
这个系列我计划写成一种“从业者笔记”的形式,不是教科书式的系统讲解,而是把我自己在实际工作中遇到的问题、解决的思路、踩过的坑,按照主题一块一块地整理出来。第一章先聊整体认知和几个核心基础问题,后续章节会逐步深入到具体的工具链、调优手段和架构设计。
如果你是有一定后端或运维基础,想往AI-Infra方向转型的工程师,这个系列应该比较适合你。如果你已经在做相关的工作,但总觉得知识比较零散、不成体系,也可以跟着这个系列一起梳理。但如果你完全没有任何Linux基础、没碰过命令行、不理解进程和内存这些基本概念,那可能需要先补一下基础再来。
我尽量不堆砌术语,遇到必须用的专业词汇会做解释。但有些东西确实需要你动手试过才能理解,光看文字是不够的。所以每篇文章里我会尽量给出可以复现的操作步骤和验证方法,你跟着做一遍,比看十遍文字都管用。
2. 核心基础:算力、显存与通信的三角关系
2.1 算力不是唯一指标,显存和带宽同样致命
很多人评估一张加速卡的时候,第一眼看的是算力数值,比如多少TFLOPS。这个指标当然重要,但它远不是全部。在实际的AI训练场景中,你经常会发现算力还没跑满,显存先爆了,或者通信带宽先成了瓶颈。
我举个具体的例子。假设你要训练一个模型,单张卡的显存是80GB。模型的权重加上梯度、优化器状态,假设总共需要60GB。看起来还剩20GB对吧?但训练过程中还有激活值需要存储,激活值的大小跟你的批次大小和序列长度直接相关。批次稍微开大一点,激活值就能吃掉几十GB。结果就是显存不够,训练直接崩掉。这时候你的算力再强也没用,因为根本跑不起来。
所以评估硬件的时候,我一般会看三个核心指标:有效算力、显存容量、显存带宽。有效算力决定了计算密集型操作的速度,显存容量决定了你能跑多大的模型和多小的批次,显存带宽决定了数据搬运的效率。三者缺一不可,任何一个短板都会成为瓶颈。
这里有一个经验公式可以参考:对于Transformer类模型,训练时的显存占用大致可以用以下方式估算:
- 模型权重:参数量 × 精度字节数(FP16是2字节,FP32是4字节)
- 梯度:参数量 × 精度字节数
- 优化器状态:参数量 × 系数(Adam通常是2倍参数量 × 4字节)
- 激活值:与批次大小、序列长度、层数、隐藏维度相关,需要实测
以一个70亿参数的模型为例,用FP16混合精度训练,Adam优化器:
- 权重:7B × 2字节 = 14GB
- 梯度:7B × 2字节 = 14GB
- 优化器状态:7B × 8字节 = 56GB(Adam的动量和方差各4字节)
- 合计已经84GB了,还没算激活值
这就是为什么70亿参数的模型在80GB显存的卡上做全参数训练会非常吃力,通常需要配合ZeRO之类的显存优化技术,把优化器状态和梯度切分到多张卡上。
2.2 卡间通信:被低估的性能杀手
当你把训练扩展到多卡之后,卡与卡之间的通信就成了一个绕不开的问题。数据并行的时候,每张卡算完梯度需要做AllReduce来同步;模型并行的时候,层与层之间的激活值需要传递;流水线并行的时候,阶段之间需要传递中间结果。这些通信操作如果效率不高,你的多卡扩展效率就会惨不忍睹。
我见过不少团队,买了很贵的卡,组了很大的集群,结果实际训练速度只有单卡的几倍,扩展效率极低。排查下来往往就是通信瓶颈。卡间通信的性能取决于几个因素:互联方式(PCIe还是NVLink)、拓扑结构(Ring还是Switch)、通信库的配置(NCCL的参数调优)。
以PCIe和NVLink为例,PCIe 4.0 x16的双向带宽大约是64GB/s,而NVLink 4.0的单卡带宽可以到900GB/s。差距是数量级的。如果你的模型并行策略需要频繁地在卡之间传递大量数据,走PCIe就会成为严重的瓶颈。
注意:不是所有多卡场景都需要NVLink。数据并行做AllReduce的时候,通信量相对可控,PCIe也能接受。但张量并行(Tensor Parallelism)因为每层都要通信,对带宽要求极高,没有NVLink基本跑不出好的效率。
2.3 存储IO:最容易被忽视的一环
训练数据从磁盘读到内存、再从内存送到显存,这条链路的速度也会影响整体效率。特别是当你的数据集很大、需要频繁读取的时候,存储的吞吐能力就直接决定了GPU会不会“饿着”。
我遇到过一个典型场景:训练一个图像相关的模型,数据集有几百GB的小文件。用的是普通的机械硬盘做存储,结果每个epoch的数据加载时间比实际计算时间还长。GPU利用率长期在30%以下。后来换成NVMe SSD做缓存,把数据预处理和加载并行化,GPU利用率才拉到80%以上。
所以做AI-Infra规划的时候,存储这一块不能随便对付。至少要保证数据读取的速度能跟上GPU的计算速度,否则就是浪费算力。常用的做法包括:用高速SSD做数据缓存层、把数据集预处理成更适合顺序读取的格式(比如WebDataset或者TFRecord)、使用多进程数据加载等。
3. 分布式训练的核心思路与方案选型
3.1 数据并行、模型并行与混合并行的适用场景
分布式训练的策略选择,本质上是在“计算效率”和“通信开销”之间找平衡。不同的并行方式适合不同的场景,没有银弹。
数据并行是最直观的方式:每张卡持有完整的模型副本,各自处理不同的数据批次,然后同步梯度。优点是实现简单,缺点是每张卡都要存完整的模型和优化器状态,显存占用高。而且当卡数增多时,AllReduce的通信开销会线性增长。数据并行适合模型能单卡放下、但训练数据量很大的场景。
模型并行是把模型切开放到不同的卡上。有两种切法:按层切(流水线并行)和按层内维度切(张量并行)。流水线并行是把不同的层分配到不同的卡上,数据像流水线一样依次经过各张卡。缺点是会有“气泡”存在,即某些卡在等待上一阶段的输出时处于空闲状态。张量并行是把同一层的矩阵运算切分到多张卡上,通信非常频繁,通常只在单机内用NVLink互联的卡之间使用。
混合并行是把上面几种方式组合起来。比如在一个节点内用张量并行(利用NVLink的高带宽),在节点间用流水线并行(减少跨节点通信),同时叠加数据并行(提高吞吐)。当前大规模训练基本都用混合并行策略。
选择哪种方案,核心看两个维度:模型能不能单卡放下,以及你的集群互联带宽是多少。下面这个表格可以帮你快速判断:
| 场景特征 | 推荐策略 | 原因 |
|---|---|---|
| 模型单卡可放下,数据量大 | 数据并行 | 实现简单,扩展性好 |
| 模型单卡放不下,单节点内 | 张量并行 | 利用NVLink高带宽 |
| 模型超大,跨节点 | 流水线并行+数据并行 | 减少跨节点通信 |
| 模型超大且节点内卡多 | 张量+流水线+数据并行 | 综合各方案优势 |
3.2 通信原语:AllReduce、AllGather与ReduceScatter
理解分布式训练,绕不开几个核心的通信原语。这些概念看起来抽象,但用生活化的方式理解就很简单。
AllReduce:每张卡都有一份数据,操作之后每张卡都得到所有卡数据的汇总结果。比如四张卡分别有1、2、3、4,AllReduce求和之后,每张卡都得到10。数据并行同步梯度用的就是这个。
AllGather:每张卡有一份数据,操作之后每张卡都得到所有卡的数据拼接。比如四张卡分别有1、2、3、4,AllGather之后每张卡都得到[1,2,3,4]。ZeRO优化器在收集参数的时候用这个。
ReduceScatter:每张卡有一份数据,操作之后每张卡得到汇总结果的一部分。比如四张卡分别有[1,2,3,4]、[5,6,7,8]、[9,10,11,12]、[13,14,15,16],ReduceScatter求和之后,第一张卡得到[28,32],第二张卡得到[36,40],以此类推。ZeRO在切分梯度的时候用这个。
Ring AllReduce是最经典的实现方式,它把通信过程分成两个阶段:ReduceScatter和AllGather。每张卡只和相邻的卡通信,带宽利用充分,而且通信量与卡数无关(只与数据量有关)。这就是为什么数据并行在卡数增加时,通信效率不会显著下降的原因。
实操心得:NCCL是当前最常用的集合通信库。调优的时候可以关注几个环境变量:NCCL_ALGO可以指定用Ring还是Tree算法,NCCL_PROTO可以指定协议,NCCL_IB_HCA可以指定用哪块网卡。这些参数在不同拓扑下效果差异很大,需要实测。
3.3 显存优化技术:ZeRO、梯度检查点与混合精度
显存不够是训练大模型时最常遇到的问题。除了加卡之外,还有几种技术手段可以在不增加硬件的情况下缓解显存压力。
ZeRO(Zero Redundancy Optimizer)的核心思想是消除数据并行中的显存冗余。在标准的数据并行中,每张卡都存了完整的优化器状态、梯度和参数,这其实是浪费的。ZeRO把这三样东西分别切分到不同的卡上,需要的时候再通过通信收集回来。ZeRO有三个阶段:Stage 1切分优化器状态,Stage 2再切分梯度,Stage 3再切分参数。切得越细,显存省得越多,但通信量也越大。
梯度检查点(Gradient Checkpointing)是用计算换显存的手段。正常训练时,前向传播的中间激活值都要存下来,供反向传播使用。梯度检查点不存所有激活值,只存一部分,反向传播时重新计算缺失的部分。这样显存占用能大幅降低,但训练速度会慢一些(因为多了重计算的开销)。通常能省50%到70%的激活值显存,速度损失在20%到30%左右。
混合精度训练是用FP16或BF16来做前向和反向计算,但保留一份FP32的权重副本用于更新。这样显存占用大约能减半,计算速度也能提升(因为低精度运算更快)。BF16比FP16的动态范围更大,不容易出现溢出问题,现在用BF16的越来越多。
这三种技术通常会组合使用。比如一个典型的配置是:BF16混合精度 + ZeRO Stage 2 + 选择性梯度检查点。具体怎么组合,取决于你的模型大小、卡的数量和显存容量。
4. 实操环境搭建与关键环节实现
4.1 从裸机到可训练集群的完整流程
这一节我把从一台裸机服务器到能跑分布式训练任务的完整流程梳理一遍。不同环境细节会有差异,但大框架是通用的。
第一步:硬件上架与基础检查。服务器上架之后,先确认所有加速卡被正确识别。用lspci | grep -i nvidia(如果是NVIDIA卡)或者对应的命令查看卡是否都在。然后检查卡之间的互联拓扑,nvidia-smi topo -m可以看到卡与卡之间是走NVLink还是PCIe,以及跨NUMA节点的连接情况。这个信息决定了你后续并行策略的选择。
第二步:驱动与CUDA安装。驱动版本和CUDA版本有对应关系,不能随便装。先确定你要用的深度学习框架需要什么CUDA版本,然后反推驱动版本。安装驱动的时候注意要禁用系统自带的nouveau驱动,否则会冲突。安装完成之后用nvidia-smi验证,能看到卡列表和驱动版本就说明成功了。
第三步:容器运行时与编排工具。现在基本没人直接在裸机上跑训练任务了,都是用容器来隔离环境。需要安装容器运行时(比如containerd或者Docker),以及GPU容器工具包,让容器内能访问到GPU设备。如果是多机集群,还需要一个编排调度系统来管理资源分配和任务排队。
第四步:通信库与网络配置。多机训练依赖高速网络,通常是InfiniBand或者RoCE。需要安装对应的驱动和通信库,配置IP地址和子网管理器。然后安装NCCL,用nccl-tests里的all_reduce_perf来验证多机通信是否正常。这一步非常关键,通信没调通,后面训练肯定跑不起来。
第五步:深度学习框架与分布式组件。安装PyTorch或你用的框架,确认能正常调用GPU。然后测试单机多卡的分布式训练,再测试多机多卡。每一步都要验证,不要跳步。
第六步:监控与日志体系。训练跑起来之后,你需要知道GPU利用率、显存占用、通信带宽、温度、功耗这些指标。常用的方案是Prometheus + Grafana,配合DCGM exporter来采集GPU指标。日志方面,建议把训练日志集中收集,方便排查问题。
4.2 单机多卡训练的最小可复现示例
下面给一个PyTorch单机多卡训练的最小示例,你可以直接拿去改。这个例子用的是DDP(DistributedDataParallel),是当前最推荐的数据并行方式。
import os import torch import torch.distributed as dist from torch.nn.parallel import DistributedDataParallel as DDP from torch.utils.data import DataLoader, DistributedSampler def setup(rank, world_size): os.environ['MASTER_ADDR'] = 'localhost' os.environ['MASTER_PORT'] = '12355' dist.init_process_group("nccl", rank=rank, world_size=world_size) def cleanup(): dist.destroy_process_group() def train(rank, world_size): setup(rank, world_size) # 创建模型并移到对应GPU model = YourModel().to(rank) ddp_model = DDP(model, device_ids=[rank]) # 数据集和分布式采样器 dataset = YourDataset() sampler = DistributedSampler(dataset, num_replicas=world_size, rank=rank) dataloader = DataLoader(dataset, batch_size=32, sampler=sampler) optimizer = torch.optim.Adam(ddp_model.parameters(), lr=1e-4) for epoch in range(num_epochs): sampler.set_epoch(epoch) # 每个epoch打乱数据 for batch in dataloader: inputs, labels = batch inputs, labels = inputs.to(rank), labels.to(rank) optimizer.zero_grad() outputs = ddp_model(inputs) loss = loss_fn(outputs, labels) loss.backward() optimizer.step() cleanup() if __name__ == "__main__": world_size = torch.cuda.device_count() torch.multiprocessing.spawn(train, args=(world_size,), nprocs=world_size)这个例子里有几个关键点需要注意。DistributedSampler确保每张卡拿到不同的数据分片,sampler.set_epoch(epoch)在每个epoch重新打乱,避免每张卡总是看到相同的数据顺序。DDP包装模型之后,梯度同步是自动完成的,你不需要手动做AllReduce。
启动方式用torchrun更规范:
torchrun --nproc_per_node=4 --nnodes=1 --node_rank=0 \ --master_addr="localhost" --master_port=12355 \ train_script.py多机的话把--nnodes改成实际节点数,每个节点指定不同的--node_rank,--master_addr指向主节点的IP。
4.3 多机训练的网络配置与验证
多机训练最容易出问题的就是网络。我整理了一个排查清单,按顺序检查基本能定位大部分问题。
首先确认所有节点的网卡状态正常,用ibstat(InfiniBand)或者ip link show查看。然后测试节点间的连通性,ping和ibping都要通。接着检查NCCL是否能正确识别网络接口,可以用NCCL_DEBUG=INFO环境变量跑一个小测试,看日志里有没有报错。
验证多机通信性能,用nccl-tests:
# 在每个节点上执行,指定主节点地址 ./build/all_reduce_perf -b 8 -e 128M -f 2 -g 8这个命令会测试从8字节到128MB的AllReduce性能。关注两个指标:带宽(bus bandwidth)和耗时。如果带宽明显低于硬件标称值,说明配置有问题。常见原因包括:用了错误的网卡、MTU设置不对、NCCL版本不匹配、拓扑识别错误等。
实操心得:多机训练时,
MASTER_ADDR一定要用所有节点都能访问到的地址,不要用localhost或者127.0.0.1。另外防火墙规则要放开相关端口,否则进程间通信会被阻断。我在这上面浪费过整整一个下午,最后发现是防火墙没关。
5. 常见问题与排查技巧实录
5.1 训练过程中的典型故障与定位思路
做AI-Infra这几年,遇到过的故障五花八门。我挑几个最有代表性的整理成速查表,方便你在遇到类似问题时快速定位。
| 故障现象 | 可能原因 | 排查手段 | 解决方案 |
|---|---|---|---|
| 训练启动即OOM | 模型+优化器状态超出显存 | 用torch.cuda.memory_summary()看显存分布 | 减小批次、开启ZeRO、用梯度检查点 |
| 多卡扩展效率低 | 通信瓶颈 | 用nccl-tests测带宽,看NCCL日志 | 调整并行策略、换用NVLink、调NCCL参数 |
| 训练中途loss变NaN | 混合精度溢出 | 检查是否有inf/nan,看grad norm | 用BF16替代FP16、加梯度裁剪、调loss scale |
| GPU利用率忽高忽低 | 数据加载瓶颈 | 看数据加载耗时和GPU计算耗时比例 | 增加DataLoader进程数、用更快的存储 |
| 多机训练hang住 | 网络不通或NCCL配置错误 | 看NCCL_DEBUG日志、检查防火墙 | 修复网络配置、统一NCCL版本 |
| 训练速度越来越慢 | 显存碎片或热降频 | 看显存碎片情况、监控温度和功耗 | 重启进程、改善散热、限制功耗 |
这张表里的每一行都是我实际踩过的坑。特别是“多机训练hang住”这一条,排查起来最费时间,因为现象就是卡住不动,没有明显报错。我的经验是先把NCCL_DEBUG设成INFO,看日志卡在哪一步,然后针对性地检查网络配置。
5.2 几个容易被忽视的配置细节
有些配置问题不会直接导致报错,但会悄悄影响性能。我列几个常见的。
共享内存大小。PyTorch的DataLoader用共享内存来在进程间传递数据。如果共享内存太小(默认可能是64MB),数据加载就会成为瓶颈。可以通过--shm-size参数在容器启动时调大,或者挂载/dev/shm到宿主机的大容量目录。
CPU亲和性。数据加载的进程如果和GPU计算进程抢CPU核心,会影响效率。可以用taskset或者numactl把数据加载进程绑定到特定的CPU核心上,避免和主进程争抢。
NUMA绑定。在多路CPU的服务器上,GPU和CPU之间的连接是分NUMA节点的。如果GPU跨NUMA访问内存,延迟会明显增加。用nvidia-smi topo -m可以看到GPU和CPU的亲和关系,启动训练时用numactl把进程绑定到对应的NUMA节点。
文件描述符限制。大规模训练时,数据加载进程可能会打开大量文件。系统的默认文件描述符限制可能不够用,需要调大ulimit -n。
这些细节单独看都不起眼,但叠加起来对性能的影响可能达到20%到30%。我在实际项目中就遇到过因为共享内存太小导致GPU利用率上不去的情况,调大之后利用率直接从60%拉到85%。
5.3 性能调优的优先级排序
面对一个性能不达预期的训练任务,应该按什么顺序去调优?我的经验是按照“影响大、改动小”的原则排序。
第一优先级是确认GPU利用率。如果利用率低于80%,说明GPU在等数据或者等通信,先解决这个问题。用nvidia-smi dmon或者DCGM看实时利用率。
第二优先级是检查数据加载。如果GPU利用率波动大,大概率是数据加载跟不上。增加DataLoader的num_workers,把数据预处理放到GPU上做,或者换更快的存储。
第三优先级是检查通信。如果单机多卡效率还行,但多机扩展效率差,那就是通信问题。用nccl-tests测实际带宽,对比硬件标称值。
第四优先级是调批次大小和学习率。在显存允许的范围内尽量开大批次,同时按比例调大学习率。大批次能提高GPU利用率和通信效率。
第五优先级是尝试编译优化。比如用PyTorch 2.0的torch.compile,或者用TensorRT做推理加速。这些手段能进一步提升计算效率,但改动成本相对较高。
这个排序不是绝对的,具体场景要具体分析。但大原则是先解决瓶颈问题,再做锦上添花的优化。不要一上来就折腾编译优化,结果发现瓶颈在数据加载上,白费功夫。
6. 从单机到集群的扩展思路
6.1 集群规模扩大后遇到的新问题
从单机8卡扩展到多机几十卡甚至上百卡,不是简单的数量叠加。每上一个数量级,都会遇到新的问题。
故障率上升。单机的时候,硬件故障概率很低。但到了几百卡的规模,卡、网卡、线缆、电源,任何一个环节出问题都会导致训练中断。所以大规模集群必须有完善的故障检测和自动恢复机制。Checkpoint要定期保存,任务要能自动重启并从最近的Checkpoint恢复。
调度复杂度增加。多个人共用集群的时候,资源分配、优先级、配额管理都变得复杂。需要一套调度系统来管理,常见的方案有Slurm、Kubernetes配合Volcano或者Kueue等。
网络拓扑影响变大。小规模的时候,网络拓扑怎么连差别不大。但到了大规模,跨交换机、跨机架的通信延迟差异就体现出来了。训练任务的卡分配要尽量在同一个交换机下,减少跨层通信。
存储压力增大。几百张卡同时读数据,存储的吞吐和IOPS压力是巨大的。需要分布式存储系统来支撑,同时要做好数据缓存和预取。
6.2 监控体系的分层设计
集群规模大了之后,监控不能只看单卡指标,需要分层设计。
最底层是硬件层监控:GPU温度、功耗、显存、ECC错误、NVLink状态、网卡状态。这些指标用DCGM exporter采集,Prometheus存储,Grafana展示。
中间层是任务层监控:每个训练任务的GPU利用率、通信带宽、loss曲线、吞吐量。这些指标需要从训练框架里打点上报,可以用TensorBoard或者WandB来收集。
最上层是集群层监控:整体资源利用率、任务排队情况、故障统计、成本分摊。这些指标帮助管理者了解集群的健康状况和使用效率。
三层监控各有侧重,缺一不可。硬件层发现问题最早,任务层帮助调优,集群层辅助决策。
6.3 成本控制与资源效率
做AI-Infra不能不考虑成本。GPU资源很贵,闲置就是浪费。提高资源效率的几个方向:
提高GPU利用率。这是最直接的。利用率从50%提到80%,等于同样的卡多跑了60%的任务。手段包括优化数据加载、调优通信、用混合精度等。
弹性调度。训练任务和推理任务混部,训练任务用闲时资源,推理任务用忙时资源。或者用抢占式调度,高优先级任务可以抢占低优先级任务的资源。
Checkpoint复用。调参的时候,如果只是改学习率或者批次大小,可以从之前的Checkpoint继续训练,不用从头开始。这样能省大量时间。
选择合适的硬件。不是所有任务都需要最顶级的卡。推理任务用中端卡可能就够了,把高端卡留给训练。根据任务特点匹配硬件,能显著降低成本。
实操心得:我见过不少团队,所有任务都用最好的卡跑,结果推理任务占了大量高端卡资源,训练任务反而排队。后来做了资源分级,推理任务调度到中端卡上,训练效率立刻上来了。硬件选型要跟任务特点匹配,不是越贵越好。
7. 一些个人体会与后续方向
这个第一章主要是把AI-Infra的整体框架和几个核心基础问题梳理了一遍。从算力、显存、通信的三角关系,到分布式训练的并行策略,再到实操环境搭建和故障排查,基本覆盖了一线工作中最常打交道的内容。
我个人在实际操作中的体会是,AI-Infra这个方向最考验的不是某一项技术的深度,而是系统性的排查思维。一个问题出现的时候,可能涉及硬件、网络、系统、框架多个层面,你需要有一套自己的排查方法论,从最可能的原因开始,逐步缩小范围。这套方法论不是看书能看来的,必须靠实际动手积累。
后续章节我计划深入几个专题:分布式训练框架的源码级解析、GPU通信的底层原理与调优、大规模集群的调度与容错设计、推理服务的性能优化。每个专题都会按照这一章的写法,从实际问题出发,给出可复现的方案和踩坑记录。
如果你跟着这一章的内容动手试了单机多卡的训练,遇到了问题,建议先按照第5章的排查表过一遍。大部分常见问题都能定位到。如果还是解决不了,可以把NCCL的调试日志打开,看看通信卡在哪一步,那通常是问题的关键所在。