You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch多GPU下使用nn.DataParallel训练设置随机种子无法复现问题

问题根因
  • 核心原因是nn.DataParallel采用单进程多线程的运行模式,每个GPU对应独立的工作线程。Python原生random库和numpy的随机种子是进程级生效的,仅作用于主线程,新启动的工作线程不会继承主进程的随机种子,会默认使用系统随机源初始化自身的随机状态,导致多卡运行时随机行为不可控。
  • 其次PyTorch本身的CPU随机数生成器为线程本地存储,你在主线程调用的torch.manual_seed仅会设置当前已存在线程的种子,nn.DataParallel启动的新工作线程也不会自动继承该配置。
  • 若你使用了带num_workers>0的DataLoader加载数据,多进程加载的每个子进程也会独立初始化随机状态,进一步放大随机性。
修复方案
  • 方案1:替换nn.DataParallel为官方更推荐的nn.parallel.DistributedDataParallel(DDP)。DDP采用单卡单进程的架构,你只需要在每个进程初始化阶段调用一次set_seed即可,完全规避多线程带来的种子失效问题,同时训练效率也远高于DataParallel。
  • 方案2:若必须使用DataParallel,需补充两处配置:
    1. 自定义DataLoader的worker_init_fn,给每个数据加载子进程单独设置种子:
    def worker_init_fn(worker_id):
        worker_seed = seed + worker_id
        set_seed(worker_seed)
    
    初始化DataLoader时传入该函数,同时固定shuffle的随机生成器:
    g = torch.Generator()
    g.manual_seed(seed)
    train_loader = DataLoader(
        train_dataset,
        batch_size=batch_size,
        shuffle=True,
        worker_init_fn=worker_init_fn,
        generator=g,
        num_workers=num_workers
    )
    
    1. 尽量将代码中所有random、numpy的随机调用替换为PyTorch自带的随机算子,PyTorch的CUDA随机状态通过你已配置的torch.cuda.manual_seed_all可全局生效,跨线程一致性更强。

内容的提问来源于stack exchange,提问作者doing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 03:36:02