当前位置:首页 >> IT
IT

必备的5种Pytorch并行新形式

2025-09-02 12:18

gpus = [0, 1, 2, 3]

torch.cuda.set_device( 'cuda:{}'.format(gpus[0]))

train_dataset = ...

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

model = ...

model = nn.DataParallel(model.to(device), device_ids=gpus, output_device=gpus[0])

optimizer = optim.SGD(model.parameters)

forepoch inrange(100):

forbatch_idx, (data, target) inenumerate(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

在 ImageNet 上的完整培训code,特地首页Github。

03

用到torch.distributed较慢分段培训

在 pytorch 1.0 之之后,此前终于对分布式的常用方法有开展了积体电路,支持 all-reduce,broadcast,send 和 receive 等等。通过 MPI 借助于 CPU 收发,通过 NCCL 借助于 GPU 收发。此前也曾在撰写道用 DistributedDataParallel 解决 DataParallel 比较慢,GPU 过载不互补的疑问,目之后仍未很转成熟了~

与 DataParallel 的单发挥作用管控多 GPU 相异,在 distributed 的为了让下,我们只须要编撰写一份code,torch 就但会系统会将其平仅分配给n个发挥作用,分别在n个 GPU 上行驶。

在 API 侧重,pytorch 为我们提供了 torch.distributed.launch 顺利完成机内,常用在命令行分布式地执行者 python 文件。在执行者反复中会,顺利完成机内但会将也就是说发挥作用的(或许就是 GPU的)index 通过匹配传递给 python,我们可以这样拿到也就是说发挥作用的 index:

parser = argparse.ArgumentParser

parser.add_argument( '--local_rank', default=-1, type=int,

help= 'node rank for distributed training')

args = parser.parse_args

print(args.local_rank)

接着,用到 init_process_group 设置GPU 二者之间收发用到的后端和终端:

dist.init_process_group(backend= 'nccl'

之之后,用到 DistributedSampler 对样本集开展界定。如此之后我们引介的那样,它能为了让我们将每个 batch 界定转成几个 partition,在也就是说发挥作用中会只须要得到和 rank 相关联的那个 partition 开展培训:

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

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

然后,用到 DistributedDataParallel 混搭框架,它能为了让我们为相异 GPU 上解的位移开展 all reduce(即概要相异 GPU 算出可得的位移,并该系统算出结果)。all reduce 后相异 GPU 中会框架的位移仅为 all reduce 之之后各 GPU 位移的仅系数:

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

之后,把样本和框架顺利完成时到也就是说发挥作用用到的 GPU 中会,正常人开展正反向传播方式:

torch.cuda.set_device(args.local_rank)

model.cuda

forepoch inrange(100):

forbatch_idx, (data, target) inenumerate(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

概要一下,torch.distributed 分段培训部分主要与如下code段有关:

# main.py

import torch

import argparse

import torch.distributed as dist

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 = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.local_rank])

optimizer = optim.SGD(model.parameters)

forepoch inrange(100):

forbatch_idx, (data, target) inenumerate(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

在用到时,呼叫 torch.distributed.launch 顺利完成机内顺利完成:

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

在 ImageNet 上的完整培训code,特地首页Github。

04

用到torch.multiprocessing引入顺利完成机内

有的学长可能比较出名 torch.multiprocessing,也可以手动用到 torch.multiprocessing 开展多发挥作用管控。绕开 torch.distributed.launch 系统会管控掀开和退出发挥作用的一些小毛病~

用到时,只须要呼叫 torch.multiprocessing.spawn,torch.multiprocessing 就但会为了让我们系统会创建发挥作用。如特地注意的code示意图,spawn 掀开了 nprocs=4 个虚拟机,每个虚拟机执行者 main_worker 并向其中会传布 local_rank(也就是说发挥作用 index)和 args(即 4 和 myargs)作为匹配:

import torch.multiprocessing as mp

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

这里,我们并不须要将当初须要 torch.distributed.launch 监管的执行者内容可,积体电路进 main_worker 表达式中会,其中会 proc 相关联 local_rank(也就是说发挥作用 index),ngpus_per_node 相关联 4, args 相关联 myargs:

def main_worker(proc, ngpus_per_node, 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)

forepoch inrange(100):

forbatch_idx, (data, target) inenumerate(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

在上面的code中会众所周知的是,由于不能 torch.distributed.launch 读取的匹配根目录作为配有,我们须要手动为 init_process_group 指定匹配:

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

概要一下,添加 multiprocessing 后分段培训部分主要与如下code段有关:

# 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, ngpus_per_node, 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)

forepoch inrange(100):

forbatch_idx, (data, target) inenumerate(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

在 ImageNet 上的完整培训code,特地首页Github。

05

用到Apex再进一步较慢

Apex 是 NVIDIA Ubuntu的常用复合精确度培训和分布式培训坎。Apex 对复合精确度培训的反复开展了积体电路,改两三行配有就可以开展复合精确度的培训,从而大幅度降低闪存迁出,节省运算整整。此外,Apex 也提供了对分布式培训的积体电路,针对 NVIDIA 的 NCCL 收发坎开展了最佳化。

在复合精确度培训上,Apex 的积体电路颇为优雅。并不须要用到 amp.initialize 混搭框架和最佳化机内,apex 就但会系统会为了让我们监管框架匹配和最佳化机内的精确度了,根据精确度需求相异可以传布其他配有匹配。

from apex import amp

model, optimizer = amp.initialize(model, optimizer

在分布式培训的积体电路上,Apex 在包包层的改动并不大,主要是最佳化了 NCCL 的收发。因此,大部分code仍与 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 的分段培训部分主要与如下code段有关:

# 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)

forepoch inrange(100):

forbatch_idx, (data, target) inenumerate(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 顺利完成机内顺利完成:

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

在 ImageNet 上的完整培训code,特地首页Github。

06

Horovod的优雅借助于

Horovod 是 Uber Ubuntu的最深处学习工具,它的发展吸取了 Facebook "Training ImageNet In 1 Hour" 与百度 "Ring Allreduce" 的低成本,可以无痛与 PyTorch/Tensorflow 等最深处学习框架结合,借助于分段培训。

在 API 侧重,Horovod 和 torch.distributed 颇为相近。在 mpirun 的为基础,Horovod 提供了自己积体电路的 horovodrun 作为顺利完成机内。

与 torch.distributed.launch 相近,我们只须要编撰写一份code,horovodrun 顺利完成机内就但会系统会将其平仅分配给n个发挥作用,分别在n个 GPU 上行驶。在执行者反复中会,顺利完成机内但会将也就是说发挥作用的(或许就是 GPU的)index 注入 hvd,我们可以这样拿到也就是说发挥作用的 index:

import horovod.torch as hvd

hvd.local_rank

与 init_process_group 相近,Horovod 用到 init 设置GPU 二者之间收发用到的后端和终端:

hvd.init

接着,用到 DistributedSampler 对样本集开展界定。如此之后我们引介的那样,它能为了让我们将每个 batch 界定转成几个 partition,在也就是说发挥作用中会只须要得到和 rank 相关联的那个 partition 开展培训:

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

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

之之后,用到 broadcast_parameters 混搭框架匹配,将框架匹配从编号为 root_rank 的 GPU 复制到所有其他 GPU 中会:

hvd.broadcast_parameters(model.state_dict, root_rank=0)

然后,用到 DistributedOptimizer 混搭最佳化机内。它能为了让我们为相异 GPU 上解的位移开展 all reduce(即概要相异 GPU 算出可得的位移,并该系统算出结果)。all reduce 后相异 GPU 中会框架的位移仅为 all reduce 之之后各 GPU 位移的仅系数:

hvd.DistributedOptimizer(optimizer, named_parameters=model.named_parameters, compression=hvd.Compression.fp16)

之后,把样本顺利完成时到也就是说 GPU 中会。在编撰写code时,我们只须要瞩目正常人开展反之亦然传播方式和反向传播方式:

torch.cuda.set_device(args.local_rank)

forepoch inrange(100):

forbatch_idx, (data, target) inenumerate(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

概要一下,Horovod 的分段培训部分主要与如下code段有关:

# main.py

import torch

import horovod.torch as hvd

hvd.init

torch.cuda.set_device(hvd.local_rank)

train_dataset = ...

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

train_dataset, num_replicas=hvd.size, rank=hvd.rank)

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

model = ...

model.cuda

optimizer = optim.SGD(model.parameters)

optimizer = hvd.DistributedOptimizer(optimizer, named_parameters=model.named_parameters)

hvd.broadcast_parameters(model.state_dict, root_rank=0)

forepoch inrange(100):

forbatch_idx, (data, target) inenumerate(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

在用到时,呼叫 horovodrun 顺利完成机内顺利完成:

CUDA_VISIBLE_DEVICES=0,1,2,3 horovodrun -np 4 -H localhost:4 --verbose python main.py

在 ImageNet 上的完整培训code,特地首页Github。

07

尾注

本文中会用到的 V100-PICE (之后 4 个 GPU)的配有:

平面图 2:配有详情

本文中会用到的 V100 (之后 4 个 GPU)的配有:

平面图 3:配有详情

本文中会用到的 K80 (之后 4 个 GPU)的配有:

平面图 4:配有详情

真的还很差就给我一个小小的激励吧!

真的还很差就给我一个小小的激励吧!

美容水果
南京男科医院挂号咨询
铜仁皮肤病医院排名

上一篇: 上手OPPO Find X5 Pro,为了它抛弃摩托罗拉s22+到底值不值?

下一篇: 新书推荐 | MATLAB函数及应用于

相关阅读
“爸爸,明天学长让带10000粒米”,宝爸质问学长,却遭当场打脸

男孩的成功和子女必不可少关系,相信现在的学生体会一定更深。 因为从男孩上幼儿园开始,家教就会构筑各种各样的家庭厂内以及育儿活动,很多学生为此也大伤脑筋。 因为劳累了一天就此好不更容易回

2021年研究生考生:学会3招助你一次考上研究生

2021年考研一段时间相符了!魏茨县一段时间,安排在12月26日至27日,将近3同一时间或有使用画板等特殊要求的应考必修在12月28日顺利完成。考研魏茨县一段时间的相符,既让考卷们有了一种预期感

友情链接