用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理

深度学习是门玄学?也不完全是。

每个人都想让模型训练得更快,但是你真的找对法子了吗?在康奈尔大学本科生、曾在 PyTorch 团队实习的 Horace He 看来,这个问题应该分几步解决:首先,你要知道为什么你的训练会慢,也就是说瓶颈在哪儿,其次才是寻找对应的解决办法。在没有了解基本原理(第一性原理)之前就胡乱尝试是一种浪费光阴的行为。在这篇文章中,Horace He 从三个角度分析可能存在的瓶颈:算计、内存带宽和额定开支,并提供了一些方式去判断当前处于哪一个瓶颈,有助于我们更加有针对性地加速系统。这篇文章得到了陈天奇等多位资深研究者、开发者的赞赏。以下是原文内容:怎样才能提高深度学习模型的性能?一般人都会选择网上博客中总结的一些随机技巧,比如「使用系统内置的运算算子,把梯度设置为 0,使用 PyTorch1.10.0 版本而不是 1.10.1 版本……」在这一领域,当代(特别是深度学习)系统给人的感觉不像是科学,反而更像炼丹,因此不难理解用户为什么倾向于采用这种随机的法子。即便如此,这一领域也有些第一性原理可以遵循,我们可以据此排除大量法子,从而使得问题更加容易解决。比如,如果你的训练损失远低于测试损失,那么你可能遇到了「过拟合」问题,而尝试着增加模型容量就是在浪费光阴。再比如,如果你的训练损失和你的验证损失是一致的,那对模型正则化就显得不明智了。类似地,你也可以把高效深度学习的问题划分为以下三个不同的组成部分:

算计:GPU 算计实际浮点运算(FLOPS)所破费的光阴;

内存:在 GPU 内传输张量所破费的光阴;

额定开支:花在其它部分的光阴。

在训练机器学习模型的时候,知道你遇到的是哪类问题非常关键,使模型高效的问题也是如此。例如,当模型破费大量光阴进行内存到 GPU 的转移的时候(也就是内存带宽紧张的时候),增加 GPU 的 FLOPS 就不管用。另一方面,如果你正在运转大量的矩阵乘法运算(也就是算计紧张的时候),将你的程序重写成 C++ 去减轻额定开支就不会管用。所以,如果你想让 GPU 丝滑运转,以上三个方面的讨论和研究就是必不可少的。

用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理

惨痛教训的背后有大量工程师保持 GPU 高效运转。注意:这个博客中的大多数内容是基于 GPU 和 PyTorch 举例子的,但这些原则基本是跨硬件和跨框架通用的。

算计

优化深度学习系统的一个方面在于我们想要最大化用于算计的光阴。你花钱买了 312 万亿次浮点数运算,那你肯定希望这些都能用到算计上。但是,为了让你的钱从你昂贵的矩阵乘法中得到回报,你需求减少破费在其他部分的光阴。但为什么这里的重点是最大化算计,而不是最大化内存的带宽?原因很单一 —— 你可以减少额定开支或者内存消耗,但如果不去改变真正的运算,你几乎无法减少算计量。与内存带宽相比,算计的增长速度增加了最大化算计利用率的难度。下表显示了 CPU 的 FLOPS 翻倍和内存带宽翻倍的光阴 (重点关注黄色一栏)。用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理一种理解算计的方式是把它想象成工场。我们把指令传达给我们的工场(额定消耗),把原始材料送给它(内存带宽),所有这些都是为了让工场运转得更加高效(算计)。用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理所以,如果工场容量扩展的速度高于我们提供给它原材料的速度,它就很难达到一个顶峰效率。

用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理

即使我们工场容量(FLOP)翻倍,但带宽跟不上,我们的性能也不能翻倍。

关于 FLOPS 还有一点要说,越来越多的机器学习加速器都有专门针对矩阵乘法的硬件配置,例如英伟达的「Tensor Cores」。用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理所以,你要是不做矩阵乘法的话,你只能达到 19.5 万亿次运算,而不是 312 万亿次。注意,并不是只有 GPU 这么特殊,事实上 TPU 是比 GPU 更加专门化的算计模块。除了矩阵乘法以外,GPU 处理其他运算时都比较慢,这一现象乍看上去似乎有问题:比如像是层归一化或者激活函数的其它算子怎么办呢?事实上,这些算子在 FLOPS 上仅仅像是矩阵乘法的舍入误差一样。例如,看看下表对于 BERT 中的不同算子类型占用的 FLOP 数,其中的「Tensor Contraction」就是指矩阵乘法。用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理可以看到,非矩阵乘法运算仅仅占所有运算的 0.2%,所以即使它们的速度仅为矩阵乘法的 1/15 也没什么问题。事实上,归一化运算和逐点(pointwise)运算使用的 FLOPS 仅为矩阵乘法的 1/250 和 1/700。那为什么非矩阵乘法运算会远比它们应该使用的运转光阴更多呢?回到前文「工场」的类比,罪魁祸首经常还是如何将原始材料运到以及运出工场,换句话说,也就是「内存带宽」。

带宽

带宽消耗本质上是把数据从一个地方运送到另一个地方的破费,这可能是指把数据从 CPU 移动到 GPU,从一个节点移动到另一个节点,甚至从 CUDA 的全部内存移动到 CUDA 的共享内存。最后一个是本文讨论的重点,我们一般称其为「带宽消耗」或者「内存带宽消耗」。前两者一般叫「数据运输消耗」或者「网络消耗」,不在本文叙述范围之内。还是回到「工场」的类比。虽然我们在工场中从事实际的工作,但它并不适合大规模的存储。我们要保证它的存储是足够高效的,并且能够很快去使用(SRAM),而不是以量取胜。那么我们在哪里存储实际的结果和「原材料」呢?一般我们要有一个仓库,那儿的地足够便宜,并且有大量的空间(DRAM)。之后我们就可以在它和工场之间运送东西了(内存带宽)。用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理这种在算计单元之间移动东西的成本就是所谓的「内存带宽」成本。事实上,nvidia-smi 命令中出现的那个「内存」就是 DRAM,而经常让人抓狂的「CUDA out of memory」说的就是这个 DRAM。值得注意的是:我们每施行一次 GPU 核运算都需求把数据运出和运回到我们的仓库 ——DRAM。现在想象一下,当我们施行一个一元运算(如 torch.cos)的时候,我们需求把数据从仓库(DRAM)运送到工场(SRAM),然后在工场中施行一小步算计,之后再把结果运送回仓库。运输是相当耗时的,这种情况下,我们几乎把所有的光阴都花在了运输数据,而不是真正的算计上。因为我们正把所有的光阴都破费在内存带宽上,这种运算也被称作内存限定运算(memory-bound operation),它意味着我们没有把大量光阴破费在算计上。显然,这并不是我们想要的。那我们能做什么呢?让我们来看看算子序列长什么样子。

用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理

一个逐点算子序列可能的样子。

在全部内存和算计单元之间来回传输数据的做法显然不是最佳的。一种更优的方式是:在数据工场中一次性施行完全部运算再把数据传回。用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理这就是算子融会(operator fusion)—— 深度学习编译器中最重要的优化。单一地说,这种法子不会为了再次读取而将数据写入全部内存,而是通过一次施行多个算计来避免额定的内存访问。例如,施行 x.cos ().cos () 运算,写入内存的方式需求 4 次全部读写。x1 = x.cos() # Read from x in global memory, write to x1
x2 = x1.cos() # Read from x1 in global memory, write to x2而算子融会只需求 2 次全部内存读写,这样就实现了 2 倍加速。x2 = x.cos().cos() # Read from x in global memory, write to x2但是这种做法也并不容易,需求一些条件。首先,GPU 需求知道施行完当前运算后下一步会发生什么,因此无法在 PyTorch 的 Eager 模式(一次运转一个运算符)下进行此优化。其次,我们需求编写 CUDA 代码,这也不是一件单一的事。并不是所有的算子融会都像逐点算子那样单一。你可以将逐点算子融会到归约(reduction)或矩阵乘法上。甚至矩阵乘法本身也可以被认为是一种融会了广播乘法(broadcasting multiply)和归约的运算。任何 2 个 PyTorch 算子都可以被融会,从而节省了读取 / 写入全部内存的内存带宽成本。此外,许多现有编译器通常可以施行「单一」的融会(例如 NVFuser 和 XLA)。然而,更复杂的融会仍然需求人们手动编写,因此如果你想尝试自己编写自定义 CUDA 内核,Triton 是一个很好的起点。令人惊讶的是,融会后的 x.cos ().cos () 运算将破费几乎与单独调用 x.cos () 相同的光阴。这就是为什么激活函数的成本几乎是一样的,尽管 gelu 显然比 relu 包含更多的运算。因此,重新实现 / 激活检查点会产生一些有趣的结果。从本质上讲,进行额定的重新算计可能会导致更少的内存带宽,从而减少运转光阴。因此,我们可以通过重新实现来减少内存占用和运转光阴,并在 AOTAutograd 中构建一个简洁的 min-cut 优化通道。

推理内存带宽成本

对于单一的运算,直接推理内存带宽是可行的。例如,A100 具有 1.5 TB / 秒的全部内存带宽,可以施行 19.5 teraflops / 秒的算计。因此,如果使用 32 位浮点数(即 4 字节),你可以在 GPU 施行 20 万亿次运算的同时加载 4000 亿个数字。此外,施行单一的一元运算(例如将张量 x2)实际上需求将张量写回全部内存。因此直到施行大约一百个一元运算之前,更多的光阴是花在了内存访问而不是实际算计上。如果你施行下面这个 PyTorch 函数:def f(x: Tensor[N]):
for _ in range(repeat):
x = x * 2
return x并使用融会编译器对其进行基准测试,就可以算计每个 repeat 值的 FLOPS 和内存带宽。增大 repeat 值是在不增加内存访问的情况下增加算计量的单一法子 – 这也称为增加算计强度 (compute intensity)。具体来说,假设我们对这段代码进行基准测试,首先要找出每秒施行的迭代次数;然后施行 2N(N 是张量大小)次内存访问和 N *repeat FLOP。因此,内存带宽将是 bytes_per_elem * 2 * N /itrs_per_second,而 FLOPS 是 N * repeat /itrs_per_second。现在,让我们绘制算计强度的 3 个函数图象:运转光阴、flops 和内存带宽。 用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理请注意,在施行 64 次乘法之前,运转光阴根本不会显著增加。这意味着在此之前主要受内存带宽的限定,而算计大多处于空闲状态。一开始 FLOPS 的值是 0.2 teraflops。当我们将算计强度加倍时,这个数字会线性增长,直到接近 9.75 teraflops 的峰值,一旦接近峰值 teraflops 就被认为是「算计受限的」。最后,可以看到内存带宽从峰值附近开始,随着我们增加算计强度开始下降。这正是我们所期待的,因为这说明施行实际算计的光阴越来越多,而不是访问内存。在这种情况下,很容易看出何时受算计限定以及何时受内存限定。repeat< 32 时,内存带宽接近饱和,而未进行充分的算计;repeat> 64 时,算计接近饱和(即接近峰值 FLOPS),而内存带宽开始下降。对于较大的系统,通常很难说是受算计限定还是内存带宽限定,因为它们通常包含算计限定和内存限定两方面的综合原因。衡量算计受限程度的一种常用法子是算计实际 FLOPS 与峰值 FLOPS 的百分比。 然而,除了内存带宽成本之外,还有一件事可能会导致 GPU 无法丝滑运转。

额定开支

当代码把光阴破费在传输张量或算计之外的其他事情上时,额定开支(overhead)就产生了,例如在 Python 解释器中破费的光阴、在 PyTorch 框架上破费的光阴、启动 CUDA 内核(但不施行)所破费的光阴, 这些都是间接开支。额定开支显得重要的原因是现代 GPU 的运算速度非常快。A100 每秒可以施行 312 万亿次浮点运算(312TeraFLOPS)。相比之下 Python 实在是太慢了 ——Python 在一秒内约施行 3200 万次加法。这意味着 Python 施行单次 FLOP 的光阴,A100 可能已经运转了 975 万次 FLOPS。更糟糕的是,Python 解释器甚至不是唯一的间接开支来源,像 PyTorch 这样的框架到达 actual kernel 之前也有很多层调度。PyTorch 每秒大约能施行 28 万次运算。如果使用微型张量(例如用于科学算计),你可能会发现 PyTorch 与 C++ 相比非常慢。例如在下图中,使用 PyTorch 施行单次添加,仅有一小块图是实际施行算计的内容,其他的部分都是纯粹的额定开支。用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理鉴于此,你可能会对 PyTorch 成为主流框架的现象感到不解,而这是因为现代深度学习模型通常施行大规模运算。此外,像 PyTorch 这样的框架是异步施行的。因此,大部分框架开支可以完全忽略。

用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理

如果我们的 GPU 算子足够大,那么 CPU 可以跑在 GPU 之前(因此 CPU 开支是无关紧要的)。另一方面,如果 GPU 算子太小,那么 GPU 将在 paperweight 上破费大部分光阴。

那么,如何判断你是否处于这个问题中?由于额定开支通常不会随着问题的规模变化而变化(而算计和内存会),所以最单一的判断法子是单一地增加数据的大小。如果运转光阴不是按比例增加,应该可以说遇到了开支限定。例如,如果将批大小翻倍,但运转光阴仅增加 10%,则可能会受到开支限定。另一种法子是使用 PyTorch 分析器。如下图,粉红色块显示了 CPU 内核与 GPU 内核的匹配情况。

用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理

CPU 运转地比 GPU 更超前。

另一方面,nvidia-smi 中的「GPU-Util」(不是「Volatile GPU-Util」)入口会测量实际运转的 GPU 内核的百分占比,所以这是另一种观察是否遇到开支限定的好法子。这种开支是 PyTorch 等所有灵活的框架所具有的,本质上都需求破费大量光阴来「弄清楚要做什么」。这可能来自 Python(查找属性或调度到正确的函数)或 PyTorch 中的代码。例如,当你施行 a + b 时,需求施行以下步骤:

Python 需求在 a 上查找__add__调度到的内容。

PyTorch 需求确定张量的很多属性(比如 dtype、device、是否需求 autograd)来决定调用哪个内核。

PyTorch 需求实际启动内核。

从根本上说,这种开支来自能够在每个步骤中施行不同运算的灵活性。如果不需求这种灵活性,解决这种灵活性的一种法子是跟踪它,例如使用 jit.trace、FX 或 jax.jit。或者,可以换用 CUDA Graphs 之类的东西在更低的级别上施行此运算。不幸的是,这是以失去灵活性为代价的。一种两全其美的法子是,通过在 VM 级别进行 introspect 来编写更多符合「真实」的 JIT 的内容。有关更多信息,可参阅 TorchDynamo (https://dev-discuss.pytorch.org/t/torchdynamo-an-experiment-in-dynamic-python-bytecode-transformation/361)。

总结

如果你想加速深度学习系统,最重要的是了解模型中的瓶颈是什么,因为瓶颈决定了适合加速该系统的法子是什么。很多时候,我看到研究人员和其他对加速 PyTorch 代码感兴趣的人,会在不了解所处问题的情况下盲目尝试。用什么tricks能让模型训练得更快?先了解下这个问题的第一性原理当然,另一方面,如果用户需求考虑这些东西,也反映了框架的部分失败。尽管 PyTorch 是一个活跃的关注领域,但 PyTorch 的编译器或配置文件 API 并不是最容易使用的。总而言之,我发现对系统基本原理的理解几乎总是有用的,希望这对你也有用。原文链接:https://horace.io/brrr_intro.html

原创文章,作者:机器之心,如若转载,请注明出处:https://www.iaiol.com/news/yong-shen-me-tricks-neng-rang-mo-xing-xun-lian-de-geng-kuai/

(0)
上一篇 2022年 3月 20日 下午1:00
下一篇 2022年 3月 23日 上午7:26

相关推荐

  • 汽车网关性能新标杆,芯驰科技发布G9系列最新旗舰产物

    7月28日,领先的车规芯片企业芯驰科技发布网关芯片“网之芯”G9系列的最新旗舰产物G9H,面向下一代高性能中心网关、车载计算单元、跨域控制器等应用场景。G9H在保留高平安性和高可靠性的同时,显著提升车内数据交换和处理能力,助力汽车电子电气架构向域控和中心计算的晋级。面向未来的高性能网关处理器G9H基于芯驰高性能高可靠车规处理器平台设计,采用台积电16纳米车规工艺,应用处理器部分配备6个1.8GHz主频的ARM Cortex-A55 CPU,用于运行Linux/QNX等复杂操作系统,并可在此基

    2022年 7月 29日
  • 特斯拉8月在华销量首破4万台,或已达产能极限

    根据乘联会销量数据显示,8月特斯拉批售量到达44264辆,环比增加34%,同比增加275%。截至8月,特斯拉2021年全球累计发卖高出25万辆,海内发卖约15万辆,超越去年全年总和。此外,特斯拉出口量也在断续攀升,自特斯拉7月底宣布将上海超等工场转型为主要的汽车出口中心后,当月出口量就已突破2万辆,8月又增加至31379辆,环比提升29%。据特斯拉CEO埃隆·马斯克此前在推特透露,特斯拉上半季度生产的汽车主要用于出口,下半季度则面向海内市场。目前,特斯拉上海超等工场年产能规划高出45万辆,月度产能规划

    2021年 9月 9日
  • 中科院图协作进修模型,从空间分辨转录组学数据中阐明肿瘤异质性

    编辑 | 萝卜皮空间解析转录组学 (SRT) 技术使钻研职员可以或许获得对构造结构和细胞发育的新见解,尤其是在肿瘤中。然而,缺乏对生物背景和多视图特点的计算开发严重阻碍了构造异质性的阐明。在这里,中国科学院的钻研团队提出了 stMVC,这是一种多视图图协作进修模型,它在通过注意力分析 SRT 数据时集成了构造学、基因表白、空间地位和生物学背景。具体来说,采用半监督图注意力自动编码器的 stMVC 分别进修构造学相似性图或空间地位图的特定视图表示,然后在生物上下文的半监督下通过注意力同时整合两个视图图以获得鲁棒表示。st

    2022年 10月 14日
  • ARM最新回应:新架构Armv9不受美国出口管理条例约束,华为可获受权

    对于Armv9架构,ARM首席执行官西蒙·塞加斯表示,「v9架构将提升宁静性和信任度,并为将来十年的计较机技巧奠定基础。」与此同时,v9架构不受美国出口管理条例约束也为华为带来了利好消息。

    2021年 3月 31日
  • AI自动化系统可以赶快找到新的电池化学成分,比人工尝试要快得多

    编辑 | 萝卜皮开发高能高效电池技术是推进交通和航空电气化的关键方面。然而,电池创新能够需要数年时间才能实现。在非水电池电解质溶液的情况下,选择多种溶剂、盐及其相对比例的许多计划变量使得电解质优化既费时又费力。为了克服这些问题,卡内基梅隆大学(Carnegie Mellon University)的钻研团队提出了一种尝试计划,将呆板人技术(一个名为「Clio」的定制自动化尝试)与呆板学习(一个名为「Dragonfly」的基于贝叶斯优化的尝试计划器)结合起来。在单盐和三元溶剂计划空间内对电解质电导率进行自主优化,在两

    2022年 10月 13日
  • 给5G基带也加上呆板进修单元:高通的AI脑洞还有太多

    最先进的人工智能手艺,并不总意味着数块 GPU、每秒算力上 E 的超算。使用最广泛的移动芯片上,人们正在使用最先进的 AI 手艺。最近,高通再次利用 AI 兑现了「突破性的 5G 效能」。在巴塞罗那举办的 MWC 2022 国际通信展上,高通 CEO 安蒙(Cristiano Amon)发布了全球首款搭载 AI 估计核心的 5G 通信基带骁龙 X70。在显卡、手机 CPU 旁边出现 AI 估计单元之后,现在连通信基带也要专门的 AI 芯片加持了 ,这不仅让人要问:「有必要吗?」首款搭载 AI 核心的 5G 基带根据

    2022年 3月 10日
  • 27亿参数的「野生版」GPT-3开源,GitHub项目2.9K Star量

    OpenAI 著名的说话模型 GPT-3 可以懂数学、翻译文字,还能写论文拿到及格成绩,这样的 AI 什么时候才能开源呢?现在已有了一个差不多的项目。

    2021年 3月 26日
  • 千寻地位冯绍军:时空网为聪慧出行注入新动能

    6月26日,2021环球聪慧出行大会主论坛暨中国汽车产业低碳发展高层论坛在南京召开。千寻地位首席科学家冯绍军出席主论坛并发表讲演——《时空网为聪慧出行注入新动能》。冯绍军认为,时空网一方面为以“人、车、路、城”四个维度为代表的聪慧出行直接注入新动能,激发新技巧融合的聚变和新运用生态的裂变;另一方面为铁路、公路、机场、港口、管道、电网、水利、市政等乡村里的各类基础设施提供时空智能,兑现传统基础设施与新一代信息基础设施的融合创新发展,为聪慧出行间接赋能。(图为千寻地位首席

    2021年 6月 28日
  • 9亿训练集、通用CV任意,微软打造Florence模型打破分类、检索等多项SOTA

    来自微软的研讨者另辟蹊径,提出了一种新的计算机视觉基础模型 Florence。在广泛的视觉和视觉 – 语言基准测试中,Florence 显著优于之前的大规模预训练方法,实现了新的 SOTA 结果。

    2021年 11月 24日
  • 言语模型参数越多越好?DeepMind用700亿打败自家2800亿,训练优化出「小」模型

    给定固定的 FLOPs 估算,该当如何权衡模型巨细和训练 token 的数目?DeepMind 得出了与先前不同的结论。

    2022年 4月 3日

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注