最近在折腾一个多节点分布式训练的任务,用的 PyTorch DDP,后端是 NCCL。环境是公司自研的 MCP 集群,网络走的是 InfiniBand。单机 8 卡跑没问题,但一扩展到两机 16 卡就频繁报“NCCL 超时”和“梯度同步失败”。我检查了网卡配置和 NCCL 版本,也试过调小 batch size 和梯度累积步数,还是偶尔会 hang 住。想问下 MCP 集群下有没有什么特别要注意的参数(比如 NCCL_IB_TIMEOUT 或者环境变量),或者是不是我初始化 group 的方式不对?真心被这个问题卡了三天了,求过来人指条明路。
MCP 环境下用 PyTorch 做分布式训练,梯度同步总是报错,有大佬指点吗?
全部回复
共 114 条遇到同类问题了,我们这边也是自研集群,用的也是IB网,之前调NCCL调到我怀疑人生。你单机没问题但多机就挂,大概率不是模型或数据的问题,而是NCCL的拓扑发现和IB动态路由没对上。先别急着改batch,直接检查一下NCCL_SOCKET_IFNAME是不是正确指向了IB接口(比如ib0),有时候默认走了eth0导致超时。另外NCCL_IB_TIMEOUT确实要调,但光调这个不够,建议同时把NCCL_IB_RETRY_CNT设大一点,比如32或64,我们这边从默认的7调到32之后,hang的频率明显降了。还有个小坑,多机的话记得确认每个节点的GID索引一致,用ibv_devinfo看下port的active和gid,不一致的话NCCL会随机选,容易卡在初始化。你初始化group的方式大概率没问题,但可以试试在torch.distributed.init_process_group里显式传init_method,用tcp://加主节点IP,别用env://,因为MCP集群的环境变量有时候会被调度器覆盖。最后如果还不行,把NCCL_DEBUG=INFO打开,跑一次看卡在哪个collective上,我们上次就是卡在allreduce的ring order上,后来发现是IB的拥塞控制参数没开,需要跟集群管理员确认下是否启用了自适应路由。三天不算啥,这种问题我们当时磨了一周。
遇到过类似的坑,MCP这种自研集群经常有隐藏的网卡路由问题,NCCL默认走IB但可能实际绑到了别的接口上。你先用nccl-tests单独跑个allreduce看看,能稳定过再上DDP,能排除不少干扰。另外建议直接设一下NCCL_IB_TIMEOUT=22和NCCL_IB_RETRY_CNT=7,超时别用默认值,还有NCCL_SOCKET_IFNAME要指定到正确的IB设备名。group初始化方式一般不会导致hang,倒是可以看看是不是多机间的共享存储权限或者防火墙拦了同步端口。
我之前也踩过类似的坑,多机NCCL超时大概率不是batch size的问题,先试试把NCCL_IB_TIMEOUT调到30以上,还有NCCL_IB_RETRY_CNT设个7,基本能解决大部分hang住的情况。另外确认下init_method是不是用的tcp://加master的IP,有时候主机名解析在MCP集群里会出问题导致握手失败。还有个小细节,如果网卡不是默认的ib0,记得设NCCL_IB_HCA指定一下,之前我漏了这个也卡了很久。
之前调过类似的多机NCCL问题,InfiniBand下NCCL_IB_TIMEOUT确实值得先拉大试试,但更常见的是MCP集群里共享IB分区导致网络抖动,建议把NCCL_IB_RETRY_CNT也调高。另外你检查过两台机器的GPU拓扑吗,如果跨NUMA访问显存也可能造成同步假死。还有个小坑,group初始化时最好显式指定device_id,别依赖默认顺序。可以试试先开NCCL_DEBUG=INFO跑一次,看卡在哪个ring上,比瞎调参数快。
NCCL_IB_TIMEOUT调大点试试,我们之前也卡这,改成62基本就稳了。
试过把NCCL_IB_TIMEOUT调到30以上没?我之前遇到类似问题,最后发现是MCP集群里IB的subnet manager配置跟默认值不匹配,光调环境变量不够,还得看下opensm的日志。另外你初始化group的时候,如果用的是init_process_group里默认的device_id,在MCP这种多机环境下容易出问题,建议显式传rank和world_size,最好再配上NCCL_DEBUG=INFO跑一次,看看具体卡在哪个集合通信上。还有个小坑,如果两机的网卡速率不一致(比如一台是HDR100另一台是HDR200),NCCL会按慢的来,但偶尔会触发超时,可以试试NCCL_IB_DISABLE=1强制走TCP验证下是不是IB链路的问题。我上次是直接把两台机器的mlx5_0和mlx5_1映射顺序对齐才解决的,你可以用ibstatus对比下。要是还hang,试试把梯度累积改成手动循环里做,别用DDP自带的,有时候跟MCP的调度器抢占有关。
多节点跑DDP,NCCL超时八成不是batch size的事,你先看看NCCL_SOCKET_IFNAME和IB绑定的网卡是不是对的,我们之前就是这俩没对上疯狂hang。另外MCP集群如果走的是shared memory或特殊调度,初始化group时建议显式指定init_method为tcp://,别用env://,容易抢端口。还有个小技巧,把NCCL_IB_TIMEOUT调到22以上,NCCL_IB_RETRY_CNT设成7,能缓解不少偶发超时。你确认下两台机器的IB速率和MTU一致吗,不一致也会同步卡死。
超时和hang大概率不是batch size的问题,先查一下两台机器的IB链路是不是通的,跑个nccl-tests的allreduce看看带宽和延迟。另外MCP集群如果启用了UCP或者有防火墙策略,NCCL的共享内存和socket通信可能会被拦,试试把NCCL_SOCKET_IFNAME指定到ib0。还有你init_process_group里有没有设init_method,用env://的话确保两台机器的MASTER_ADDR和RANK都对齐了,之前见过有人忘了在第二台机器上设不同的RANK导致一直等同步。如果还不行,把NCCL_DEBUG=INFO打开看下具体卡在哪个阶段,通常是连接建立或者数据交换那块。
试试把NCCL_IB_TIMEOUT调到60以上,另外检查下MCP的共享内存映射,小batch反而容易触发同步卡死。
我之前也踩过类似的坑,NCCL超时大概率不是batch size的问题,而是IB通信拓扑没对齐。你试试在初始化DDP之前手动设一下NCCL_IB_TIMEOUT=1200,然后把NCCL_IB_RETRY_CNT调到5以上,这俩环境变量在多机场景下比啥都管用。另外确认下两台机器的网卡是不是都绑到了同一个IB子网,MCP集群有时候会默认走eth0回环。如果还hang,可以加一句os.environ['NCCL_DEBUG']='INFO'看下卡在哪个rank的allreduce上,我上次是发现rank4和rank5的IB速率协商到了不同档位,强制设成一样的就稳了。
NCCL超时八成不是batch size的锅,你这情况先查一下IB的GID索引和NCCL_IB_QPS_PER_CONNECTION,MCP集群虚拟化后经常因为GID选错导致跨节点通信卡死。另外把NCCL_IB_TIMEOUT调到22以上,默认的15在IB+多机场景太短了。初始化group的话,确认下init_method用的是tcp://还是共享文件系统,MCP上经常有权限问题导致rank不同步,我上次就是换成env://才好的。
我之前也踩过类似的坑,特别是多机时NCCL的IB超时特别敏感。你可以试试把NCCL_IB_TIMEOUT调大到30s以上,同时加个NCCL_IB_RETRY_CNT=8,另外确认一下两机的网卡是否都绑到了正确的IB设备上,有时候是vlan或者路由表的问题。还有,你初始化group时用的init_method是tcp还是file?如果走tcp,建议换成共享文件系统的方式,能少很多握手异常。最后,如果还hang,可以开NCCL_DEBUG=INFO看下卡在哪个集合通信原语上,基本能定位是网络还是同步逻辑的问题。
NCCL超时八成是IB网络没调好,试试把NCCL_IB_TIMEOUT加到30,另外确认下MCP的共享内存够不够。
试试把NCCL_IB_TIMEOUT调到60再配个NCCL_IB_RETRY_CNT,之前我们也是这么解的。
这情况八成是网卡仲裁和MCP的通信调度冲突,换个GDRDMA试试。
遇到过类似情况,多机NCCL超时八成不是batch size的问题,你先试试把NCCL_IB_TIMEOUT调到60以上,同时加上NCCL_IB_RETRY_CNT=20,很多时候是IB拥塞控制没跟上。另外确认下两机的网卡速率和MTU是否一致,MCP集群里不同节点间配置偶尔会有隐藏差异。group初始化本身一般不会导致hang,但你可以打印一下每张卡的rank和world_size对比下日志,看是不是有节点没同步上。最后建议用torchrun的--rdzv-backend=c10d并显式指定ip,别依赖自动发现。
NCCL_IB_TIMEOUT调到30以上,再加NCCL_IB_RETRY_CNT=7试试,多半能稳。另外确认下MCP的网卡是否有PFC流控,没开的话超时是常态。
检查下NCCL_IB_TIMEOUT和NCCL_SOCKET_IFNAME,另外init_method用tcp://主节点IP试试,我们之前这么解决的。
遇到过类似坑,多半是IB跟RoCE冲突,设个NCCL_IB_DISABLE=1先跑通,再看是不是网卡绑定问题。
之前调过类似的MCP环境,NCCL_IB_TIMEOUT确实很关键,可以试试调到22以上,另外NCCL_IB_RETRY_CNT也顺手设一下。你那个hang住大概率是跨节点通信的QoS没对齐,MCP集群里给InfiniBand设个高优先级带宽保障会好很多。还有确认下init_method是不是用的tcp://稳定IP,别用hostname解析。
多机场景下NCCL超时大概率跟IB的active/ passive配置有关,建议先确认一下两台机器的ibstat里端口状态都是active,然后强制指定NCCL_IB_DISABLE=0配合NCCL_SOCKET_IFNAME=ib0试试。另外你初始化group的时候用的init_method是tcp还是共享文件?如果是tcp,记得把MASTER_ADDR指向第一台机器的内网IP,别用hostname。还有个小坑,检查下两机的ulimit -l,锁页内存不够也会导致随机hang,调成无限或至少64GB再跑一次看看。
我之前也踩过类似的坑,NCCL 在 IB 下对超时特别敏感,你先试试把 NCCL_IB_TIMEOUT 调到 60 甚至更高,还有 NCCL_SOCKET_IFNAME 指定一下具体网卡,别让它自动选。另外检查下两机之间是否有防火墙或者路由问题,有时候 MCP 集群的虚拟网络会干扰 IB 的 PKey 匹配,这个比调 batch size 更关键。你初始化 group 用的是 init_method 的 tcp 还是共享文件系统?如果是 tcp 可能 master 地址配错了,建议换成 file 方式试试,能避免很多隐蔽的握手问题。