PyTorch多进程训练报错:守护进程无法创建子进程的解决方法
解决方法
方案1:修改子进程的守护属性
Python中守护进程不允许创建子进程,而spawn启动的Pool子进程默认是守护进程,导致DataLoader的num_workers无法创建子进程。可以在每个子进程的训练函数开头,手动将当前进程设为非守护:
import multiprocessing as mp import torch def train_single_dataset(dataset_path): # 将当前子进程设为非守护,允许创建DataLoader的worker进程 mp.current_process().daemon = False # 正常初始化数据集和DataLoader dataset = YourCustomDataset(dataset_path) dataloader = torch.utils.data.DataLoader( dataset, num_workers=4, batch_size=32, shuffle=True ) # 后续训练逻辑... model = YourModel() optimizer = torch.optim.Adam(model.parameters()) for epoch in range(10): for batch in dataloader: # 训练步骤... def main(): mp.set_start_method('spawn') dataset_paths = ['dataset1', 'dataset2', 'dataset3'] with mp.Pool(processes=3) as pool: results = pool.map(train_single_dataset, dataset_paths) # 聚合训练结果... if __name__ == '__main__': main()
方案2:使用Manager创建非守护进程池
multiprocessing.Manager创建的进程池默认是非守护进程,天然支持在子进程内再创建子进程,完美适配你的场景:
import multiprocessing as mp import torch def train_single_dataset(dataset_path): # 直接正常使用DataLoader,无需额外修改 dataset = YourCustomDataset(dataset_path) dataloader = torch.utils.data.DataLoader( dataset, num_workers=4, batch_size=32, shuffle=True ) # 训练逻辑... model = YourModel() # ...训练步骤... return model.state_dict() def main(): mp.set_start_method('spawn') dataset_paths = ['dataset1', 'dataset2', 'dataset3'] # 使用Manager创建非守护进程池 with mp.Manager() as manager: pool = manager.Pool(processes=3) trained_models = pool.map(train_single_dataset, dataset_paths) # 聚合多个模型的结果... pool.close() pool.join() if __name__ == '__main__': main()
方案3:兜底方案——关闭DataLoader多进程
如果上面两种方法不适用,可以暂时将DataLoader的num_workers设为0,用单进程加载数据,虽然会牺牲部分数据加载效率,但能快速解决报错:
dataloader = torch.utils.data.DataLoader( dataset, num_workers=0, # 关闭多进程加载 batch_size=32, shuffle=True )
核心原因
multiprocessing.Pool默认创建的是守护进程,这类进程的设计目的是随主进程退出而终止,因此Python禁止它们创建子进程。而PyTorch的DataLoader在num_workers>0时,会通过多进程加速数据加载,这就触发了守护进程的限制,导致报错AssertionError: daemonic processes are not allowed to have children。
内容的提问来源于stack exchange,提问作者cat
相关产品推荐
相关产品推荐

