最近在搞一个多智能体协作的AI Agent项目,环境是PettingZoo的MAMujoco,策略用的是MAPPO。单机单卡跑小规模(2个agent)还没啥问题,但一上4个agent并用torch.distributed做多进程训练,就疯狂报“NCCL通信超时”,有时候还莫名其妙内存溢出。我试过调大timeout和减小batch size,但跑个几百步就卡死。有没有老哥踩过类似的坑?是环境同步的问题还是PyTorch分布式策略没配好?求指点,孩子快调吐了。
用PyTorch搭多智能体强化学习,分布式训练总是报错,求老哥支招
全部回复
共 179 条碰到过类似的,MAMujoco里agent一多,PettingZoo的step同步本身就会拖慢整体节奏,NCCL超时大概率不是网络问题,而是某个进程在环境reset或action计算上卡住导致其他进程等太久。建议先查一下是不是所有worker都在同一时刻调用env.step,MAMujoco的全局奖励计算有时候会隐式同步,容易让某个rank掉队。另外内存溢出可能跟PettingZoo的obs空间有关,4个agent时每个obs拼接的维度会暴涨,试试在传给MAPPO前先做一次numpy到tensor的异步拷贝,别让主线程攒太多中间变量。我上次是把distributed的init_method改成tcp://而不是env://,顺便把每个进程的CPU绑核,跑起来稳定很多,你可以试试看。
之前跑MAMujoco也遇到过NCCL超时,最后发现是子进程里PettingZoo环境重置不同步导致的,尤其agent多了以后,建议把环境初始化放到主进程做完再broadcast给各worker,别让每个进程自己reset。内存溢出那块儿大概率是replay buffer或者GAE计算时每个进程都存了一份完整轨迹,试试用共享内存或者把advantage计算挪到collect之后统一做。另外torch.distributed的backend换gloo跑通逻辑再换nccl,能排除不少通信层面的坑。你用的是spawn还是launch脚本起进程?这个区别也挺大的。
大概率是MAMujoco每个子环境步调不一致,试试把PettingZeo的同步锁加上,或者用env.reset(seed)固定下时序。
NCCL超时八成是某个agent的进程卡在环境step上了,检查下是不是有隐藏的全局锁,或者干脆把distributed换成Ray试试。
同样调过MAMujoco的来握个手,你这问题大概率不是NCCL本身,而是PettingZoo的env在子进程里没做对序列化,特别是多agent时每个进程的obs空间不一致特别容易卡死。我后来是改成把环境实例化放到每个worker内部,然后用SharedMemory传action,再配合torch的DistributedDataParallel而不是DistributedDataParallel的旧接口才稳下来。另外内存溢出很可能是经验回放buffer在主进程里复制了太多份,试着把buffer也分片到各个进程,最后all_gather汇总,能省不少。你用的是gymnasium还是老版gym的API?版本不匹配也会出这种诡异问题。
NCCL超时这个坑我太熟了,多半不是PyTorch的问题,而是MAMujoco环境里agent的action space或者observation space在子进程里没同步好。PettingZoo的env在fork之后经常会出现共享内存的句柄错乱,尤其是你用了多进程dataloader或者环境并行的时候,建议把环境创建放到worker进程内部,别在main进程里先实例化再传进去。
另外你用的是MAPPO,注意一下GAE的计算是不是把不同agent的advantage混在一个tensor里做allreduce了,这会导致通信量暴增而且卡死。我之前就是把这个拆成每个agent独立计算再同步,问题直接消掉一大半。
内存溢出的话,大概率是PettingZoo的observation返回的是numpy数组,你在分布式采样的时候没做pin_memory或者没及时释放,导致每个worker攒了一堆历史buffer。试着把replay buffer改成按agent分片存储,并且用shared_memory来传,别走torch.distributed的tensor接口。
还有个小技巧,NCCL超时你把环境变量设一下NCCL_DEBUG=INFO,看卡在哪个collective上,有时候是某个agent的step返回了不同shape导致集体通信卡死。如果实在不行,先降级用gloo跑通逻辑,再换回nccl调优,别一上来就死磕分布式。
这问题我太熟了,MAPPO+PettingZoo的坑基本都踩在环境交互和分布式 rollout 的同步上。NCCL超时大概率不是通信本身,而是某个进程在step时卡住(比如MAMujoco子进程没同步),导致其他rank等不到梯度。建议先把每个agent的env单独用spawn起子进程,别在同一个进程里跑多个环境实例,内存溢出多半是共享内存没释放。另外torch.distributed的init_method用env://比tcp://稳,timeout调到30分钟以上,batch size降下来不如直接把gradient accumulation打开,省显存还能稳住通信。
之前搞过类似的,MAMujoco这环境交互频率高,NCCL超时大概率不是timeout不够,而是子进程里数据加载和模拟器不同步导致的,试试把PettingZoo的渲染和step放到主进程,worker只做梯度计算。内存溢出也可能是共享内存没清理,每个agent的obs维度不一样时尤其容易炸,检查下是不是有隐式的tensor拷贝。另外torch.distributed配MAPPO有个坑,GAE计算时advantage的allreduce时机不对会卡死,建议先单进程模拟多agent跑通逻辑再上分布式。
这问题我碰到过,大概率不是环境同步的锅,而是MAMujoco里每个agent的observation space维度不一样,你如果用同一种buffer去存,NCCL all-gather的时候tensor shape对不上就会卡死。可以试试把每个agent的obs单独pad到最大维度,或者直接用PettingZoo的parallel API配合agileRL的分布式封装,能省不少事。另外内存溢出那个,查下是不是dataloader的num_workers开太多,跟NCCL的进程数打架了。
这问题我太熟了,之前搞多智能体也是被NCCL折磨得不行。你试试把MAMujoco的vector env改成同步模式,别用异步,还有torch.distributed的init_method用tcp://加固定端口,别用env://。另外内存溢出大概率是每个进程都复制了一份环境,用spawn方式启动worker前把env建在子进程里,别在main里初始化。
NCCL超时这个坑我太熟了,八成不是PyTorch配置问题,而是PettingZoo环境本身在多进程下同步有死锁。你试试把MAMujoco的渲染关掉,再把每个agent的观测空间单独用shared memory传,别走NCCL。另外内存溢出可能是每个子进程都复制了一份环境,4个agent加并行采样直接爆显存,建议用torch.multiprocessing的spawn方式启动,别用fork。我之前也是调了半天,最后发现是环境里有个全局变量没加锁,改成进程间独立实例就好了。
这问题我太熟了,之前搞QMIX也栽在NCCL上。你试试把每个进程的env实例单独创建,别共享内存里的PettingZoo环境,另外把torch的线程数设成1,OMP_NUM_THREADS=1,大概率能缓解。还有个坑是MAMujoco的reset可能在不同进程里不同步,建议手动加个barrier,比调timeout管用。内存溢出的话,检查下是不是在收集经验时把每个agent的obs都存到同一个list里了,分进程存能省不少。
这问题我熟,之前跑MAPPO多智能体也卡在NCCL超时上,后来发现是PettingZoo环境reset的时候各进程没同步好,得在step和reset之后手动加torch.distributed.barrier()。另外内存溢出大概率是replay buffer或者advantage计算那块没释放干净,试试用gradient checkpointing或者把obs先转成numpy存。你用的gloo后端做混合训练吗?我换了这个之后稳定很多。
NCCL超时八成是子进程里MAMujoco的步进没做同步,试试把每个agent的reset和step都包上dist.barrier。
也可能是多进程里PettingZoo环境对象各自为政,内存直接爆了,建议把环境放主进程用队列广播。
NCCL超时这事儿,八成不是PyTorch配错,而是PettingZoo环境本身在多个进程里复制时出了岔子。MAMujoco每个agent的observation空间挺大,你多进程一开,每个进程都得维护一份完整环境副本,内存直接翻倍,溢出太正常了。我之前搞过类似的,后来改成共享内存或者用subproc-vec-env那种方式,环境只初始化一次,数据通过队列传,内存压力小很多。至于NCCL超时,除了调timeout,你看看是不是每个进程的GPU利用率不均衡,有的agent步数跑得快,有的卡在环境step上,导致梯度同步的时候等太久。可以试着把环境交互和策略更新拆开,用异步的采样器,或者干脆把4个agent塞进同一个环境实例,用vectorized的方式跑,别真开4个进程。另外,torch.distributed里默认的NCCL对多机多卡优化好,单机多卡反而容易出幺蛾子,你可以试试换成gloo后端,虽然慢点但稳定,先跑通逻辑再说。还有,你是不是忘了设OMP_NUM_THREADS或者CUDA_VISIBLE_DEVICES?这种环境变量在子进程里没继承好,也会莫名卡死。最后问一句,你用的是MAPPO的哪个开源实现?有些版本对PettingZoo的接口兼容性有问题,换个库可能直接就好了。
我之前也卡在NCCL超时上,折腾好久发现多半是PettingZoo的reset和step里有些全局状态没同步好,多进程下每个环境的观测维度不一致就会这样。你可以试试把环境创建和rollout收集都放在同一个进程组里,然后给每个worker单独设个随机种子,不然MAMujoco的物理步进会互相干扰。另外内存溢出那个,检查下是不是每个进程都在重复存经验buffer,搞成共享内存或者干脆用gather汇总再更新会稳很多。你要是方便的话,可以贴下启动命令里的torchrun参数,我怀疑是world_size和nproc_per_node没对应上。
遇到一模一样的情况,2个agent没事,4个就炸。后来发现是MAMujoco里每个agent的动作空间维度不一样,多进程下data loader的batch拼接时会触发隐式同步,导致某个rank等太久。我直接把PettingZoo的vector env换成自己写的同步包装器,然后分布式那边用gloo后端跑CPU版的MAPPO做验证,确认逻辑没问题再换回NCCL,至少能跑完几百步了。你试试把batch size调成全局大小除以world_size,别用每个进程里的原始值。
这问题我熟,八成是PettingZoo环境里头的内部缓冲和torch.distributed的进程组没对齐。你试试把环境创建放在init
这问题八成出在PettingZoo环境reset不同步上,试试把每个进程的env实例单独建,别共用数据。
NCCL超时多半是某个agent的action维度算错了,导致梯度传播卡死,检查下MAPPO的critic输入。
我之前搞过类似的,MAMujoco这环境本身就有点吃内存,4个agent加多进程容易把共享内存打爆,你可以试试把PettingZoo的渲染和vector环境彻底关掉,只留原始数据流。NCCL超时大概率不是通信问题,是某个进程卡在环境step上,建议给每个子进程单独设个环境实例,别共用,再在训练循环里加个手动同步屏障试下。另外torch.distributed里用gloo做backup,虽然慢点但能定位是不是NCCL的锅。你调timeout治标不治本,重点看下是不是某个agent的obs维度不一致导致死锁。
NCCL超时这事八成不是PyTorch的问题,是MAMujoco里多个子环境步进不同步导致的,你先试试把每个agent的reset和step都包上torch.distributed.barrier,强制对齐一下看看。内存溢出我倒觉得是PettingZoo的渲染buffer没清理,特别是MAMujoco这种带物理仿真的一多开就会爆,你可以在每个episode结束后手动调一下env.unwrapped.model的释放。还有个野路子,把NCCL的socket超时参数调成0,让它不限制等待时间,但治标不治本,最后还是得查环境里有没有隐式的随机sleep。
试试给每个子进程绑单独的CPU核,再关掉MAMujoco的全局渲染,大概率是环境步进不同步拖垮了NCCL。
这报错八成是PettingZoo的vector env和torch.distributed的collective通信没对齐,换个同步采样器试试。
大概率是MAMujoco的env在子进程里没做好序列化,试试把环境创建放worker里,别用global变量。