在命令行看nvidia-smi:GPU利用率和显存占用没有直接关系! GPU利用率类似cpu利用率,表示gpu核在进行计算操作,而显存类似于仓库,用于存放计算过程中的数据,每一个Float32数会占用4字节的显存,也就是4B的显存。
1、神经网络训练时占用显存计算:
①、模型参数占用的显存->参数数量×4B(Float32),无论训练的batchsize是多少,参数量占用的显存都是一个模型的参数量占用的显存(在一个GPU上)
②、模型输入、输出以及中间变量占用的显存,会随着batchsize的增加而增加。
③、优化器的参数->梯度与动量占用的显存:梯度占用的显存=参数占用的显存=动量占用的显存;SGD优化器(需要保存梯度)Momentum-SGD优化器(梯度+动量);Adam优化器(梯度+一阶动量+二阶动量),这里无论batchsize为多少,都是一个模型的参数量,也就是如果Adam优化器,则梯度和参数占用的显存恒定为参数显存*4。
④、模型框架自身的显存开销,很小,几百兆。
2、 神经网络推理时占用的显存
少了梯度、优化器状态、中间激活,模型推理阶段的显存占用大头是模型参数!
①、模型参数占用的显存
②、输入、输出以及中间变量占用的显存
3、减少显存占用的方式
占用显存的模块:卷积、全连接linear,BN;不占用显存的模块:激活函数、池化层、dropout。
比如 ReLU,在 PyTorch 中,使用 nn.ReLU(inplace = True) 能 将激活函数 ReLU 的输出直接覆盖保存于模型的输入之中,节省不少显存,尽量使用 Inplace:在 PyTorch 中,inplce 操作指的是改变一个 tensor 值的时候,不经过复制操作而是直接在原来的内 存上修改它的值,也就是原地操作
尽量少产生中间结果: 不需要的中间变量尽可能的都是用一个变量来代替,因为这些变量都是会占用显存的
不要使用过大的全连接: 相比于卷积的参数,全连接的参数量大很多。因为卷积只是一个局部的连接,而全连接则是一个全局的连接!