如何在GPU上训练pytorch代码?

目录

如何在GPU上训练pytorch代码?

1.需要将哪些数据送入gpu里呢?

2. 如何将这三个部分送入gpu呢?

如何确认程序是否在GPU上跑——查看GPU使用情况

在Python代码中指定GPU

设置定量的GPU使用量

设置最小的GPU使用量

PyTorchGPU利用率较低问题原因:

 1.1 GPU内存占用率问题

1.2 GPU利用率问题

问题原因分析与总结记录:

3.1 模型提速技巧


如何在GPU上训练pytorch代码?

1.需要将哪些数据送入gpu里呢?

需要将模型,数据集,loss function这三个部分分别送入gpu里

2. 如何将这三个部分送入gpu呢?

使用cuda(),和to(device)指令

举例说明:

首先设定gpu:

 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

其次将模型放入gpu:

net.to(device)

再将数据集和loss function放入gpu里:

        x_batch = x_batch.cuda()
        y_batch = y_batch.cuda()

        loss = loss.to(device)
# 首先设定gpu
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
os.environ["CUDA_VISIBLE_DEVICES"] = "0,1,2,3"

# 如果epoch不为0,就加载已经训练过的ckpt
if epoch != 0:
    ckpt = os.path.join(opt.out_path, 'net.pth')
    
    if torch.cuda.is_available():
        device = torch.device("cuda:0")
        net.to(device)
        criterion.to(device)

        # 多块gpu只转移模型
        if torch.cuda.device_count() > 1:
            net = nn.DataParallel(net, device_ids=[0,1,2,3])
            net.to(device)

        net.load_state_dict(torch.load(ckpt))

# 否则不加载
else:
    if torch.cuda.is_available():
        device = torch.device("cuda:0")
        net.to(device)
        criterion.to(device)
        
        if torch.cuda.device_count() > 1:
            net = nn.DataParallel(net, device_ids=[0,1,2,3])
            net.to(device)


如何确认程序是否在GPU上跑——查看GPU使用情况

方法1:

使用cmd打开控制窗口,使用如下指令

命令: nvidia-smi

功能:显示机器上gpu的情况

命令: nvidia-smi -l

功能:定时更新显示机器上gpu的情况

命令:watch -n 3 nvidia-smi

功能:设定刷新时间(秒)显示GPU使用情况

 注意GPU的编号,在后面指定GPU时需要使用这个编号,我这边只有gpu 编号0

方法2: 打开任务管理器,快捷键esc+shift+ctrl查看cuda使用情况:比如我这里是42%,使用率不是很高


在Python代码中指定GPU

import os

os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

设置定量的GPU使用量

config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.9 # 占用GPU90%的显存
session = tf.Session(config=config)

设置最小的GPU使用量

config = tf.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.Session(config=config)

原文链接:https://blog.csdn.net/zqx951102/article/details/89462160


PyTorchGPU利用率较低问题原因:

服务器端或者本地pc端,

输入nvidia-smi

来观察显卡的GPU内存占用率(Memory-Usage),显卡的GPU利用率(GPU-util),然后采用top来查看CPU的线程数(PID数)和利用率(%CPU)

 1 GPU内存占用率问题

这是由于模型的大小以及batch size的大小,来影响这个指标。

  • GPU的内存占用率主要是模型的大小,包括网络的宽度,深度,参数量,中间每一层的缓存,都会在内存中开辟空间来进行保存,所以模型本身会占用很大一部分内存。
  • 其次是batch size的大小,也会占用影响内存占用率。batch size设置为128,与设置为256相比,内存占用率是接近于2倍关系。当你batch size设置为128,占用率为40%的话,设置为256时,此时模型的占用率约等于80%所以在模型结构固定的情况下,尽量将batch size设置大,充分利用GPU的内存。

2 GPU利用率问题

这个是Volatile GPU-Util表示,当没有设置好CPU的线程数时,这个参数是在反复的跳动的,这样停息1-2 秒然后又重复起来。其实是GPU在等待数据从CPU传输过来,当从总线传输到GPU之后,GPU逐渐起计算来,利用率会突然升高,但是GPU的算力很强大,0.5秒就基本能处理完数据,所以利用率接下来又会降下去,等待下一个batch的传入。因此,这个GPU利用率瓶颈在内存带宽和内存介质上以及CPU的性能上面。

另外的一个方法是,在PyTorch这个框架里面,数据加载Dataloader上做更改和优化,包括num_workers(线程数),pin_memory,会提升速度。解决好数据传输的带宽瓶颈和GPU的运算效率低的问题。在TensorFlow下面,也有这个加载数据的设置。

 torch.utils.data.DataLoader(image_datasets[x], batch_size=batch_size, shuffle=True,num_workers=8,pin_memory=True)
 

为了提高利用率,首先要将num_workers(线程数)设置得体,4,8,16是几个常选的几个参数,建议打开pin_memory打开,就省掉了将数据从CPU传入到缓存RAM里面,再给传输到GPU上;为True时是直接映射到GPU的相关内存块上,省掉了一点数据传输时间。


问题原因分析与总结记录:

因为训练的主要时间都花在了写日志上,文件IO耗时特别多,尤其是我设置的写入间隔还很小,所以GPU计算一瞬间,然后写很久的记录,计算一瞬间,再写很久的记录,最终导致速度特别慢。

在调试过程,
命令:top 实时查看你的CPU的进程利用率,这个参数对应你的num_workers的设置;
命令: watch -n 0.5 nvidia-smi 每0.5秒刷新并显示显卡设置。
实时查看你的GPU的使用情况,这是GPU的设置相关。这两个配合好。包括batch_size的设置。

最后总结一下,有的时候模型训练慢并不是因为显卡不行或者模型太大,而是在跑模型过程中有一些其他的操作导致速度很慢,尤其是文件的IO操作,这会导致GPU得不到连续性使用,整体速度特别慢。

第一:是增加batch size,增加GPU的内存占用率,尽量用完内存,而不要剩一半,空的内存给另外的程序用,两个任务的效率都会非常低。
第二:在数据加载时候,将num_workers线程数设置稍微大一点,推荐是8,16等,且开启pin_memory=True。不要将整个任务放在 主进程里面做,这样消耗CPU,且速度和性能极为低下。

模型GPU提速技巧

  • 减少日志IO操作频率
  • 使用pin_memory和num_workers
  • 使用半精度训练
  • 更好的显卡,更轻的模型

另外也可以通过增大batch size提高epoch速度,但是收敛速度也会变慢,需要再适当升高学习率

 作者:汀丶人工智能技术
原文链接:https://www.zhihu.com/question/455084239/answer/2803649363


猜你喜欢

转载自blog.csdn.net/Viviane_2022/article/details/128403436