Pytorch分布式训练/多卡训练(二) —— Data Parallel并行(DDP)(2.3)(torch.multiprocessing(spawn) & Apex)

使用 torch.multiprocessing 取代torch.distributed.launch启动器

      我们可以手动使用 torch.multiprocessing 进行多进程控制。绕开 torch.distributed.launch 自动控制开启和退出进程的一些小毛病

      使用时,只需要调用 torch.multiprocessing.spawn,torch.multiprocessing 就会帮助我们自动创建进程。

import torch.multiprocessing as mp

mp.spawn(main_worker, nprocs=4, args=(4, myargs))

      这里spawn 开启了 nprocs=4 个进程,每个进程执行 main_worker 并向其中传入 local_rank(当前进程 index)和 args(即 4 和 myargs)作为参数

      这样我们就将原本需要 torch.distributed.launch 管理的执行内容,封装进 main_worker 函数中

      值得注意的是,由于没有 torch.distributed.launch 读取的默认环境变量作为配置,我们需要手动为 init_process_group 指定参数

      添加 multiprocessing 后并行训练部分主要与如下代码段有关

# main.py
import torch
import torch.distributed as dist
import torch.multiprocessing as mp

mp.spawn(main_worker, nprocs=4, args=(4, myargs))

def main_worker(proc, nprocs, args):

   dist.init_process_group(backend='nccl', init_method='tcp://127.0.0.1:23456', world_size=4, rank=gpu)
   torch.cuda.set_device(args.local_rank)

   train_dataset = ...
   train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)

   train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=..., sampler=train_sampler)

   model = ...
   model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.local_rank])

   optimizer = optim.SGD(model.parameters())

   for epoch in range(100):
      for batch_idx, (data, target) in enumerate(train_loader):
          images = images.cuda(non_blocking=True)
          target = target.cuda(non_blocking=True)
          ...
          output = model(images)
          loss = criterion(output, target)
          ...
          optimizer.zero_grad()
          loss.backward()
          optimizer.step()

在使用时,直接使用 python 运行就可以了:

python main.py

使用 Apex 再加速

      Apex 是 NVIDIA 开源的用于混合精度训练和分布式训练库。

      注意apex不只是混合精度库,也是一个分布式训练库!!!

      Apex 对混合精度训练的过程进行了封装,改两三行配置就可以进行混合精度的训练,从而大幅度降低显存占用,节约运算时间。此外,Apex 也提供了对分布式训练的封装,针对 NVIDIA 的 NCCL 通信库进行了优化。

      在混合精度训练上,Apex 的封装十分优雅。直接使用 amp.initialize 包装模型和优化器,apex 就会自动帮助我们管理模型参数和优化器的精度了,根据精度需求不同可以传入其他配置参数。

from apex import amp

model, optimizer = amp.initialize(model, optimizer)

       在分布式训练的封装上,Apex 在胶水层的改动并不大,主要是优化了 NCCL 的通信。因此,大部分代码仍与 torch.distributed 保持一致。使用的时候只需要将

       torch.nn.parallel.DistributedDataParallel 替换为 apex.parallel.DistributedDataParallel 用于包装模型。在 API 层面,相对于 torch.distributed ,它可以自动管理一些参数(可以少传一点):

from apex.parallel import DistributedDataParallel

model = DistributedDataParallel(model)
# # torch.distributed
# model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.local_rank])
# model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.local_rank], output_device=args.local_rank)

      在正向传播计算 loss 时,Apex 需要使用 amp.scale_loss 包装,用于根据 loss 值自动对精度进行缩放:

with amp.scale_loss(loss, optimizer) as scaled_loss:
   scaled_loss.backward()

汇总一下,Apex 的并行训练部分主要与如下代码段有关

# main.py
import torch
import argparse
import torch.distributed as dist

from apex.parallel import DistributedDataParallel

parser = argparse.ArgumentParser()
parser.add_argument('--local_rank', default=-1, type=int,
                    help='node rank for distributed training')
args = parser.parse_args()

dist.init_process_group(backend='nccl')
torch.cuda.set_device(args.local_rank)

train_dataset = ...
train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=..., sampler=train_sampler)

model = ...
model, optimizer = amp.initialize(model, optimizer)
model = DistributedDataParallel(model, device_ids=[args.local_rank])

optimizer = optim.SGD(model.parameters())

for epoch in range(100):
   for batch_idx, (data, target) in enumerate(train_loader):
      images = images.cuda(non_blocking=True)
      target = target.cuda(non_blocking=True)
      ...
      output = model(images)
      loss = criterion(output, target)
      optimizer.zero_grad()
      with amp.scale_loss(loss, optimizer) as scaled_loss:
         scaled_loss.backward()
      optimizer.step()

在使用时,调用 torch.distributed.launch 启动器启动:

CUDA_VISIBLE_DEVICES=0,1,2,3 python -m torch.distributed.launch --nproc_per_node=4 main.py

### 回答1: torch.multiprocessing.spawnPyTorch中的一个函数,用于在多个进程中启动一个函数。它可以在多个GPU上并行运行模型训练,加快训练速度。该函数可以指定进程数量、每个进程的参数、函数名称等。 ### 回答2: torch.multiprocessing.spawn是一种多进程创建和启动的方式,它是PyTorch中多进程的一种实现方式。由于GIL(全局锁)的存在,Python不能真正并行地运行多个线程,所以在训练和处理大量数据时,多进程是一种提高性能的常见技术。而所谓的spawn,也就是派生进程,是一种在父进程的基础上创建一个新的子进程并让它执行不同的代码的过程。而在torch.multiprocessing.spawn中,该过程由torch.multiprocessing.start_processes()函数完成。 torch.multiprocessing.spawn函数接收四个参数:fn、args、nprocs、join。其中fn是一个函数,它描述如何在每个进程中运行。args是一个表示每个进程的参数的元组,nprocs是要创建的进程数,join指定进程在运行完之后是否要立即结束。在函数fn中,将会根据当前进程的参数获取设备信息和进程ID,并根据这些信息判断当前进程所负责的是哪一部分数据,并使用这些数据进行训练或其他操作。每个进程最终输出结果,并由主进程进行汇总。 torch.multiprocessing.spawn函数在创建多个进程时,会通过pickle将文件对象和变量传递给子进程。因此,在使用torch.multiprocessing.spawn时,应当谨慎处理pickle,避免潜在的安全问题。 总之,torch.multiprocessing.spawnPyTorch中一种创建和启动多个进程的方式。它通过启动多个进程,实现了多进程的训练。使用该函数,可以在训练和处理大量数据时提高性能并加速模型的训练。然而,在使用该函数时,需要注意文件对象和变量的序列化问题。 ### 回答3: torch.multiprocessing.spawnPyTorch中的一个工具,用于在多个进程中运行模型并行化代码。 它提供了一个简单的方式来创建多个进程并将它们分配给不同的计算资源,以同时运行多个模型并行化代码。因此,它可以显著缩短模型训练的时间,提高模型的训练效率。 PyTorch中的torch.multiprocessing.spawn函数的调用方式如下所示: ```python torch.multiprocessing.spawn(fn, args=(), nprocs=1, join=True, daemon=False, start_method='spawn') ``` 其中,参数fn是一个函数,这个函数就是需要在多个进程中并行执行的函数。args是fn函数的参数列表。nprocs是需要创建的进程数量,默认为1。join表示进程是否需要等待子进程完成后再结束,daemon表示进程是否是后台进程。start_method表示使用的进程启动方式,默认为spawn。 默认的start_method就是spawnspawn是使用forking的方式来创建进程,适用于Linux和MacOS系统。其他启动方式还包括fork、forkserver、以及在Windows上的spawn(Windows)。因为每种启动方式都有不同的适用环境,需要根据实际情况进行选择。 在使用torch.multiprocessing.spawn函数时,需要注意fn函数必须可序列化、可调用,否则程序会无法正常运行。另外,在fn函数内部对全局变量的修改,也会使程序无法正常运行。为了避免这种情况,可以采用分布式连接方式,使用隐式同步和广播方式来同步更新参数。 总之,torch.multiprocessing.spawn函数可以大大提高PyTorch模型训练的速度和效率,但是在使用时需要仔细考虑参数设置、序列化问题和全局变量修改等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值