- 哪些会占用GPU显存 - 占用:卷积层,全连接层,batchNorm层,Embedding层 - 不占用:relu激活层,池化层 - 上面这些指的是对应层的参数会占用显存 - 额外的显存占用:模型在计算时产生的中间参数(也就是输入图像在计算时每一层产生的输入和输出) - 需要计算每一层的feature map的形状
- 需要保存输出对应的梯度用以反向传播
- 显存占用与batch_size近似成正比
 - backward的时候产生的额外的中间参数 - 优化器在优化时产生的额外的模型参数,不同优化算法需要占用不同大小的内存 - https://zhuanlan.zhihu.com/p/31558973 - 1 - 显存占用 = 模型显存占用 + batch_size × 每个样本的显存占用 
- 如何优化显存占用 - 减少图像的输入尺寸 - 减少batch_size - 多使用下采样,池化层 
- feature map是需要保存的,也就是我们上面说的额外的显存占用:模型在计算时产生的中间参数(也就是输入图像在计算时每一层产生的输入和输出)。特征图是一个层在前向传播中生成的中间输出结果,且在后向传输的梯度计算中作为输入。 - https://zhuanlan.zhihu.com/p/31863033 - 特征图的大小通常由批尺寸(batchsize)和模型架构决定(如CNN架构的卷积步幅大小、输出通道数量;RNN架构的门数量、时间步长和隐层大小)。不再需要作为输入的特征图占用的显存将会被释放,导致图1中显存占用曲线的下降。 - 这些数据使用的内存主要和两个参数有关系, 一是batch size,另一个是每条序列(Sequence)长度。所以,其实也是和每个mini-batch中包含 的时间步信息成正比。 - 减小batch size。 即在网络配置中 settings(batch_size=1000)设置成一个小一些的值。但是batch size本身是神经网络的超参数,减小batch size可能会对训练结果产生影响。
- 减小序列的长度,或者直接扔掉非常长的序列。比如,一个数据集大部分序列长度是100-200, 但是突然有一个10000长的序列,就很容易导致内存超限,特别是在LSTM等RNN中。因为RNN中存在沿着时间反向传播的操作,所以我们需要记录每个时间步的feature map
 /gpu占用曲线.jpg) - 对于权重参数而言,权重参数占用内存相对较少。权重一般作为GPU内存中的持久内存,只有训练任务完成后才会被释放。特征图才是GPU显存占用的主要因素。 
- 减小batch size。 即在网络配置中 
- 变量共享 - https://blog.csdn.net/wwwwenming2007/article/details/70821467 - 1 - 可以通过tf.get_variable_scope().reuse函数来获取上下文管理器中reuse参数的值 - https://www.cnblogs.com/weizhen/p/6751792.html - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- #通过tf.variable_scope和tf.get_variable函数,以下代码对inference函数的前向传播结果做了一些改进 
 def inference(input_tensor,reuse=False):
 #定义第一层神经网络的变量和前向传播过程
 with tf.variable_scope('layer1',reuse=reuse):
 #根据传进来的reuse来判断是创建新变量还是使用已经创建好了。在第一次构造网络时需要创建新的变量,
 #以后每次调用这个函数都直接使用reuse=True就不需要每次将变量传进来了
 weights= tf.get_variable("weights",[INPUT_NODE,LAYER1_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1))
 biases= tf.get_variable("biases",[LAYER1_NODE],initializer=tf.constant_initializer(0.0))
 layer1 = tf.nn.relu(tf.matmul(input_tensor,weights)+biases)
 
 #类似地定义第二层神经网络的变量和前向传播过程
 with tf.variable_scope('layer2',reuse=reuse):
 weights=tf.get_variable("weights",[LAYER1_NODE,OUTPUT_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1))
 biases=tf.get_variable("biases",[OUTPUT_NODE],initializer=tf.constant_initializer(0.0))
 layer2=tf.matmul(layer1,weights)+biases
 #返回最后的前向传播结果
 return layer2
 x=tf.placeholder(tf.float32,[None,INPUT_NODE],name='x-input')
 y=inference(x)
 #在程序中需要使用训练好的神经网络进行推倒时,可以直接调用inference(new_x,True)-