前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >pytorch如何将训练提速?

pytorch如何将训练提速?

作者头像
机器学习AI算法工程
发布2020-06-17 14:43:19
2.1K0
发布2020-06-17 14:43:19
举报
入门pytorch似乎不慢,写好dataloader和model就可以跑起来了,然而把模型搭好用起来时,却往往发觉自己的程序运行效率并不高,GPU使用率宛如舞动的妖精...忽高忽低,影响模型迭代不说,占着显存还浪费人家的计算资源hh 我最近就是遇到这个困难,花了一些精力给模型提速,这里总结一下(有些描述可能并不准确,但至少这些point可以借鉴hh,不妥之处恳请大家指正/补充啦)

dataloader方面:

  1. DataLoader的参数中,
    1. num_workers与batch_size调到合适值,并非越大越快(注意后者也影响模型性能)
    2. eval/test时shuffle=False
    3. 内存够大的情况下,dataloader的pin_memory设为True,并用data_prefetcher技巧(方法)
  2. https://zhuanlan.zhihu.com/p/80695364
  3. 把不怎么会更改的预处理提前做好 保存到硬盘上,不要放dataloader里做,尤其对图像视频的操作
  4. 减少IO操作,服务器如果是hdd根本架不住多人对磁盘的折磨,曾经几个小伙伴把服务器弄得卡到无法login...可先多线程把数据放到内存,不太会的话可以先用个dataloader专门把数据先读到list中(即内存),然后把这个list作为每次取数据的池。还可以用tmpfs把内存当硬盘,不过需要权限
  5. prefetch_generator(方法)让读数据的worker能在运算时预读数据,而默认是数据清空时才读

model方面:

  1. 用float16代替默认的float32运算(方法参考,搜索"fp16"可以看到需要修改之处,包括model、optimizer、backward、learning rate)
  2. 优化器以及对应参数的选择,如learning rate,不过它对性能的影响似乎更重要【占坑】
  3. 少用循环,多用向量化操作
  4. 经典操作尽量用别人优化好的库,别自己写(想自己实现锻炼能力除外)
  5. 数据很多时少用append,虽然使用很方便,不过它每次都会重新分配空间?所以数据很大的话,光一次append就要几秒(测过),可以先分配好整个容器大小,每次用索引去修改内容,这样一步只要0.0x秒
  6. 固定对模型影响不大的部分参数,还能节约显存,可以用detach()切断反向传播,注意若仅仅给变量设置required_grad=False 还是会计算梯度的
  7. eval/test的时候,加上model.eval()和torch.no_grad(),前者固定batch-normalization和dropout 但是会影响性能,后者关闭autograd
  8. 提高程序并行度,例如 我想train时对每个epoch都能test一下以追踪模型性能变化,但是test时间成本太高要一个小时,所以写了个socket,设一个127.0.0.1的端口,每次train完一个epoch就发个UDP过去,那个进程就可以自己test,同时原进程可以继续train下一个epoch(对 这是自己想的诡异方法hhh)

Using CUDA in correct way:

  • 设置torch.backends.cudnn.benchmark = True

使用benchmark以启动CUDNN_FIND自动寻找最快的操作,当计算图不会改变的时候(每次输入形状相同,模型不改变)的情况下可以提高性能,反之则降低性能

  • 另外,还可以采用确定性卷积:(相当于把所有操作的seed=0,以便重现,会变慢)

torch.backends.cudnn.deterministic

添加torch.cuda.get_device_name和torch.cuda.get_device_capability实现如下功能。例:

如果设置torch.backends.cudnn.deterministic = True,则CuDNN卷积使用确定性算法

torch.cuda_get_rng_state_all并torch.cuda_set_rng_state_all引入,让您一次保存/加载随机数生成器的状态在所有GPU上

torch.cuda.emptyCache()释放PyTorch的缓存分配器中的缓存内存块。当与其他进程共享GPU时特别有用。

训练模型个人的基本要求是deterministic/reproducible,或者说是可重复性。也就是说在随机种子固定的情况下,每次训练出来的模型要一样。之前遇到了两次不可重复的情况。第一次是训练CNN的时候,发现每次跑出来小数点后几位会有不一样。epoch越多,误差就越多,虽然结果大致上一样,但是强迫症真的不能忍。后来发现在0.3.0的时候已经修复了这个问题,可以用torch.backends.cudnn.deterministic = True 这样调用的CuDNN的卷积操作就是每次一样的了。

预先分配内存空间:pin_memory + non_blocking async GPU training

为了防止多GPU同时读取内存导致blocking,non_blocking需要对train data设置,否则,0.4.0版本中的DataParallel会自动尝试用async GPU training。

用比Adam更快的优化器

  • SGD with Momentum :该优化器在多项式时间内的收敛性已经明确被证明,更不用说所有的参数都已经像您的老朋友一样熟悉了
  • 【暂时不可用】使用AdamW or Adam with correct weight decay:

因为Adam在优化过程中有一个L2正则化参数,但在当前版本的Pytorch中,L2正则化没有根据学习率进行归一化,AdamW论文中提出的Adam修改方案解决了这一问题并证明收敛更快,而且适用于cosine学习率衰减等。

其他:

  1. torch.backends.cudnn.benchmark设为True,可以让cudnn根据当前训练各项config寻找优化算法,但这本身需要时间,所以input size在训练时会频繁变化的话,建议设为False
  • 使用pytorch时,训练集数据太多达到上千万张,Dataloader加载很慢怎么办?

https://www.zhihu.com/question/356829360

  • MrTian:给训练踩踩油门 —— Pytorch 加速数据读取

https://zhuanlan.zhihu.com/p/80695364

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器学习AI算法工程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Using CUDA in correct way:
  • 预先分配内存空间:pin_memory + non_blocking async GPU training
  • 用比Adam更快的优化器
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档