关于GPU显存占满(即memory usage 很大),但GPU-util很小,导致模型训练很慢

  1. 以下两个参数都可以使用nvidia-smi进行查看
  2. GPU内存占用率:
    1. GPU内存的占用率往往是由模型大小和batchsize决定的,如果发现GPU占用率很小,比如40%,70%等等。如果此时网络结构已经固定,则只需要改变batch size的大小,就可以尽量利用完整个GPU的内存。
    2. 对GPU内存占用率影响最大的还是模型大小,包括网络的宽度,深度,参数量,中间每一层的缓存,都会在内存中开辟空间来进行保存,模型本身会占用很大一部分内存。
    3. 其次是batch size的大小,也会占用影响内存占用率。batch size设置为128,与设置为256相比,内存占用率是接近于2倍关系。当你batch size设置为128,占用率为40%的话,设置为256时,此时模型的占用率约等于80%,偏差不大。所以在模型结构固定的情况下,尽量将batch size设置大,充分利用GPU的内存。
    4. GPU会很快的算完你给进去的数据,主要瓶颈在CPU的数据吞吐量上面。
  3.  GPU 内存利用率(GPU-Util):
    1. 没有设置好CPU的线程数时,这个参数是在反复的跳动的。本质原因:GPU在等待数据从CPU传输过来,当数据从总线传输到GPU之后,GPU逐渐计算起来,利用率会突然升高,但是GPU的算力很强大,0.5秒就基本能处理完数据,所以利用率接下来又会降下去,等待下一个batch的传入。
    2. GPU利用率瓶颈在内存带宽和内存介质上以及CPU的性能上面。
    3. 提供GPU利用率的方式:
      1. pytorch中的Dataloader类设置num_worker(线程数)以及pin_memory,可以提升速度
        1. 首先要将num_workers(线程数)设置合理,4,8,16是几个常选的几个参数。
          1. 测试发现将num_workers设置的非常大,例如,24,32,等,其效率也不一定会变高,因为模型需要将数据平均分配到几个子线程去进行预处理,分发等数据操作,设高了反而影响效率。
          2. 当然,线程数设置为1,是单个CPU来进行数据的预处理和传输给GPU,效率也会低。
        2. pinned memory 是一种加速数据从cpu到gpu传输速度的方式。
      2. 其次,当服务器或者电脑的内存较大,性能较好的时候,可以打开pin_memory,就省掉了将数据从CPU传入到缓存RAM里,再给传输到GPU上;为True,会直接映射到GPU的相关内存块上,省掉了一点数据传输时间。
  4. 调试:
    1. 命令:top 实时查看CPU的进程利用率,这个参数对应你的num_workers的设置;
    2. 命令: watch -n 0.5 nvidia-smi 每0.5秒刷新并显示显卡设置。实时查看你的GPU的使用情况,这是GPU的设置相关。
    3. 这两个配合好。包括batch_size的设置。
    4. 自动实时刷新GPU的使用情况:nvidia-smi -l
  5.  有时cuda版本太老也会导致运行的很慢(后续可以尝试的就是更新cudnn的版本)
  6. 显卡占用和GPU占用是两个不一样的东西,显卡是由GPU和显卡等组成的,显卡和GPU的关系有点类似于内存和CPU的关系,两个指标的占用率不一定是互相对应的。
  7. 查看内存使用情况:free -m

猜你喜欢

转载自blog.csdn.net/weixin_45647721/article/details/128219914