本篇文章是看了各个网站的一个个人理解,请各位大佬批评指正。

一、一个有意思的现象

今天在尝试使用pytorch-GPU跑源码的时候,Pytorch 装成了pytorch-CPU版本,导致训练速度很慢。然后切换到GPU跑的时候,速度是CPU的数倍。

pytorch训练卡住 pytorch训练速度越来越慢_pytorch训练卡住

图中左右是GPU跑的,右边是CPU跑的。

当使用CPU跑的时候,CPU的占用率可以达到300%(我的电脑是4核的)

pytorch训练卡住 pytorch训练速度越来越慢_pytorch训练卡住_02


切换成GPU跑的时候,CPU的占用率在100%上下浮动,GPU的占用率在20%-40%浮动。

pytorch训练卡住 pytorch训练速度越来越慢_pytorch训练卡住_03


pytorch训练卡住 pytorch训练速度越来越慢_pytorch_04

我不满足于GPU占用率,尝试去提升他。结果使用提升不上去。

二、提升训练速度的方法(从硬件层面)

原文如下,在此写下个人理解。


  • GPU内存占用率低:提升batch_size
  • GPU利用率低:提升CPU数据传输效率
  • CPU利用率低:提升线程数量

三、 出现上述现象原因总结

此处只是个人理解,请大佬给出指正。

深度学习中有以下两个参数:num_workers和batch_size。num_workers是指在加载数据的时候使用几个线程数去加载,batch_size是指在一个epoch中,将数据分成若干个batch_size大小的batch。

在只是用CPU训练时,CPU的一个内核首先通过num_workers个线程将数据分成若干个batch。然后将每个batch送入另外几个内核进行处理。Pytorch可以多线程操作,所以在仅用CPU训练时他的利用率可以达到300%。(如果你有更多的内核或者CPU可以达到更大的利用率)

在使用GPU训练时,CPU的一个内核首先通过num_workers个线程将数据分成若干个batch。然后CPU将batch送入GPU中进行运算。因此CPU的利用率在100%左右。而GPU的算力远远大于CPU,这样就导致CPU传送的数据不需要GPU火力全开就可以处理了。所以GPU的利用率在20-40%左右。(上下浮动的原因:因为batch_size在一个epoch中分到最后可能是小于batch_size的,最后一个batch_size数据量小了,自然利用率就下来了)此时,想提升GPU的利用率只能提高CPU的性能调用多核去处理数据提高num_workers提高batch_size

四、解决思路

1、提高CPU性能

按道理来说CPU性能是固定了,但是有一种可能是你的磁盘IO数据的速度跟不上CPU的处理速度。
这时就要监控IO数据

sudo apt-get install sysstat
sudo iostat

2、提高num_workers

增加子线程个数提高CPU的处理能力,从而将数据更快地传给GPU

实际上在博客中,作者提到并不是越大的num_workers处理就越快,应该找到合适的num_workers。因为如果你把一个问题分给过多线程,有大量的时间就会浪费在线程传输中。

3、提高batch_size

每次CPU多传点数据给GPU,让GPU忙起来

实际上在博客中,作者提到并不是越大的batch_size处理就越快,应该找到合适的batch_size。因为CPU的计算能力不如GPU,如果过大CPU也要花费更多的时间去处理数据。

4、调用多核去处理

在pytorch中,可以通过以下代码制定CPU运行个数。我在寻找到最合适的batch_size和num_workers后想尝试多核调用处理,但是发现失败了。

import os
cpu_num = 3 # 这里设置成你想运行的CPU个数
os.environ ['OMP_NUM_THREADS'] = str(cpu_num)
os.environ ['OPENBLAS_NUM_THREADS'] = str(cpu_num)
os.environ ['MKL_NUM_THREADS'] = str(cpu_num)
os.environ ['VECLIB_MAXIMUM_THREADS'] = str(cpu_num)
os.environ ['NUMEXPR_NUM_THREADS'] = str(cpu_num)
torch.set_num_threads(cpu_num)

pytorch训练卡住 pytorch训练速度越来越慢_pytorch_05

虽然确实调用了多个内核,但是他们的总利用率是不变的。所以也没有办法提升。(是不是因为pytorch切分数据只能单线程?)

五、总结

从硬件层面考虑加速Pytorch-GPU的深度学习,分为以下几个步骤

  • 查看GPU的利用率和内存占用率。如果已经拉满了,那就以为止只能这样了。考虑修改一下模型。
  • 如果GPU的利用率和内存占用率都不高,查看CPU利用率。如果CPU也拉满运行了,考虑以下几个方法:提高CPU的性能调用多核去处理数据提高num_workers提高batch_size
  • 如果CPU的利用率和内存占用率都不高,查看IO的利用率。如果拉满的话可能是硬件有点拉胯。