深度学习模型训练中关于GPU使用的3个bug:

530 阅读4分钟

概述

本文主要记述本人作为初学者在训练深度学习模型过程中常见的一些BUG,以及自己对于这些BUG的解决思路和最后的解决办法,应当算是干货吧!希望对各位新晋“炼丹师”有一些帮助吧!

遇到的问题及解决思路与方法

1. 使用Tensorflow框架读取数据时,出现显卡全占用的问题;

这一个bug在使用Tensorflow框架读取数据时,会经常出现。如下图所示,

image.png

我在使用 ds = tf.data.TFRecordDataset(files, num_parallel_reads=5, )读取files中的原始数据时,会直接占用所有的6张显卡。可能就会有人说了,显卡虽然不少,也不能这么造吧。

于是,我查询了一下有关资料。发现,Tensorflow这个框架(如果装的是GPU版本),在使用tf.data读取数据时会自动查询当前os能够找到的所有的gpu设备,并且将所有设备占用,方便直接在多显卡上训练模型。

所以,这就需要在主体代码段前加上一句os.environ["CUDA_VISIBLE_DEVICES"] = "-1" 以限制gpu设备使用。

在训练模型时,我们通常会是CPU读数据然后将数据送入GPU上训练。 所以,读数据模块和训练模块通常会分离,一般来说,我们会在train模块前使用os.environ["CUDA_VISIBLE_DEVICES"] = "0" 来指定可用GPU(当前为第一块CPU),这点对大家来说肯定是没问题的。但os.environ["CUDA_VISIBLE_DEVICES"] = "0" 通常会写在模块引入之后。这就意味着我们在数据读取模块时设置的os.environ["CUDA_VISIBLE_DEVICES"] = "-1" 会被train模块中的os.environ["CUDA_VISIBLE_DEVICES"] = "0" 覆盖掉,以至于数据直接被读到指定的GPU上了。 所以,这是,我们最好在 ds = tf.data.TFRecordDataset(files, num_parallel_reads=5, )前使用with tf.device("cpu:/0")直接定死数据读取是在CPU上进行的。

2. 在使用os.environ['CUDA_VISIBLE_DEVICES"]限制CUDA设备时出现BUG;

因为我的模型训练部分是基于Pytorch框架编写的,所以,我会自然而然地使用device = torch.device("cuda:n")来指定我所使用的GPU。作为初学者来说,我会毫无疑问地把nos.environ["CUDA_VISIBLE_DEVICES"] = "n" 直接挂上等号,结果报如下bug:

"RuntimeError: CUDA error: invalid device ordinal
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
Compile with `TORCH_USE_CUDA_DSA` to enable device-side assertions."

这个bug折磨了我很久,最后,我甚至上StackOverflow上提了一个issue:python - A special issue: RuntimeError: CUDA error: invalid device ordinal - Stack Overflow

结果,后面又仔细看了一下Pytorch的文档与os.environ['CUDA_VISIBLE_DEVICES"]之间的一个关系,发现:在使用os.environ['CUDA_VISIBLE_DEVICES"]指定特定的GPU时,此时torch.device()的默认逻辑寻址路径会从os.environ['CUDA_VISIBLE_DEVICES"]= '1,2,3'中开始查找,这意味着我此时能调用的第0号显卡torch.device("cuda:0")实际上是实际上的第1号显卡,即会寻址到物理上的第二张显卡显存的地址,后面的可以此类推。

所以,大家一定要注意好device = torch.device("cuda:n")os.environ["CUDA_VISIBLE_DE VICES"] = "n" 之间的对应关系。

3. GPU利用率低的问题;

引发这个问题的来源有多种,一般来说,可以分为以下几种:

  1. 没有设置Pytorchnum_worker或者是Tensorflowprefetch。这个问题主要是CPU吞吐GPU吞吐速度不协调的问题,通常来说,就是GPU训练模型的速度很快,但CPU读取数据送给GPU的速度达不到GPU的期望值所引起的。 解决的办法其实很简单,在读取数据时,一次性让CPU多读几次数据,把数据送到缓冲区,GPU需要的时候直接取就行。PyTorch使用

train_data = data.DataLoader(train_dataset, num_workers=4)即可, 而Tensorflow

在使用ds = tf.data.TFRecordDataset(files, num_parallel_reads=5, )后使用

ds = ds.prefetch(buffer_size=1024)进行设置即可。

  1. 第二点原因可能是CPU在读取数据后又进行数据预处理,也就是说,送入模型的数据是你实时预处理出来。如果处理的时间很长的话,就很可能会导致GPU利用率为几个点,十几个点的情况。这种情况,就需要你先将数据完全处理过后,得到最终输入模型的数据形式才行。
  2. 第3点原因可能就是显卡本身的原因了,不过这情况一般很少会出现!

总结

以上就是我目前阶段在“炼丹”过程中遇到的一些bug的总结,希望对你们有用。如果有用的话,还望不吝点赞收藏,谢谢!