ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PCIe、NVLink、NVSwitch:看懂GPU服务器通信架构与性能排查

PCIe、NVLink、NVSwitch:看懂GPU服务器通信架构与性能排查 如果你组装过一台8卡GPU服务器或者第一次跑大模型训练时在日志里看到长时间卡在“all_reduce”这一步你很快就会意识到一个问题GPU之间的通信和GPU本身的算力一样关键。这个领域绕不开三个词——PCIe、NVLink、NVSwitch。它们分别代表了三代不同定位的数据通路决定了一张显卡上的数据能不能快速搬到另一张显卡上。这篇文章我从实际部署和性能排查的角度把这三样东西放在一起讲清楚包括它们各自的带宽、拓扑、在训练推理中怎么配合以及你拿到机器之后如何验证通信路径、排查“明明八卡全用上了但速度就是上不去”的经典问题。这篇文章适合谁准备采购GPU服务器但看不懂规格表里“600GB/s NVLink”是什么意思的架构师刚上手多卡训练、被NCCL日志和nvidia-smi topo -m搞得一头雾水的算法工程师以及做AI基础设施运维、需要快速判断机器通信是否正常的朋友。懂得这三样东西你看一台GPU服务器的眼光会完全不一样。1. 先搞清楚为什么通信会成为瓶颈1.1 多卡训练里数据到底要怎么搬大模型训练最常见的是数据并行也就是每张卡都放一份完整的模型副本各自拿着不同的mini-batch做前向和反向。反向传播算完梯度之后所有卡必须把梯度加起来得到全局梯度再做参数更新。这个“把梯度加起来”的过程就是all-reduce是集合通信里最典型的操作。以8卡A100训练一个70亿参数模型为例模型大小约14GBFP16梯度和它一样大。每一轮迭代都要把这14GB梯度在所有GPU之间做一次全交换。如果通信带宽只有几十GB每秒你就会发现GPU算力越强通信等待占比越高。好的情况是计算和通信能重叠一部分但在all-reduce这种强同步点上通信带宽直接决定了训练效率。这也是为什么GPU之间需要一套比传统总线更快的互联方案。PCIe在一开始还能应付后来算力翻倍、模型疯长PCIe的带宽逐渐不够用了NVIDIA才推出NVLink和NVSwitch去填这个坑。1.2 算力增长和总线带宽增长完全不在一个量级比较一下你会更直观。单块GPU的FP16算力从V100的约125 TFLOPS涨到H100的约989 TFLOPS涨了大约8倍而PCIe的带宽从Gen3的约32GB/sx16双向到Gen5的约128GB/sx16双向只涨了4倍。如果只靠PCIe做多卡通信算力越强通信占比越高扩展性越差。NVIDIA在Volta架构之后给出的答案就是NVLink。它的定位很明确不是替代PCIe而是专门在GPU之间提供一条高带宽、低延迟的私有通道。NVSwitch则是把NVLink从“点对点”升级成“全互联交换网络”的关键设备。三者不是竞争关系而是各管一段PCIe负责常规外设连接和上行NVLink负责GPU间近邻高速通信NVSwitch负责把多颗GPU组织成一张无阻塞的交换网。2. 先补基础课PCIe 是怎么把GPU接起来的2.1 lane、版本和带宽看懂这些参数才算入门PCIe是当前计算机里最通用的总线协议从显卡、NVMe SSD到网卡全在用它。它的基本单位是lane通道每个lane是一对差分发送线加一对差分接收线。一条PCIe链路可以同时使用1、2、4、8、16条lane显卡和NVMe盘最常见的是x4或x16。带宽由“版本x lane数”决定。以x16为例各代双向总带宽大概是版本单lane速率x16双向带宽编码效率PCIe 3.08 GT/s约32 GB/s128b/130bPCIe 4.016 GT/s约64 GB/s128b/130bPCIe 5.032 GT/s约128 GB/s128b/130b注意这里都是双向总带宽实际读或者写是单向的要再除以2。而且PCIe是包交换协议还有包头、流量控制等开销实测有效带宽通常打八到九折。很多人跑nvidia-smi看到的PCIe Gen4 x16是64GB/s双向就以为单方向能跑满32GB/s实际上测出来经常只有25GB/s左右这是正常的。2.2 三层协议做一次完整的数据搬运PCIe通信在逻辑上分成事务层、数据链路层和物理层。我们平时不太需要关注每一层的细节但有几个概念是排查问题时常见的。事务层传输的数据包叫TLPTransaction Layer Packet里面有Header和数据。Header里最关键的是地址信息用来告诉对端数据要写到哪个地址。GPU显存的BAR空间就是通过这种方式映射到系统地址空间里的CPU和GPU之间其实是在做“内存语义”的访问而不是像网线那样发字节流。物理层里有件事值得单独说叫弹性缓冲Elastic Buffer。PCIe两端时钟不是完全同频的即使标称都是8GHz实际频率也会有几百分之一的偏差。如果没有弹性缓冲去吸收时钟频偏数据流里就会时不时多一位或少一位整个链路就崩了。这和以太网里收发电协调时钟是类似的问题但PCIe处理方式很优雅——在串行数据流里插入SKP字符接收端通过弹性缓冲把它们扔掉或补上从而对齐本地时钟。很多人调试PCIe信号不稳定时第一反应是改差分对等长其实先确认链路训练是否稳定、是否出现大量错误校验才是更关键的。2.3 PCIe Switch到底做了什么PCIe协议设计上每个Root Complex根复合体能挂的设备数量有限lane数也有限一颗CPU通常只有几十条PCIe lane。比如一颗64 lane的CPU你插一张x16显卡、一张x16网卡就差不多用完了再想加卡只能想别的办法。办法就是PCIe Switch。它本质上是一个PCIe交换机把上游的一路PCIe拆分成下游的多路相当于把一根大口径水管分成多个水龙头。最常见的场景是把CPU的x16拆成两个x8或者把x32拆成四个x8。多卡服务器里CPU通过PCIe Switch再连到多张GPU让一张CPU能带得动8张卡。代价也有所有下游设备共享上游带宽。如果一张x16网卡和一张GPU挂在同一个PCIe Switch下两边同时跑满数据PCIe Switch和CPU之间的链路口就会成为瓶颈。这也是为什么高端GPU服务器里软件层要特意区分“同一PCIe Switch下的GPU”和“不同PCIe Switch下的GPU”因为后者的通信延迟和带宽都更差。3. NVLink专为GPU之间的高频访问设计3.1 PCIe的短板在哪里延迟和双向同时传输PCIe做通用设备互联很称职但做GPU间通信有两个先天不足。第一是延迟PCIe通信要经过根复合体、PCIe Switch等多级转发加上事务层协议的打包解析延迟通常在微秒量级。第二是双向传输时会互相挤占虽然标称双向总带宽很高但实际all-reduce这类操作需要同时收发很容易打到瓶颈。NVLink的思路完全是为GPU间通信定制的。它不经过CPU或根复合体直接在两颗GPU之间建立物理链路而且是多lane并行。更关键的是NVLink支持“直接内存访问”GPU可以像访问自己显存一样去访问另一颗GPU的显存驱动层可以把它当成一块更大的显存来用。打个比方PCIe像是两个小区之间走公共马路NVLink则是在两栋楼之间架了一座专属天桥不走红绿灯不跟其他车辆抢道。3.2 每代NVLink的带宽演进NVLink从2016年P100开始商用之后几乎每一代GPU架构都在加宽加量。GPU架构NVLink版本单卡链路数总双向带宽P100NVLink 1.04条160 GB/sV100NVLink 2.06条300 GB/sA100NVLink 3.012条600 GB/sH100NVLink 4.018条900 GB/s以A100为例12条NVLink每条双向约50GB/s换算成单向也有25GB/s。前面说PCIe Gen4 x16单向约32GB/s看起来差不多但NVLink是点对点的两卡之间独享带宽不经过Switch也不会被其他设备挤占实际使用体验明显更快。到了H100900GB/s的双向带宽已经远超PCIe Gen5能提供的上限这也是为什么高端训练卡之间一定要走NVLink。3.3 NVLink和PCIe在同一台机器里怎么共存这里要澄清一个很多人误解的点NVLink并没有取代PCIe。即使在最顶级的8卡机器里每张GPU照样会留出一条PCIe链路作为“常规通道”用于加载驱动、访问配置空间、和CPU进行控制面通信。NVLink则作为数据面的加速通道存在。SXM形态的GPU就是那种不带风扇、插在底座上的计算卡同时拥有两条通路一条PCIe Gen4/Gen5 x16连到CPU或PCIe Switch用于基本控制和少量数据传输多条NVLink连到相邻GPU或NVSwitch用于大规模显存交换。两者并行工作互不干扰。这也是为什么nvidia-smi里看到的PCIe带宽数字很小但NCCL实测通信带宽却能跑出几百GB/s——因为真正的大流量都走了NVLink。4. NVSwitch把“点对点”升级成“全互联”4.1 为什么不能一直用NVLink做全连接你可能马上会想到一个问题既然NVLink带宽这么高那我让8张卡两两之间都拉满NVLink不就行了答案是物理上做不到。假设每张GPU只有6条或12条NVLink而8卡全互联意味着每张卡要同时连接其他7张卡。如果每对连接要占用2条链路那每张卡需要14条NVLink。V100/A100时代链路数量不够只能组成不完美的拓扑。比如A100的12条NVLink实际构成的是“立方体”拓扑任意两张卡都可能不是直连需要中间卡转发。直连转发会带来两个问题一是转发占用了中间卡的NVLink带宽导致通信效率下降二是延迟变高。NCCL里的ring all-reduce调度得很精细但再精细也架不住拓扑不是全互联。NVSwitch就是来解决这个拓扑问题的。它的角色类似以太网交换机每颗NVSwitch上有几十条NVLink口可以把任意输入口的数据交换到任意输出口所有端口同时双向跑满。GPU之间不再需要两两直连而是把所有链路插到NVSwitch上由交换芯片做交叉互连。4.2 一颗芯片撑起一个无阻塞的网络一台HGX基板上的4颗NVSwitch配合8张SXM GPU构成的就是一个无阻塞的全互联网络。所谓“无阻塞”意思是任何两张GPU之间通信时都不会因为其他GPU同时在通信而速下降。这是多卡训练里最理想的状态。NVSwitch本质上是一个巨大的交叉开关Crossbar多个输入口和多个输出口同时工作。每颗NVSwitch有算力极高的交换能力多个NVSwitch并联还能做冗余和扩展。从H100开始NVSwitch还加入了多播加速功能对all-reduce、all-gather这类“一个数据发给多个目标”的集合操作特别友好。NCCL在做集合通信时如果检测到底层是NVSwitch会启用多播策略把广播数据一次推给多张卡而不是一张一张发。如果你用的机器是“NVLink直连”方案比如部分8卡V100或更早的4卡配置两颗GPU之间的通信路径是固定的某些对间的通信可能要走多跳表现就不如NVSwitch机型稳定。这也是为什么训练大模型时大家更倾向于选择HGX基板的机器而不是拿四张卡自己拼。4.3 从机内走向机外NVLink域和跨节点扩展NVSwitch不只是管一块基板它还能把多个基板连成更大的域。NVIDIA在DGX等大型系统里用NVSwitch把多台机器拉进同一个NVLink域。在这个域里任意两颗GPU之间的通信都能保持非常高的带宽延迟远低于走网卡的方案。不过要注意跨节点通信目前在绝大多数场景下还是走InfiniBand或RoCE网络。NVLink域更多是降低单机内通信开销而跨机通信的瓶颈通常在网卡和交换网络。这里也踩过很多坑明明机内NVLink速度极快但跨节点训练时因为网络没调好整机性能被拖垮。所以做分布式训练调优时我把“机内通信”和“跨机通信”作为两个独立的性能域分开看不要混在一起调。5. 一台8卡机器的通信全景三者如何协同5.1 实际拓扑拆解CPU、PCIe Switch、NVSwitch各管什么为了把前面这些讲成一个整体我们来拆一台典型的8卡 SXM 服务器比如A100/H100 HGX基板的机型。从CPU视角看机器里有两条总线系统。一条是PCIe总线CPU通过PCIe链路连到PCIe SwitchPCIe Switch再分出多条PCIe x16链路连到各张GPU的PCIe控制器同时还有PCIe链路连到网卡和NVMe盘负责控制面和常规数据传输。另一条是NVLink域8颗GPU各自拉出多条NVLink连到板载的4颗NVSwitchNVSwitch之间也有高速互连形成全互联网络。数据搬运时GPU驱动会自动判断目的地。如果目标显存在同一颗GPU上直接走本地显存如果目标在另一颗GPU上第一选择是走NVLink/NVSwitch路径如果NVLink不可用或距离较远退而求其次走PCIe跨机器时则要通过网卡走网络。这个路径选择是NCCL等通信库在运行前通过拓扑探测完成的不是随机决策。5.2 数据路径选择为什么不是所有卡都“点对点直连”NCCL做的第一件事是构建一张拓扑图记录每对GPU之间的相对位置。它读的信息就来自nvidia-smi topo -m的输出判断两颗GPU是在同一NVSwitch下、同一PCIe Switch下还是要经过CPU。不同路径的通信性能差别很大实测下来NVLink路径通常比PCIe路径快5到10倍。如果软件层面错误地把通信调度到了PCIe上整个训练速度会断崖式下跌。所以很多跑大模型训练的人会格外关注NCCL_P2P_LEVEL这类环境变量。默认情况下NCCL会启用P2P通信也就是让GPU绕过CPU和内存直接在NVLink或PCIe上交换数据。如果驱动或容器配置有问题P2P被禁掉数据就要先从源GPU拷贝到CPU内存再拷到目标GPU带宽和延迟都恶化一个数量级。这里有个排查技巧如果训练日志显示通信占比特别高先用nvidia-smi topo -m确认卡的布局再用NCCL的测试工具跑一次all-reduce带宽直接看实际速度是否符合预期。不要一上来就怀疑代码。5.3 软件栈怎么感知到这些硬件差异CUDA层面有一个概念叫“可访问对等”通过cudaDeviceCanAccessPeer和cudaDeviceEnablePeerAccess来判断并开启GPU间P2P。如果可以CUDA会让GPU直接读写对方显存跳过CPU。这一层对上层框架是透明的PyTorch会通过CUDA Runtime API自动启用这些能力。再往上是NCCL。它负责把复杂的集合操作分解成适合具体拓扑的通信原语。比如all-reduce在环形拓扑下是“分块流水线”在树形拓扑下是“多播累加”。NVSwitch出现后NCCL还能利用多播特性做更高效的方案。所以你会看到同样8张H100老的NCCL版本和新的NCCL版本跑出来的带宽不一样很多时候就是新版本对NVSwitch多播路径的调度做了优化。6. 实操中的通信路径查看、验证与调优6.1 三分钟看懂nvidia-smi topo -m拿到一台多卡机器第一件事就是跑nvidia-smi topo -m看GPU之间和CPU之间的连接情况。输出结果是一个矩阵里面的标记含义很重要NV#两颗GPU之间有NVLink直连通信最快。PIX两颗GPU挂在同一个PCIe Switch下走PCIe通信但距离较近。PXB经过PCIe Bridge多了一级转发。PHB经过CPU上的不同PCIe根端口可能需要绕过CPU内部。SYS最差要跨CPU甚至跨节点通信延迟最高。实际使用中我的经验是先看有没有NVLink直连的卡再看PIX级别的卡有多少。如果一个训练任务被调度到了大量SYS级别的卡上性能一定好不了。早期很多人在云厂商租多卡实例时没注意这点结果训练速度远不如预期。6.2 怎么实测通信带宽光看拓扑还不够得跑一下真实带宽。常用方案是NCCl官方测试工具nccl-tests里面的all_reduce_perf典型命令是mpirun -np 8 ./build/all_reduce_perf -b 8M -e 8G -f 2 -g 1注意-g 1是每个进程用一张GPU-f 2是带宽翻倍更新数据量从8MB跑到8GB。输出里的Algbw是算法带宽Busbw是总线带宽。对于8卡A100单卡NVLink 600GB/s总带宽的机器all-reduce的Algbw一般能跑到400GB/s以上H100则有机会跑到700GB/s以上。如果只能跑到几十GB/s多半是P2P被禁用、NCCL版本过老、或者驱动/容器配置有问题。也可以直接用nvidia-smi -q -d NVLINK查每张卡NVLink的错误计数。NVLink链路如果因为信号问题降速或重训错误计数会一直增长。这个数值在训练卡顿且报NVLink相关错误时很关键。6.3 高频问题速查通信相关的坑我基本都踩过我把自己实际遇到过的问题整理成了一张速查表新手照着查能省不少时间。现象可能原因排查与解决训练时GPU利用率忽高忽低通信占比很大数据没走NVLink而是走了PCIe跑nvidia-smi topo -m确认拓扑检查NCCL_P2P_LEVEL和驱动版本all_reduce_perf带宽只有几十GB/sP2P被禁用数据经过CPU中转用cudaDeviceCanAccessPeer做测试或检查容器挂载的参数是否屏蔽了P2PNVSwitch机型上NCCL版本较老性能上不去老版本不支持NVSwitch多播优化升级NCCL到较新版本配合新CUDA驱动使用跨节点训练慢单机内正常InfiniBand或RoCE网络配置问题、网卡走了PCIe瓶颈用ib_write_bw测网络带宽检查网卡是否被PCIe Switch挤占训练刚开始报错“out of memory”但显存看着够NVLink连接异常导致CUDA启用了回退路径占用了额外显存检查nvidia-smi -q -d NVLINK的错误计数确认链路状态正常容器里看不到P2P能力裸机正常容器隔离了设备节点或驱动挂载不全用--gpus all方式启动挂载/dev/nvidia-uvm等设备节点6.4 硬件设计层面的通信质量提醒如果你不只是用机器还涉及到服务器硬件选型或者自己设计小板卡PCIe的硬件质量同样影响通信稳定性。热搜里很多人问“PCIe差分对间需不需要等长”这个问题我在硬件调试时的结论是差分对内等长要求严格但差分对之间允许一定长度差PCIe规范对lane与lane之间的skew要求相对宽松因为协议层有弹性缓冲和deskew机制。真正容易出问题的是电源完整性和参考层不连续这比等长更难排查。信号质量可以用协议分析仪抓链路训练过程或者看系统日志里有没有PCIe错误上报。NVLink作为私有协议硬件调试手段比PCIe少一旦出现问题通常只能看驱动的NVLink错误计数和链路位宽是否降级。因此在实际运维中我建议把NVLink状态检查纳入例行巡检尤其在训练任务频繁切换、机器搬运过之后一定要检查链路是否仍然跑在完整位宽和速率上。一点个人体会这套体系我花了不少时间才真正串起来。一开始我以为只要选型号够新、带宽数字够大就万事大吉后来发现通信性能是“协议、拓扑、软件栈、硬件质量”四件事共同决定的结果。PCIe是基础NVLink是加速器NVSwitch是把加速器组织成网络的纽带而NCCL和CUDA则是在这张网络上做流调度的“交警”。它们配合得好才能让8卡、甚至更多卡的机器发挥出接近线性扩展的能力。最后分享一个小技巧新机器到手我习惯先跑一遍nccl-tests的all_reduce_perf做基线把结果记录下来存档。以后训练出问题、机器维修过、驱动升级过再跑一次对比基线几秒钟就能定位是不是通信链路的锅。这套方法帮我排查过太多“看起来训练很慢”的伪故障了。
返回列表