PyTorch 团队亲自教你如何加速大模型推理。
在过去的一年里,生成式 AI 发展迅猛,在这当中,文本生成一直是一个特别受欢迎的领域,很多开源项目如 llama.cpp、vLLM 、 MLC-LLM 等,为了取得更好的效果,都在进行不停的优化。
作为机器学习社区中最受欢迎框架之一的 PyTorch,自然也是抓住了这一新的机遇,不断优化。为此让大家更好的了解这些创新,PyTorch 团队专门设置了系列博客,重点介绍如何使用纯原生 PyTorch 加速生成式 AI 模型。
在第一篇博客中,PyTorch 团队展示了仅使用纯原生 PyTorch 重写 Segment Anything(SAM)模型,比原始实现快 8 倍。在本博客中,他们又为我们带来了新的内容,即如何加快 LLM 推理。
我们先来看看结果,该团队重写 LLM,推理速度比基线足足快了 10 倍,并且没有损失准确率,只用了不到 1000 行的纯原生 PyTorch 代码!
这些优化包括:
- Torch.compile:PyTorch 模型编译器, PyTorch 2.0 加入了一个新的函数,叫做 torch.compile (),能够通过一行代码对已有的模型进行加速;
- GPU 量化:通过降低运算精度来加速模型;
- Speculative Decoding:一种大模型推理加速方法,使用一个小的「draft」模型来预测大的「目标」模型的输出;
- 张量并行:通过在多个设备上运行模型来加速模型推理。
接下来,我们看看每一步都是如何实现的。
6 步加快大模型推理
该研究表示,在没有优化之前,大模型的推理性能为 25.5 tok/s,效果不是很好:
torch.compile 允许用户将更大的区域捕获到单个编译区域中,特别是在 mode=”reduce-overhead” 时(参考下面的代码),这一功能对于减少 CPU 开销非常有效,除此以外,本文还指定 fullgraph=True,用来验证模型中没有「图形中断」(即 torch.compile 无法编译的部分)。
第一个障碍是 kv 缓存。即当用户生成更多的 token 时, kv 缓存的「逻辑长度(logical length)」会增长。出现这种问题有两个原因:一是每次缓存增长时重新分配(和复制)kv 缓存的成本非常高;其次,这种动态分配使得减少开销变得更加困难。
为了解决这个问题,本文使用静态 KV 缓存,静态分配 KV 缓存的大小,然后屏蔽掉注意力机制中未使用的值。
尽管 kv 缓存被设置为静态化,但由于提示长度可变 ,prefill 阶段仍然需要更多的动态性。因此,需要使用单独的编译策略来编译这两个阶段。
通过上文,我们已经看到应用 torch.compile 、静态 kv 缓存等带来的巨大加速,但 PyTorch 团队并不满足于此,他们又找了其他角度进行优化。
他们认为加速生成式 AI 训练的最大瓶颈是将权重从 GPU 全局内存加载到寄存器的代价。换句话说,每次前向传播都需要「接触(touch)」GPU 上的每个参数。那么,理论上我们能够以多快的速度「接触」模型中的每个参数?
如下图所示,将上述公式带入具体的数值,可以得到 MBU 为 72%!这个结果是相当不错的,因为很多研究很难突破 85%。
将 int8 量化应用于 Llama-7B 模型,性能提高了约 50%,达到 157.4 tokens/s。
即使在使用了 int8 量化等技术之后,该团队仍然面临着另一个问题,即为了生成 100 个 token,必须加载权重 100 次。
本文发现,当权重为 4-bits 时,模型的准确率开始下降。
最后,将所有技术组合在一起以获得更好的性能,得到 244.7 tok/s。
到目前为止,本文一直是在单个 GPU 上最大限度地减少延迟。其实,使用多个 GPU 也是可以的,这样一来,延迟现象会得到进一步改善。
非常庆幸的是,PyTorch 团队提供了张量并行的低级工具,只需 150 行代码,并且不需要任何模型更改。
原文链接:https://pytorch.org/blog/accelerating-generative-ai-2/本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。