前言亲爱的,显存炸了,你的显卡要冒烟了!torch.FatalError:cudaruntimeerror(2):outofmemoryat/opt/conda/conda-bld/pytorch_1524590031827/work/aten/src/THC/generic/THCStorage.cu:58这一定是所有炼金术士最不想看到的错误,没有他们中的。OUTOFMEMORY,很明显显存放不下你的模型权重和中间变量,然后程序就崩溃了。怎么办,其实有很多方法,比如及时清除中间变量,优化代码,减少批次等等,都可以降低显存溢出的风险。但是这篇文章讲的是上面所有优化操作的基础,如何计算我们使用的显存。了解如何计算我们设计的模型和中间变量占用的显存大小。想必知道这一点,我们自己的显存就会得心应手了。如何计算首先要了解基本的数据量信息:1G=1000MB1M=1000KB1K=1000Byte1B=8bit好吧,肯定有人会问为什么是1000而不是1024,不过这里也不过多讨论,只能说两种说法都对,只是应用场景略有不同。这里统一按照上述标准进行计算。然后说一下我们平时用到的vector占用的空间,以Pytorch官方的数据格式为例(所有深度学习框架的数据格式都遵循相同的标准):我们只需要看左边的信息,在平时training其中,我们经常用到这两种类型:float32单精度浮点型int32整数型一般8位整型变量占用1B的空间,也就是8bit。32位的float占用4B,也就是32bit。双精度浮点double和长整型long在正常训练中一般不用。ps:消费级显卡针对单精度计算进行了优化,服务器级显卡针对双精度计算进行了优化。也就是说,假设有一张RGB三通道真彩图片,长宽为500×500,数据类型为单精度浮点数,那么这张图片占用的显存大小为:500x500x3x4B=3M。而一个(256,3,100,100)-(N,C,H,W)FloatTensor占用空间为256x3x100x100x4B=31M,不多,没关系,好??玩的才刚刚开始。显存在哪里?看起来一张图片(3x256x256)和卷积层(256x100x100)占用的空间并不大,那为什么还要多用显存呢?原因很简单。它不是我们的输入图像,而是神经网络中的中间变量和使用优化器算法时产生的大量中间参数。我们先简单计算一下Vgg16网络需要占用的显存:通常一个模型占用的显存是两部分:模型自身的参数(params)和模型从cs231n计算产生的中间变量(内存)图片,这是一个典型的顺序网络,从上到下非常平滑。可以看到我们输入的是一张224x224x3的三通道图像。我们可以看到一张图片只占了150x4k,但是上面的部分是150k。这是因为它是在这里计算的。默认的数据格式是8位的,而不是32位的,所以最后的结果要乘以4。我们可以看到左边的内存值代表的是图像输入所占用的空间,图像和得到的中间体卷积层。我们都知道,这些形形色色的深度卷积层是深度神经网络“思考”的过程:图片从3通道变为64-->128-->256-->512....这些都是体积堆叠的图层,我们的显存主要被它们占用。右上方还有params,这些是神经网络的权重,可以看到第一层卷积是3x3,输入图像的通道是3,输出通道是64,所以很明显,第一个卷积层的权值所占用的空间是(3x3x3)x64。另外需要注意的是中间变量在向后时会翻倍!比如下面是一个计算图,输入x,走一遍中间结果z,然后得到最终的变量L:我们落后的时候需要保存的中间值。输出为L,然后输入x,我们要求在backward时L对x的梯度。这时候我们需要z在计算链L和x的中间:dz/dx的中间值必须预留用于计算,所以粗略估计中间变量在backward时占用是forward的两倍!注意优化器和动量,优化器也会占用我们的显存!为什么,看这个公式:上面的公式就是典型的SGD随机下降法的整体公式。更新权重W时,会生成并保存中间变量,即优化时,模型中params参数占用的显存数量会翻倍。当然,这只是SGD优化器。其他复杂的优化器如果在计算过程中需要更多的中间变量,就会占用更多的内存。模型中的哪些层会占用显存?带参数的图层会占用显存。我们一般的卷积层都会占用显存,而我们经常使用的激活层Relu没有参数是不会占用的。占用显存的层一般有:卷积层,通常的conv2d全连接层,也就是Linear层,BatchNorm层,不占用显存的Embedding层:激活层Relu等pooling的具体计算方式layers刚刚提到的Dropout层:Conv2d(Cin,Cout,K):Numberofparameters:Cin×Cout×K×KLinear(M->N):Numberofparameters:M×NBatchNorm(N):Numberofparameters:2NEmbedding(N,W):参数个数:N×W额外显存总结一下,在我们整体训练中,占用的显存大致可以分为以下几类:模型中的参数(卷积层或者其他层)withparameters)模型在计算时产生的中间参数(即计算输入图像时各层产生的输入和输出)backwardoptimizer产生的额外中间参数o产生的额外模型参数ptimizerduringoptimization但实际上,为什么我们占用的显存空间和我们理论计算的相比呢?原因很可能是因为深度学习框架的一些额外开销,但如果使用上面的公式,理论上计算出的显存与实际相差不大。如何优化优化除了算法层的优化,最基本的优化无外乎几点:就地取笑我,如果你和我有相同的目标,老潘愿意和你交流;如果喜欢老潘的内容,欢迎关注和支持。如果你喜欢我的文章,希望点赞:+1:收藏:file_folder:评论:speech_balloon:三次~
