ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Pytorch训练时GPU占用率低0%

2022-01-29 14:03:44  阅读:464  来源: 互联网

标签:读取 img dataset Pytorch train npy path GPU 占用率


问题描述

最近在做毕业设计的论文,训练CNN的时候用nvidia-smi命令查看显卡占用率的时候发现一个事:
显存占用上去了,但是GPU利用率一直为0%或者频繁跳动(图来自网络)

数据集用的1万张图,7000左右拿来训练,用resnet-18网络,图resize成112*112的灰度图,GPU-A4000。训练一个epoch大概30S......

dataloader部分的解决方法

  1. 增加dataloader的num_num_workers数量(这个函数应放在main函数里执行,不然会报错)。一般设置为与CPU核心数相同的(这条建议我是从租GPU的网站看到的),不过设置过高并没有用反而性能降低。可以从2,4,6....这样的逐步增加,看看多少合适
  train_loader = data.DataLoader(dataset=train_dataset,
                                 batch_size=512,
                                 shuffle=False, num_workers=6)

2.修改dataloader的prefetch_factor(pytorch版本1.7以上的新特性,我用的Pytorch-1.8.1可以使用),default=2,表示有2 * num_workers样本会被提前取出

    train_loader = data.DataLoader(dataset=train_dataset,batch_size=512,
                                 num_workers=6,prefetch_factor=4)
                                   

3.设置dataloader的persistent_workers。如果为True表示dataset被使用后进程不会被关闭,会一直保持

train_loader = data.DataLoader(dataset=train_dataset,batch_size=512,
                                 num_workers=6,prefetch_factor=4,
                                 persistent_workers=True
)

上述部分的解释可能与pytorch官方文档有一些出入,详细可以见:https://pytorch.org/docs/stable/data.html

从数据集本身

一般的数据读取方法

  1. 从csv等等文件读取注释信息。以分类任务为例:有图片的路径,和要分类的结果。(img:/root/path/苹果.jpg label:'apple'这样的格式)
  2. 根据注释的path用cv2,PIL等库对图片读取。以PIL读取为例
from PIL import Image
Image.open(img_path).convert("L")

3.在dataset里使用的时候,读取注释path,转换label为数字

    def __getitem__(self, index):
        'Generates one sample of data'
        img_path = 根据index从csv文件获取路径
        label = 根据index从csv文件获取标签
        X = Image.open(img_path).convert("L")
        y = torch.tensor(label)

        return X, y

==========》这样写是很普遍的用法,如果用SSD读取还好,SSD的速度很快。但是!!我租GPU的网站硬盘是机械的,这就导致我大量的时间都耗费在IO上了
但是租GPU的网站有个好处-------->大内存,那么就可以考虑先把所有图片加载到内存中,然后直接映射读取,这样就解决了IO问题

解决方法

1.根据csv读取img_path,label信息
2.把图片和标签存入一个文件,这里我存入npy文件
3.在dataset初始化时直接读取npy文件,就加载到内存中------>后续从npy文件获取数据即可
4.npy文件的shape为[1000, 2] 1000行2列的矩阵
对于每一行元素 npy[i, 0]第一列表示img(注意是img,而不是img_path),npy[i, 1]第二列表示label
部分代码如下

ls = []
for line_index, line in df.iterrows():
    img_path = line.path
    val = line.cell_type_idx
    img_path = line.path
    # 读图片 灰度处理 方法缩小
    temp_img = Image.open(img_path).convert("L")
    temp_img = temp_img.resize([conf.IMAGE_WIDTH, conf.IMAGE_HEIGHT])
    temp_img = np.array(temp_img)
    # 存入npy
    ls.append([temp_img, val])
    
npy_file = np.array(ls)
np.save("/root/test.npy" (这个参数是你要存npy文件的地方), arr=npy_file (这个参数是需要保存的npy是什么))

在dataset中,初始化时就读取这个npy文件

class MyDataset(data.Dataset):
    'Characterizes a dataset for PyTorch'
    def __init__(self, train_type):
        'Initialization'
        train_npy ="/root/test.npy"
        train_npy = np.load(train_npy,allow_pickle=True)
        self.df = train_npy
        def __len__(self):
        'Denotes the total number of samples'
        return self.df.shape[0]

    def __getitem__(self, index):
        'Generates one sample of data'
        X = self.df[index, 0]
        X = np.array(X)
        y = torch.tensor(int(self.df[index, 1]))
        return X, y

最终效果

最初一个epoch:30s 现在一个epoch5s (进步巨大)

同时GPU占用也上去了

最后再加一个小技巧

让远程服务器的Nvidia-smi命令自动刷新结果 就不用每次都输入命令手动查看了

进入tmux等
nvidia-smi -l

标签:读取,img,dataset,Pytorch,train,npy,path,GPU,占用率
来源: https://www.cnblogs.com/Coder-Photographer/p/15854911.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有