pytorch 单机多卡--DistributedDataParallel+混合精度--提高速度,减少内存占用

Pytorch使用DDP加载模型时出现多进程在GPU0上占用过多显存的问题 Pytorch使用DDP加载模型时出现多进程在GPU0上占用过多显存的问题,此问题可能导致GOU0在训练过程中爆显存。 阅读详情

DataParallel巨慢,DistributedDataParallel巨快!
在这里插入图片描述
DataParallel的并行处理机制:DataParallel是将输入一个 batch 的数据均分成多份,分别送到对应的 GPU 进行计算,各 个 GPU 得到的梯度累加。与 Module 相关的所有数据也都会以浅复制的方式复制多份。每个 GPU 将针对各自的输入数据独立进行 forward 计算,在 backward 时,每个卡上的梯度会汇总到原始的 module 上,再用反向传播更新单个 GPU 上的模型参数,再将更新后的模型参数复制到剩余指定的 GPU 中,以此来实现并行。

DataParallel会将定义的网络模型参数默认放在GPU 0上,所以dataparallel实质是可以看做把训练参数从GPU拷贝到其他的GPU同时训练,这样会导致内存和GPU使用率出现很严重的负载不均衡现象,即GPU 0的使用内存和使用率会大大超出其他显卡的使用内存,因为在这里GPU0作为master来进行梯度的汇总和模型的更新,再将计算任务下发给其他GPU,所以他的内存和使用率会比其他的高。
参考链接:
Pytorch 分布式并行训练 + 半精度/混合精度训练

示例:

from torch.utils.data.distributed import DistributedSampler
from apex import amp  # 使用混合精度
import torch.distributed as dist
import argparse, os
import MMVAE#my function file
#如果还import了其他子函数文件,无需对子函数文件中再进行这些操作
# from gpu_mem_track import MemTracker  # 引用显存跟踪代码
os.environ['CUDA_LAUNCH_BLOCKING'] = '1'
os.environ['CUDA_VISIBLE_DEVICES']="4,5,2,8"
print('torch.cuda.device_count()',torch.cuda.device_count())
os.environ["WORLD_SIZE"]='4'   #4个进程
os.environ['MASTER_ADDR']='127.0.0.1'
os.environ['MASTER_PORT']='29500'#此端口不可变,否则会卡住
parser = argparse.ArgumentParser()
parser.add_argument("--local_rank", type=int, default=0)
args = parser.parse_args()

dist.init_process_group("nccl", init_method='env://')
rank = dist.get_rank()
local_rank = os.environ['LOCAL_RANK']
master_addr = os.environ['MASTER_ADDR']
master_port = os.environ['MASTER_PORT']
print(f"rank = {rank} is initialized in {master_addr}:{master_port}; local_rank = {local_rank}")
torch.cuda.set_device(rank)
local_rank = rank
torch.cuda.set_device(local_rank)
device = torch.device("cuda", local_rank)
world_size = dist.get_world_size()  # os.environ["WORLD_SIZE"]
print('world_size',world_size)

#数据并行
milan_datase = ……
sampler = DistributedSampler(milan_dataset, num_replicas=world_size, shuffle=True)
    train_loader = DataLoader(dataset=milan_dataset,
                             batch_size=batch_size,
                             shuffle=False,
                             sampler=sampler)
#模型并行
model=……
model.to(device)
optimizer = torch.optim.Adam([{'params': model.parameters()}], lr=0.1)#
model = torch.nn.parallel.DistributedDataParallel(model,
                                                  device_ids=[local_rank],
                                                  output_device=local_rank)

#训练阶段整合loss,测试阶段类似。仅仅是为了打印的时候,打印四个卡的loss的平均。反向传播的时候还是用各自的loss传播。

if batch_i % 10 == 0:
	# We manually reduce and average the metrics across processes. In-place reduce tensor.
	reduced_loss = reduce_tensor(losses.data)
	losses1.update(to_python_float(reduced_loss), all_input.size(1))  # update needs average and number
	torch.cuda.synchronize()
	epoch_loss += losses1.item()

运行:

 #单机4个GPU
python3 -m torch.distributed.launch --nproc_per_node=4 trainModel_distr_gpus.py  

出现错误:

RuntimeError: Expected to have finished reduction in the prior iteration before starting a new one. This error indicates that your module has parameters that were not used in producing loss. You can enable unused parameter detection by (1) passing the keyword argument find_unused_parameters=True to torch.nn.parallel.DistributedDataParallel; (2) making sure all forward function outputs participate in calculating loss. If you already have done the above two steps, then the distributed data parallel module wasn't able to locate the output tensors in the return value of your module's forward function. Please include the loss function and the structure of the return value of forward of your module when reporting this issue (e.g. list, dict, iterable)

使用单卡调试,在loss.backward()之后optimizer.step()之前加入下面代码:

for name, param in model.named_parameters():
    if param.grad is None:
        print(name)

打印出来的参数就是没有参与loss运算的部分,他们梯度为None
在这里插入图片描述
是因为encoder模型中定义了一个没有用到的initial模型,注释掉就好了!在这里插入图片描述
使用混合精度:

from apex import amp  # 使用混合精度
model, optimizer = amp.initialize(model, optimizer,
                                 opt_level="O1")  # 如果使用apex混合精度训练,初始化放在model和optimizer定义之后,DDP之前
with amp.scale_loss(loss, optimizer) as scaled_loss:
   scaled_loss.backward()
optimizer.step()

在这里插入图片描述
在这里插入图片描述
仔细看报错追溯信息,可以看到大概还是混合精度包apex未装好,
在这里插入图片描述
混合精度链接
因为安装amp包没成功,直接使用torch 原生支持的amp。
只需要安装有pytorch就能使用,而且代码也简单。限制条件只有一个就是pytorch的版本一定>1.6。主要是利用了这两个API——torch.cuda.amp.GradScalar 和 torch.cuda.amp.autocast。

from torch.cuda.amp import autocast as autocast, GradScaler
 
>>>>>>>>
other code
>>>>>>>>
 
# 在训练最开始之前实例化一个GradScaler对象
scaler = GradScaler()
 
>>>>>>>>
#alternatively   #注意自定义的model中也要with autocast()
MyModel(nn.Module):
    def forward(self, input):
        with autocast():
            ...
data=*****
model = torch.nn.parallel.DistributedDataParallel(model,
                                                  device_ids=[local_rank],
                                                  output_device=local_rank)
optimizer=optim.SGD(model.parameters(),lr=0.1)
for epoch in epochs:
  for input,target in data:
    optimizer.zero_grad()
>>>>>>>>
        # 前向过程(model + loss)开启 autocast
        with autocast():
            output = model(input)
            loss = loss_fn(output, target)
 
        # Scales loss,这是因为半精度的数值范围有限,因此需要用它放大
        scaler.scale(loss).backward()
 
        # scaler.step() unscale之前放大后的梯度,但是scale太多可能出现inf或NaN
        # 故其会判断是否出现了inf/NaN
        # 如果梯度的值不是 infs 或者 NaNs, 那么调用optimizer.step()来更新权重,
        # 如果检测到出现了inf或者NaN,就跳过这次梯度更新,同时动态调整scaler的大小
        scaler.step(optimizer)
 
        # 查看是否要更新scaler,这个要注意不能丢
        scaler.update()
 
 
>>>>>>>>
other code
>>>>>>>>

更加详细的混合精度教程

命令行改进
自动化启动多进程

单击多卡执行多个并行程序
注意:端口号和py文件名不能重复!
Pytorch distributed RuntimeError: Address already in use

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

脚本顺序启动多个程序+传参交互
参考:
传参交互
import os
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(‘-set_num’, help=‘dataset’, type=int, default=2)
parser.add_argument(‘-seq_length’, help=‘history_seq_length’, type=int, default=40)
parser.add_argument(‘-future_length’, help=‘future_seq__length’, type=int, default=1)
args = parser.parse_args()

set_num = args.set_num

脚本编写:run.sh

milan=1
london=2
#history=(40 60 80)
#future=(1 4 8)
history=(60 80 40)
future=(1 4 8)
for((i=0;i<=2;i++))
do
  for((j=0;j<=2;j++))
  do
    python3 -m torch.distributed.launch --nproc_per_node=4 --master_port 29999 trainModel_distr_gpus.py \
                -set_num $london\
                -seq_length ${history[i]} \
                -future_length ${future[j]}
    wait
  done
done

wait
#history1=(60 90 120)
#future1=(1 6 12)
history1=(60 120 90)
future1=(1 6 12)
for((i=0;i<=2;i++))
do
  for((j=0;j<=2;j++))
  do
    python3 -m torch.distributed.launch --nproc_per_node=4 --master_port 29999 trainModel_distr_gpus.py \
                -set_num $milan\
                -seq_length ${history1[i]} \
                -future_length ${future1[j]}
    wait
  done
done

运行:

bash ./run.sh

./run.sh: line 5: syntax error near unexpected token `$‘\r’’
解决

sed -i 's/\r//g' run.sh

挂在后台运行:

nohup bash ./run.sh &

一些坑:
1、如果运行程序时,卡在以下
在这里插入图片描述
大概率是因为运行命令中写的端口号或py文件名与源代码不一致,仔细检查一下!

pytorch单机多卡:从DataParallel到distributedDataParallel pytorch单机多卡:从DataParallel到distributedDataParallel 最近想做的实验比较多,于是稍微学习了一下和pytorch相关的加速方式。本人之前一直在使用DataParalle 阅读详情

相关推荐

【亲测】ubuntu20.4 安装CUDA11.8

一步一步搭建C++ CUDA CUDNN TENSORRT OPENCV DNN ONNXRUNTIME推理环境

weixin_40950590的博客 3894

pytorch中的单机多卡和多机多卡

pytorch 单机多卡的正确打开方式pytorch 使用单机多卡,大体上有两种方式简单方便的 torch.nn.DataParallel(很 low,但是真的很简单很友好)使用 torch.distributed 加速并行训练(推荐,但是不友好)首先讲一下这两种方式分别的优缺点nn.DataParallel优点:就是简单缺点就是:所有的数据要先load到主GPU上,然后再分发给每个GPU去train,注意这时候主GPU的显存占用很大,你想提升batch_size,那你的主GPU就会限制。

liguandong 4520

Arduino Nano + MCP3422A0 ADC 毫欧表:3档分辨率(0.1mΩ-1.3kΩ)开尔文连接实测

本文详细介绍了如何使用Arduino Nano与MCP3422A0 ADC构建高精度毫欧表,采用四线制开尔文连接和三档量程设计,实现0.1mΩ-1.3kΩ的精确测量。通过精密恒流源和18位ADC技术,结合智能量程切换和数字滤波算法,显著提升测量精度和稳定性,适用于电子维修、PCB测试等场景。

weixin_28292761的博客 323

使用pytorch的distributeddataparallel遇到GPU0显存不均衡

使用pytorch的distributeddataparallel遇到GPU0显存不均衡

qq_42296251的博客 764

【论文导读】ICDM2018|SASRec---基于自注意力机制的序列推荐(召回)

前言本次分享2018年发表在ICDM上的论文----「Self-Attentive Sequential Recommendation」。主要是应用self-attention机制来做一...

Blank_Space 8033

【PLC】三菱PLC控件安装疑难解析:Error Number:-119的全面解决方案

本文针对三菱PLC控件安装过程中常见的Error Number:-119错误,提供了深度解析与实战解决方案。该错误通常源于Windows系统权限限制或文件冲突。文章从理解错误本质入手,逐步介绍了以管理员身份运行、手动注册DLL文件、采用新版环境搭配旧版控件的黄金组合以及系统环境修复等四大招法,帮助用户彻底解决这一安装难题,确保工控软件稳定运行。

jj890的博客 496

torch.nn.parallel.DistributedDataParallel使用中卡在第一个epoch的原因之一

torch.nn.parallel.DistributedDataParallel的模型在进行eval()的时候必须加上with torch.no_grad(),否则就会导致一个卡卡死在运行eval()后的代码,而其他卡仍然在进行训练,其他卡不再等这个进行eval()的卡。 在使用中有一个地方很容易错误,代码如下: if int(os.environ.get('RANK')) == 0: with torch.no_grad(): # print('dd0')

jiongta9473的博客 2520

SAP VC实战:用CU01和CS02搞定BOM里的‘智能’对象相关性(附语法避坑指南)

在工业制造领域,产品配置的复杂性往往超出想象。想象一下,当客户需要定制一台工业设备时,可能有数百种配置选项相互影响——从基础材质到动力系统,从控制模块到安全装置。如何在SAP系统中优雅地管理这种复杂性?对象相关性(Object Dependencies)就是解决这一挑战的利器。

weixin_42524824的博客 467

【多卡运行】(未完待续)

在带有多GPU的机器上运行代码,只要在原始单GPU代码中模型定义完成后面,添加以下代码即可,这样会默认在所有的GPU上进行训练,特别注意:若banchsize=30,则在单GPU上是30个样本一组进行训练,在2个GPU上并行训练,则是每个GPU上15个样本,以此类推。所以可以考虑增加banchsize的值,即设置为30*GPU个数。

闪闪发光的博客 887

图像紫边消除(depurple)

对图像紫边形成原因、消除方法进行了介绍。

沧海一升的博客 7565

基于YOLO26深度学习框架的人脸识别门禁系统的算法研究实现方法

本文研究了基于YOLO26深度学习框架的人脸识别门禁系统实现方法。系统采用YOLO26目标检测算法,通过CSPDarknet53主干网络、特征金字塔结构和注意力机制实现高效人脸检测。研究内容包括数据预处理、模型训练优化和身份验证等关键技术,使用迁移学习策略和CIoU损失函数提升检测精度。该系统可应用于智能安防场景,具有实时性强、识别准确的特点,为门禁管理提供了智能化解决方案。

一键难忘的博客 766

实践教程|PyTorch训练加速技巧

点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达作者丨用什么名字没那么重要@知乎(已授权)来源丨https://zhuanlan.zhihu.com/p/360697168编辑丨极市平台极市导读本篇讲述了如何应用torch实现混合精度运算、数据并行和分布式运算。由于最近的程序对速度要求比较高,想要快速出结果,因此特地学习了一下混合精度运算和并行化操作,由于已经有很多的文章介...

小白学视觉 522

用一个稳定的 Deep Link,直接打开 SAP CRM WebClient 里的 Sales Order 创建界面

本文详细介绍了如何在SAP CRM WebClient UI中构建直接进入销售订单创建页面的Deep Link URL。关键步骤包括:1) 通过SMICM和SICF确认系统入口路径及端口;2) 使用BSP_DLC_SDESIGN或F2功能获取Sales Order的对象类型;3) 确保创建动作(D)能正确映射到目标页面;4) 按规范拼接包含sap-client、saprole等参数的完整URL。文章还提供了ABAP代码示例自动生成URL,并提醒注意浏览器缓存问题。通过这种标准化导航方式,可以实现稳定的页面直

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 211

【深度学习】多卡训练__单机多GPU方法详解(torch.nn.DataParallel、torch.distributed)

多GPU训练能够加快模型的训练速度,而且在单卡上不能训练的模型可以使用多个小卡达到训练的目的。多GPU训练可以分为单机多卡和多机多卡这两种,后面一种也就是分布式训练——训练方式比较麻烦,而且要关注的性能问题也有很多,据网上的资料有人建议能单机训练最好单机训练,不要使用多机训练。本文主要对单机多卡训练的实现展开说明。

weixin_44955407的博客 4885

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

pytorch单精度、半精度、混合精度、单卡、多卡(DP / DDP)、FSDP、DeepSpeed模型训练

pytorch单精度、半精度、混合精度、单卡、多卡(DP / DDP)、FSDP、DeepSpeed(环境没搞起来)模型训练代码,并对比不同方法的训练速度以及GPU内存的使用

胖胖大海的博客 7007

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【转】DataParallel & DistributedDataParallel分布式训练-转载只为记录

model = nn.DataParallel(model) 测试结果相差特别多(如下图所示),加了这句mIoU是第一个结果0.8847,没加是0.4929(以mIoU为例,可以看到其他各项指标也都掉的严重),所以决定花点心思把nn.DataParallel(model)搞清楚。 指标结果掉的严重 这里需要注意一下:多卡训练要考虑通信开销的, 是个trade-off的过程,不见得四块卡一定比两块卡快多少,训练到四块卡的时候可能io通信开销已经占了大头。 nn.DataParallel() ...

qq_36955294的博客 1376

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

pytorch 分布式实践(一)

学习资源 实践踩坑 1,model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.local_rank]) 卡住不动 python -u -m torch.distributed.launch --nproc_per_node=2 train_single_label.py --batch_size=4 --data_path=/mnt/dataset --model_name=mobilenetv3_large_10

jaffe的博客 480

【计算系统】分布式训练:DDP单机多卡并行实战

分布式训练是一种模型训练范式,涉及在多个工作节点上分散训练工作量,从而显著提高训练速度和模型准确性。虽然分布式训练可以用于任何类型的ML模型训练,但将其用于大型模型和计算要求高的任务(如深度学习)是最有益的。

小哲的博客 4291

【深度学习实战(27)】「分布式训练」DDP单机多卡并行指南

【深度学习实战(27)】「分布式训练」DDP单机多卡并行指南

m0_51579041的博客 2510

【PyCharm远程连接服务器,调试torch.distributed.launch分布式程序,无需.sh,命令行操作】

PyCharm远程连接服务器,调试torch.distributed.launch分布式程序,无需.sh,命令行操作

topgun666的博客 1702

nn.DataParallel失效卡死,无输出

解决torch.nn.DataParallel卡死在foward()处,无输出

studyduts的博客 2400

pytorch单机多卡DistributedDataParallel (DDP)分布式训练

利用pytorch的DistributedDataParallel进行单机多卡分布式训练。

xwyljt的博客 3320

DistributedDataParallel后台单机多卡训练

后台单机多卡训练 文章目录后台单机多卡训练参考链接如何单机多卡DistributedDataParallel如何后台训练screen ......nohup train.sh ..... 参考链接 Pytorch分布式训练(单机多卡) Linux screen命令 Linux使用screen执行长时间运行的任务 如何单机多卡 一种是torch.nn.DataParallel,但是这种会有内存分配不平衡的弊端,因此这里采用的是官方推荐的torch.nn.parallel.DistributedDataP

椰子奶糖的博客 2215

分布式训练:DataParallel、DistributedDataParallel的用法和区别

在反向传播时...,使用DataParallel时,数据的使用是并行的,每张卡获得的数据都一样多,但是输出的loss则是所有的卡的loss都会在第output_device块GPU进行计算,这导致了output_device卡的负载进一步增加。在反向传播时,每个GPU上的梯度汇总到主GPU上,求得梯度均值更新模型参数后,再复制到其它GPU,以此来实现并行。

weixin_45914748的博客 1387

以MNIST数据集为例进行单机多卡训练(DP和DDP)

DP是单进程多线程的简单并行方式,将模型复制到多个GPU,数据切分后分发到不同GPU计算,最后在主GPU聚合梯度。DDP是多进程并行,每个GPU独立运行一个进程,通过NCCL通信同步梯度,效率更高且无主GPU瓶颈。在单机多卡环境下使用PyTorch训练MNIST数据集时,可以通过。两种方式实现多卡并行。

午夜的行人 589
上一篇: 非参贝叶斯 高斯过程 狄利克雷过程 高斯混合 中国餐馆 狄利克雷分布
下一篇: Linux服务器没有图形界面,无法使用matplotlib.plt.show()和matplotlib.plt.plot()函数
cloudless_sky
博客等级 码龄8年 106粉丝 128原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值