【深度学习】为什么深度学习需要大内存?

news/2025/2/5 20:44:44/

本文主要译介自Graphcore在2017年1月的这篇博客: Why is so much memory needed for deep neural networks。介绍了深度学习中内存的开销,以及降低内存需求的几种解决方案。

为便于阅读,本文修改了原文分段,并添加更详细的计算说明。

深度学习的内存消耗在哪里?

回顾:简单例子

考虑一个单层线性网络,附带一个激活函数:
h = w 1 x + w 2 h=w_1x+w_2 h=w1x+w2

y = f ( h ) y=f(h) y=f(h)

代价函数: E = ∣ ∣ y − y ‾ ∣ ∣ 2 E=||y-\overline{y}||^2 E=yy2

在训练时,每一个迭代要记录以下数据:

  • 当前模型参数 w 1 , w 2 w_1,w_2 w1,w2
  • 前向运算各层响应: x , h , y x, h, y x,h,y

这样,可以在后向运算中用梯度下降更新参数:
Δ w 1 = η ⋅ ∂ E ∂ w 1 = η ⋅ 2 ( y − y ‾ ) ⋅ f ′ ( h ) ⋅ x \Delta w_1=\eta\cdot \frac{\partial E}{\partial w_1}=\eta \cdot 2(y-\overline{y})\cdot f'(h) \cdot x Δw1=ηw1E=η2(yy)f(h)x

Δ w 2 = η ⋅ ∂ E ∂ w 1 = η ⋅ 2 ( y − y ‾ ) ⋅ f ′ ( h ) \Delta w_2=\eta\cdot \frac{\partial E}{\partial w_1}=\eta \cdot 2(y-\overline{y})\cdot f'(h) Δw2=ηw1E=η2(yy)f(h)

内存消耗的三方面

输入数据

很小,不做考量。

256256的彩色图像:25625631 byte= 192KB

模型参数

较大,和模型复杂度有关。

入门级的MNIST识别网络有6.6 million参数,使用32-bit浮点精度,占内存:6.6M * 32 bit = 25MB

50层的ResNet有26 million参数,占内存:26M * 32 bit = 99MB

当然,你可以设计精简的网络来处理很复杂的问题。

各层响应

较大,同样和模型复杂度有关。

50层的ResNet有16 million响应,占内存:16M*32bit = 64MB

响应和模型参数的数量并没有直接关系。卷积层可以有很大尺寸的响应,但只有很少的参数;激活层甚至可以没有参数。

– 这样看起来也不大啊?几百兆而已。
– 往下看。

batch的影响

为了有效利用GPU的SIMD机制,要把数据以mini-batch的形式输入网络。
如果要用32 bit的浮点数填满常见的1024 bit通路,需要32个样本同时计算。

在使用mini-batch时,模型参数依然只保存一份,但各层响应需要按mini-batch大小翻倍。

50层的ResNet,mini-batch=32,各层相应占内存:64MB*32 = 2GB

卷积计算的影响

H × W H\times W H×W的输入图像为 X X X K × K K\times K K×K的卷积核为 R R R,符合我们直觉的卷积是这样计算的。

对每一个输出位置,计算小块对位乘法结果之和。
Y ( h , w ) = ∑ X k , k s ( h , w ) ⊙ R Y(h,w) = \sum{X^s_{k,k}(h,w) \odot R} Y(h,w)=Xk,ks(h,w)R

h = 1 : H , w = 1 : W h=1:H, w=1:W h=1:H,w=1:W
其中, X k , k s ( h , w ) X^s_{k,k}(h,w) Xk,ks(h,w)表示输入图像中,以 h , w h,w h,w为中心,尺寸为 K × K K\times K K×K的子图像。

但是,这种零碎运算很慢

在深度学习库中,一般会采用lowering的方式,把卷积计算转换成矩阵乘法

首先,把输入图像分别平移不同距离,得到 K 2 K^2 K2 H × W H\times W H×W的位移图像,串接成 H × W × K 2 H\times W \times K^2 H×W×K2的矩阵 X ‾ \overline{X} X
之后,把 K × K K\times K K×K的卷积核按照同样顺序拉伸成 K 2 × 1 K^2\times 1 K2×1的矩阵 R ‾ \overline{R} R
卷积结果通过一次矩阵乘法获得:
Y = X ‾ ⋅ R ‾ Y=\overline{X}\cdot \overline{R} Y=XR

输入输出为多通道时,方法类似,详情参见这篇博客。

在计算此类卷积时,前层响应 X X X需要扩大 K 2 K^2 K2倍。

50层的ResNet,考虑lowering效应时,各层响应占内存7.5GB

使用低精度不能降内存

为了有效利用SIMD,如果精度降低一倍,batch大小要扩大一倍。不能降低内存消耗。

降内存的有效方法

in-place运算

不开辟新内存,直接重写原有响应。
很多激活函数都可以这样操作。
复杂一些,通过分析整个网络图,可以找出只需要用一次的响应,它可以和后续响应共享内存。例如MxNet的memory sharing机制。

综合运用这种方法,MIT在2016年的这篇论文能够把内存降低两到三倍。

计算换存储

找出那些容易计算的响应结果(例如激活函数层的输出)不与存储,在需要使用的时候临时计算。

使用这种方法,MxNet的这个例子能够把50层的ResNet网络占用的内存减小四倍。

类似地,DeepMind在2016年的这篇论文用RNN处理长度为1000的序列,内存占用降低20倍,计算量增加30%。

百度语音在2016年的这篇论文同样针对RNN,内存占用降低16倍,可以训练100层网络。

当然,还有Graphcore自家的IPU,也通过存储和计算的平衡来节约资源。

Graphcore本身是一家机器学习芯片初创公司,行文中难免夹带私货,请明辨。


http://www.ppmy.cn/news/227229.html

相关文章

Linux 中的“大内存页”(hugepage)是个什么?

学习 Linux 中的大内存页hugepage。理解什么是“大内存页”,如何进行配置,如何查看当前状态以及如何禁用它。 本文中我们会详细介绍大内存页huge page,让你能够回答:Linux 中的“大内存页”是什么?在 RHEL6、RHEL7、Ub…

小cache与大内存的映射详细解析

更多精彩内容,或者需要更详细的资料,欢迎关注微信公众号:云计算coding之美,留言,感谢。 众所周知,电脑的设计与制造可以说是信息时代,整个人类智慧的集大成者,包括众多技术&#xff…

让大内存不再“空虚”

现在的内存价格可谓平易近人,越来越多的用户为自己的电脑配置了大容量内存。安装1GB甚至几个GB内存已经变得很普通,大容量内存可以让Windows运行得更加流畅。但是,大的内存并非全部利用,其中有很大一部分处于闲置状态。而且&#…

linux大内存页 HugePages on Linux

HugePages on Linux HugePages是linux内核的一个特性,使用hugepage可以用更大的内存页来取代传统的4K页面。使用HugePage主要带来如下好处 1,没有swap。Notswappable: HugePages are not swappable. Therefore there is no page-in/page-outmechanism ov…

大内存页的设置方式

1.大页的作用 简单地说,linux的内存页大小是4K,大内存页是2M,当内存使用较高,那么,cpu在对内存寻址的时候会寻多次地址找到所有的内存页,如果使用大内存页就会减少这种寻址次数,比如在理想情况下…

Python 优雅的读取大内存文件

背景: 使用 python 读取一个相对较大内存的文件,比如电脑运行内存只有1G,但是读取的文件大小为 2G,这个时候怎么处理呢?有人说直接用 open函数不就好了吗?但是如果你直接使用的话,会把文件一次…

Windows 10大内存优化(关闭内存压缩功能)

为爱机扩展了内存,系统确实流畅了许多;但发现怎么也用不完,是不是有点浪费?而且CPU使用率居高不下,为什么? 查阅了资料,终于找到了结果:Windows 10新增了内存压缩功能,对…

大型计算机 内存,【技术贴】16GB超大内存该怎么玩儿?大内存应用方案解析

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 首先把Grub4dos解压到C盘并将文件夹改名为“grub”,然后将“grub”文件夹中的grldr和grldr.mbr两个文件复制到C盘 根目录,接着在“命令提示符”界面中输入“bcdedit /create /d \"Grub\" /application bootsector”后…