Pytorch 如何加速Dataloader提升数据读取速度


Posted in Python onMay 28, 2021

在利用DL解决图像问题时,影响训练效率最大的有时候是GPU,有时候也可能是CPU和你的磁盘。

很多设计不当的任务,在训练神经网络的时候,大部分时间都是在从磁盘中读取数据,而不是做 Backpropagation 。

这种症状的体现是使用 Nividia-smi 查看 GPU 使用率时,Memory-Usage 占用率很高,但是 GPU-Util 时常为 0% ,如下图所示:

Pytorch 如何加速Dataloader提升数据读取速度

如何解决这种问题呢?

在 Nvidia 提出的分布式框架 Apex 里面,我们在源码里面找到了一个简单的解决方案:

https://github.com/NVIDIA/apex/blob/f5cd5ae937f168c763985f627bbf850648ea5f3f/examples/imagenet/main_amp.py#L256 ​

class data_prefetcher():
    def __init__(self, loader):
        self.loader = iter(loader)
        self.stream = torch.cuda.Stream()
        self.mean = torch.tensor([0.485 * 255, 0.456 * 255, 0.406 * 255]).cuda().view(1,3,1,1)
        self.std = torch.tensor([0.229 * 255, 0.224 * 255, 0.225 * 255]).cuda().view(1,3,1,1)
        # With Amp, it isn't necessary to manually convert data to half.
        # if args.fp16:
        #     self.mean = self.mean.half()
        #     self.std = self.std.half()
        self.preload()

    def preload(self):
        try:
            self.next_input, self.next_target = next(self.loader)
        except StopIteration:
            self.next_input = None
            self.next_target = None
            return
        with torch.cuda.stream(self.stream):
            self.next_input = self.next_input.cuda(non_blocking=True)
            self.next_target = self.next_target.cuda(non_blocking=True)
            # With Amp, it isn't necessary to manually convert data to half.
            # if args.fp16:
            #     self.next_input = self.next_input.half()
            # else:
            self.next_input = self.next_input.float()
            self.next_input = self.next_input.sub_(self.mean).div_(self.std)

我们能看到 Nvidia 是在读取每次数据返回给网络的时候,预读取下一次迭代需要的数据,

那么对我们自己的训练代码只需要做下面的改造:

training_data_loader = DataLoader(
    dataset=train_dataset,
    num_workers=opts.threads,
    batch_size=opts.batchSize,
    pin_memory=True,
    shuffle=True,
)
for iteration, batch in enumerate(training_data_loader, 1):
    # 训练代码

#-------------升级后---------

data, label = prefetcher.next()
iteration = 0
while data is not None:
    iteration += 1
    # 训练代码
    data, label = prefetcher.next()

这样子我们的 Dataloader 就像打了鸡血一样提高了效率很多,如下图:

Pytorch 如何加速Dataloader提升数据读取速度

当然,最好的解决方案还是从硬件上,把读取速度慢的机械硬盘换成 NVME 固态吧~

补充:Pytorch设置多线程进行dataloader时影响GPU运行

使用PyTorch设置多线程(threads)进行数据读取时,其实是假的多线程,他是开了N个子进程(PID是连续的)进行模拟多线程工作。

以载入cocodataset为例

DataLoader

dataloader = torch.utils.data.DataLoader(COCODataset(config["train_path"],
                                                     (config["img_w"], config["img_h"]),
                                                     is_training=True),
                                         batch_size=config["batch_size"],
                                         shuffle=True, num_workers=32, pin_memory=True)

numworkers就是指定多少线程的参数,原为32。

检查GPU是否运行该程序

查看运行在gpu上的所有程序:

fuser -v /dev/nvidia*

如果没有返回,则该程序并没有在GPU上运行

指定GPU运行

将num_workers改成0即可

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python监控网卡流量并使用graphite绘图的示例
Apr 27 Python
基于python实现的抓取腾讯视频所有电影的爬虫
Apr 22 Python
python实现装饰器、描述符
Feb 28 Python
pandas apply 函数 实现多进程的示例讲解
Apr 20 Python
Python QQBot库的QQ聊天机器人
Jun 19 Python
python实现对服务器脚本敏感信息的加密解密功能
Aug 13 Python
什么是python类属性
Jun 10 Python
Python中logging日志记录到文件及自动分割的操作代码
Aug 05 Python
浅谈python数据类型及其操作
May 25 Python
pandas中DataFrame检测重复值的实现
May 26 Python
解决pytorch 损失函数中输入输出不匹配的问题
Jun 05 Python
Python中的嵌套循环详情
Mar 23 Python
在前女友婚礼上,用Python破解了现场的WIFI还把名称改成了
pytorch DataLoader的num_workers参数与设置大小详解
May 28 #Python
Flask搭建一个API服务器的步骤
May 28 #Python
Python趣味挑战之给幼儿园弟弟生成1000道算术题
May 28 #Python
解决Python中的modf()函数取小数部分不准确问题
May 28 #Python
利用Python+OpenCV三步去除水印
python实现自定义日志的具体方法
May 28 #Python
You might like
《猛禽小队》:DC宇宙的又一超级大烂片
2020/04/09 欧美动漫
ajax缓存问题解决途径
2006/12/06 PHP
PHP 字符串编码截取函数(兼容utf-8和gb2312)
2009/05/02 PHP
joomla jce editor 解决上传中文名文件失败问题
2013/06/09 PHP
ThinkPHP之R方法实例详解
2014/06/20 PHP
基于PHP给大家讲解防刷票的一些技巧
2015/11/18 PHP
js 判断计算字符串长度/判断空的简单方法
2013/08/05 Javascript
js导出table到excel同时兼容FF和IE示例
2013/09/03 Javascript
对js关键字命名的疑问介绍
2014/04/25 Javascript
JQuery 给元素绑定click事件多次执行的解决方法
2014/09/09 Javascript
js表格排序实例分析(支持int,float,date,string四种数据类型)
2015/05/06 Javascript
javascript实现简单的ajax封装示例
2016/12/28 Javascript
nodejs mysql 实现分页的方法
2017/06/06 NodeJs
Vue CLI3.0中使用jQuery和Bootstrap的方法
2019/02/28 jQuery
AngularJS动态生成select下拉框的方法实例
2019/11/17 Javascript
javascript History对象原理解析
2020/02/17 Javascript
微信小程序动态添加和删除组件的现实
2020/02/28 Javascript
js实现无刷新监听URL的变化示例代码详解
2020/06/03 Javascript
JS访问对象两种方式区别解析
2020/08/29 Javascript
vue keep-alive的简单总结
2021/01/25 Vue.js
python基础教程之Hello World!
2014/08/29 Python
Python的动态重新封装的教程
2015/04/11 Python
Python的Asyncore异步Socket模块及实现端口转发的例子
2016/06/14 Python
详解Python3中字符串中的数字提取方法
2017/01/14 Python
详谈python3中用for循环删除列表中元素的坑
2018/04/19 Python
python机器学习之KNN分类算法
2018/08/29 Python
浅述python中深浅拷贝原理
2018/09/18 Python
浅析PyTorch中nn.Module的使用
2019/08/18 Python
Django实现任意文件上传(最简单的方法)
2020/06/03 Python
Python如何爬取b站热门视频并导入Excel
2020/08/10 Python
施华洛世奇加拿大官网:SWAROVSKI加拿大
2018/06/03 全球购物
科级干部考察材料
2014/02/15 职场文书
古汉语文学求职信范文
2014/03/16 职场文书
八项规定个人对照检查材料思想汇报
2014/09/25 职场文书
工作检讨书范文
2015/01/23 职场文书
简历自我评价优缺点
2015/03/11 职场文书