项目场景:

利用Pytorch在PTB数据集上训练的词嵌入模型的实现。


问题描述:

在训练过程中,发现训练速度很慢,利用GPU-Z查看后,发现GPU利用率基本为0。

pytorch 网络参数量 pytorch网络训练太慢_pytorch 网络参数量

pytorch 网络参数量 pytorch网络训练太慢_深度学习_02


原因分析:

为了找到耗时大的程序段,在训练代码中加入输出耗时的语句。

for batch in data_iter:
            print("end:, time ", time.time() - start)
            center, context_negative, mask, label = [d.to(device) for d in batch]
            pred = skip_gram(center, context_negative, net[0], net[1])
            l = loss(pred.view(label.shape), label, mask).mean()  # 一个batch的平均loss
            optimizer.zero_grad()
            l.backward()
            optimizer.step()
            sum_loss += l.cpu().item()
            print("sta:, time ", time.time() - start)

pytorch 网络参数量 pytorch网络训练太慢_pytorch 网络参数量_03


发现训练耗时很短,主要的时间花费都在读取数据的环节,每次都要花费1.5s左右。

for batch in data_iter:

而读取数据是由CPU完成的,训练过程的处理数据是由GPU完成了,也就是说程序运行时间长是由于CPU性能不足导致的,GPU每次处理数据都很快,只需要很短的时间就可以处理完数据,而后一直处于等待时间,因此利用率才会为0。同样利用GPU-Z查看平均利用率:

pytorch 网络参数量 pytorch网络训练太慢_深度学习_04


发现实际上是有使用GPU的,只是平均利用率非常低。为了进一步验证问题,同样也是为了查看GPU的处理能力,将batca size加大一个数量级,从512改为4096,进行观察。

pytorch 网络参数量 pytorch网络训练太慢_读取数据_05


发现CPU读取数据所用时间增长了66倍,而GPU处理数据所用时间基本不变。

因此可以确定,训练速度慢的原因,是遇到CPU瓶颈了。也就是CPU加载速度慢,使GPU空转、利用率低。


解决方案:

参考中提出的两种方法。

1、从单线程改为多线程。也就是将num_workers(线程数)改为4、8、16等,提高加载数据的速度。但windows系统有个贼sb的bug,好像已经有几年了,num_workers必须为0,不然就会出现错误如下:

pytorch 网络参数量 pytorch网络训练太慢_读取数据_06


因此该方法在win上暂时不可用。2、pin_memory=True。当你的服务器或者电脑的内存较大,性能较好的时候,建议打开pin_memory打开,就省掉了将数据从CPU传入到缓存RAM里面,再给传输到GPU上;为True时是直接映射到GPU的相关内存块上,省掉了一点数据传输时间。

pytorch 网络参数量 pytorch网络训练太慢_数据_07


也许是因为我的电脑性能不足,速度不仅没有变快,反而变慢了,只好放弃该方法。

3、此外,在一些其他的文章上看到,可以对数据的加载代码做一些优化,但还没有尝试过,不知道效果如何。

结论:无能为力,还是准备用服务器跑吧。