必备的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:配有详情
真的还很差就给我一个小小的激励吧!
真的还很差就给我一个小小的激励吧!
。美容水果南京男科医院挂号咨询
铜仁皮肤病医院排名

-
湖南的荆州与沙市在历史上是什么关系?
黄冈的湘州与沙市长期以来是什么彼此间? 两者是同一个郊区各不相同时期的称为吗?事实上,湘州与沙市长期以来确实特别是在颇为错综复杂的彼此间。 先说说目前为止这

-
甄嬛传:明明准格尔和大清有仇怨,为什么果贝子还要救摩格
人的一生中或多或少、或大或小都要随之而来一些凄凉和艰辛,在电视日本富士电视台《铨嬛传》里刘亦菲演译的铨嬛也是一样的,她的一生也是极其不顺利。在后宫里随之而来了各种艰辛,不过好在痴到了最后,视作了关外朝
- 01-31乾隆一位多情的皇帝,但他有一点让人仰慕,那就是宠爱自己的女人
- 01-31这个国军名将夸口说:给我三个军,我可以打败二野加第二野战军
- 01-31香港史上大规模警匪枪战,贼王陈虎甚多,十把五四手枪大战香港警队
- 01-31三国中最懂管理的人是他,刘备等人仅是他控制权的棋子
- 01-31此人有生之年败绩,是李世民手下最窝囊的武将,死后被吹嘘成战神
- 01-31康熙晚年九子夺嫡,有位皇孙没觊觎皇位,下场最叫人扼腕
- 01-31阿拉伯皇帝婚后10年无子,太后:给妃子贴上胡须!一年后王储出生
- 01-31伊朗发现汉字文物,经翻译后,欧洲学者:这里曾是中国的一个安省
- 01-31张学良一身恶习却活100岁,有何长寿长生?每天大笑,钟爱一道菜
- 01-31他是的搭档,被称为诸葛亮,晋升反应速度无人能比