最近在折腾一个图像分类项目,单卡跑没问题,但想试试多卡加速。参考官方文档写了DistributedDataParallel,结果一跑就报“RuntimeError: NCCL error: invalid usage”。排查了半天,发现好像是我设了torch.cuda.set_device(local_rank)后,主进程和子进程的设备号对不上?我用的启动命令是torchrun --nproc_per_node=2 train.py,代码里也加了init_process_group(backend='nccl')。是不是我多卡初始化顺序有问题,或者环境变量没设全?有没有大佬能帮忙看看常见坑在哪?先谢谢了!
用PyTorch做多卡训练,DDP一直报错找不到设备,求指点
全部回复
共 147 条试试点把set_device放到init_process_group后面,我上次这么换了下顺序就好了。
遇到过类似问题,大概率是init_process_group里少了world_size和rank参数,torchrun虽然会自动设环境变量,但代码里得显式读一下os.environ['RANK']和WORLD_SIZE。另外set_device最好放在init之后,而且主进程别调用local_rank,直接用全局rank比较稳。你可以试试换成device = torch.device(f'cuda:{local_rank}')再传给模型,别在init前切设备。
哎这个坑我当初也踩过,NCCL报invalid usage八成就是设备号和进程没对齐。你用了torch.cuda.set_device(local_rank)但torchrun其实会自动帮你设环境变量,你手动再set一次反而可能覆盖掉正确值。我建议你试试去掉set_device,直接靠torchrun的local_rank和CUDA_VISIBLE_DEVICES来映射,更稳妥。另外检查一下init_process_group里有没有设world_size和rank,虽然torchrun会传环境变量,但有些版本要求显式传参。还有个常见问题是你得确保所有进程都调用了barrier()后再开始DDP包装模型,否则主进程先跑起来子进程还没初始化完就会报设备找不到。如果还不行,可以看看torch.distributed.get_world_size()返回值对不对,有时候多卡但进程数没设够也会这样。
试试在init_process_group前面先设好os.environ['RANK'],有时候torchrun传的环境变量不是自动生效的。
遇到过类似问题,关键点在于torch.cuda.set_device(local_rank)要在init_process_group之前调用,而且local_rank最好从环境变量LOCAL_RANK里拿,别自己随便设。另外NCCL报错有时是网络问题,可以试试先设NCCL_DEBUG=INFO看具体卡在哪一步。还有个小坑,torchrun会自动分配rank和device,如果你代码里重复设了可能会冲突,检查下初始化顺序吧。
试试在torchrun命令里加上--local_rank参数,或者代码里直接用os.environ['LOCAL_RANK']取设备号。
试试在init_process_group之前先设好环境变量LOCAL_RANK,或者用torchrun的话设备号交给它自动分配。
我也遇到过类似的问题,后来发现是torch.cuda.set_device这行其实可以去掉,因为torchrun会自动帮你设好local_rank的环境变量,再手动设反而容易冲突。另外建议检查一下init_process_group里有没有加world_size和rank参数,虽然torchrun会传环境变量,但有时候显式指定会更稳。还有就是nccl版本和PyTorch版本是否匹配,这个也容易在分布式时出幺蛾子。
这个坑我也踩过,大概率是torch.cuda.set_device和torchrun自动分配设备冲突了。torchrun本身会通过环境变量LOCAL_RANK帮你设好当前进程的GPU,你再手动set_device反而可能覆盖错。试试去掉set_device那行,直接用torch.cuda.device(local_rank)包装模型,或者把init_process_group里的rank和world_size显式从环境变量读出来。另外确认下nccl版本和PyTorch是否匹配,有时候换个gloo后端也能临时排查问题。
试试在init_process_group之前先设好环境变量RANK和WORLD_SIZE,torchrun有时候不会自动传全。
我之前也踩过这个坑,torchrun其实会自动帮你设好LOCAL_RANK这些环境变量,你手动set_device反而容易和它冲突。建议试试把set_device那行去掉,或者直接用torch.cuda.device(local_rank)的上下文管理器来包裹模型创建的部分。另外确认一下nccl版本和CUDA版本是不是匹配的,有时候版本对不上也会报这个错。
试一下在torchrun命令里加上--use_env,或者手动把RANK和WORLD_SIZE环境变量print出来核对一下。
这问题我也踩过坑,大概率是torch.cuda.set_device(local_rank)放错了位置——得在init_process_group之后、模型搬进DDP之前调用。另外可以检查下torchrun有没有自动设好LOCAL_RANK环境变量,有时候手动设了反而会冲突。你试试把set_device那句删了,直接让DDP自己管设备分配,我这么改完就没再报过NCCL的错了。
这个思路不错,收藏了。
这个问题我之前也踩过坑,torch.cuda.set_device(local_rank)其实在torchrun里是多余的,它会打乱NCCL的默认设备分配。建议你直接删掉这行,让torchrun自动管理设备,然后把init_process_group放到模型初始化之前试试。另外可以检查下环境变量RANK和LOCAL_RANK是不是从torchrun传进来的,有时候手动设了会冲突。
这个问题我踩过一模一样的坑,大概率是torch.cuda.set_device(local_rank)和torchrun自动分配的LOCAL_RANK冲突了。你用torchrun启动的话其实不需要手动set_device,它已经帮你把环境变量配好了,直接删掉那行应该就能通。另外可以检查下init_process_group里有没有显式传rank和world_size,有时候漏掉也会导致设备号错乱。
遇到过类似问题,感觉是torch.cuda.set_device(local_rank)和torchrun自动设置的LOCAL_RANK环境变量冲突了。你可以试试直接去掉手动set_device,让torchrun自己管设备分配,或者把set_device放到init_process_group后面再执行。另外检查下os.environ['LOCAL_RANK']是不是正确传递给了local_rank参数,有时候漏了这一步也会报这个错。
踩过一样的坑,torchrun其实会自动帮你设好local_rank的环境变量,不需要手动调set_device,不然反而容易跟主进程冲突。你试试把set_device那行去掉,让DDP自己分配设备。另外init_process_group里加个world_size参数指定总进程数会稳一些,我上次这么改完就能跑了。
看到你这个报错我太有共鸣了,之前折腾DDP的时候也被这个NCCL invalid usage折磨过。其实问题大概率出在torch.cuda.set_device(local_rank)和init_process_group的调用顺序上——官方推荐的做法是先调init_process_group,再手动设当前设备,因为nccl后端初始化时会自动绑定当前rank的GPU。另外你用的torchrun其实会自动设置LOCAL_RANK和WORLD_SIZE这些环境变量,不用自己额外传,但要注意代码里千万别手动改CUDA_VISIBLE_DEVICES,否则多进程的设备映射会乱。还有个小细节:如果你的模型里用到了torch.nn.DataParallel的残留代码,记得完全替换成DDP,混用也会导致设备号冲突。建议你试试把初始化顺序改成init_process_group -> torch.cuda.set_device -> 构建模型并包装DDP,同时检查一下每个进程打印出来的local_rank和cuda.current_device()是否一致。如果还不行,可以贴一下完整报错栈,可能是NCCL版本和PyTorch版本不匹配的老坑。
这问题我踩过类似的坑,大概率是set_device和torchrun自动分配的rank没配合好。torchrun本身会帮你设好LOCAL_RANK环境变量,你在代码里手动set_device反而可能覆盖掉它的逻辑。试试直接把set_device那行删掉,或者在init_process_group之后再用torch.cuda.set_device(local_rank),让主进程先完成初始化。另外可以打印一下每个进程的os.environ['LOCAL_RANK']和torch.cuda.current_device(),对比看是不是真的对不上。