大语言模型(Large Language Model, LLM, 下称大模型)可谓是当下最火的科技。纵使它这么火爆,能够入局的玩家却不多。究其原因,还是玩转大模型的门槛太高了。「拥有」一个专属大模型并不难。参照论文、开源代码、数据集,改一改,总能搓出来一个大模型。但是想要玩转,就难了。

怎样才算玩转?当然是玩着,还把钱挣了。本文尝试从学术界和工业界的双重视角来解释:为了玩转大模型,需要克服哪些门槛?

如何将一个大模型运行起来?

GPUs, lots of GPUs.

现在,所有人都知道,跑大语言模型的关键在于显卡(GPU)。谁拥有最多的显卡,谁就有机会发展出更大的模型,提供更好的服务。但是只要有显卡就够了吗?

答案是:不够。

目前流行的大语言模型,通常是 Transformer 架构模型,是一类深度神经网络模型。这类模型需要经历训练和推理两个阶段。就像人脑一样,先学习知识,再运用到新的问题上,所谓举一反三。对于企业来说,就需要先拥有一个训练好的模型,再将用户的问题输入到模型中,进行推理,并返回结果。

理想情况下,如果一块 GPU 训练一个模型要一天,那么两块 GPU 训练相同的模型就只用半天。现实会给你狠狠的一巴掌——钞能力在这不管用。正如《人月神话》讨论工作效率随人数增加,非线性增加的问题,随着 GPU 数量的增加,模型训练的效率也不是成比例增加的。业界通常使用加速比(多卡训练下的单卡吞吐量平均指标除以单卡训练下的吞吐量平均指标)来衡量多卡训练的效率,越接近 1 越好。

以双卡加速比 0.8 为例。这代表着,如果一张卡单独训练时的吞吐率为每秒钟 600 条序列(即每秒钟,显卡可以接收 600 条序列的文字并更新模型参数),那么两张卡时,每张卡每秒钟只能处理 600*0.8 = 480 条序列了,两张卡也才处理 960 条序列。相比较理想情况下,双卡 600*2=1200 条序列,是不是感觉两张卡带来的效率提升也没那么大了?

GPU 越多,GPU 的吞吐率越小,GPU 吞吐率越小,GPU 越少。所以,GPU 越多,GPU 越少。

一个「GPU 大厂」是如何运转的?

假设 GPU 已经不是门槛,厂商就会把这些 GPU 全部放在一起,搭建一个专门的 AI 集群处理 LLM 相关服务流量,称为「GPU 大厂」。大厂员工往往干活的时间不多,更多的时间花费在拉通对齐,GPU 大厂也不例外。

GPU 拉通对齐什么呢?

回答上面的问题,首先要解释一下多卡训练时,每个 GPU 在干嘛。模型训练阶段主要涉及两个部分:数据集和模型参数。随着数据集和模型参数的增加,多卡训练也可以分为数据并行和模型并行。数据并行就是将一整个数据集分成几个小数据集,每个 GPU 负责训练一个小数据集。模型并行就是将模型划分为好几个子模型(按照划分的方式不同,分为张量并行和流水线并行),每个 GPU 负责训练一个子模型。由于训练的过程需要迭代好多轮,所以每一轮结束这些 GPU 都需要进行同步,向别的 GPU 汇报这一轮的工作结果(训练结果)。

  • 流水线并行:一个 LLM 模型通常包含很多层,每一层需要依次接收上一层的结果作为输入,并将计算结果输出到下一层,涉及到 Send/Recv 通信操作。这类操作通信量不多,是 GPU 所负责的模型层的计算结果,但是由于依赖关系,每一层需要等待上一层的计算结果才可以继续训练,引入了很多等待时间,学术界称为 Bubble 。
  • 张量并行:LLM 模型的一层也可以由几个 GPU 负责训练。这时候拉通对齐的成本就大大增加了。因为单层模型训练涉及到的是矩阵乘法,这里每个元素的计算结果都有赖于周围的元素,所以这里的通信关系就由链式的变成了网状的,一般称为 All-to-All 通信,即每个 GPU 都要和其他 GPU 都通信一次,且每次通信的内容都有所不同。张量并行的通信量是多卡训练中最多的环节,也是最容易产生瓶颈的地方。如果流水线并行看作部门间和部门间的交流,那么张量并行就是部门内部小组成员高强度频繁的交流。
  • 数据并行:当数据集很庞大的时候,可以用多个 GPU 同时训练一个模型,每个模型使用一部分子数据集作为输入,最终每一轮的训练成果汇总到其中一个 GPU,或者同步到全部 GPU 上,通过这种方式能够降低数据集的训练时间。不可避免的需要在训练一段时间后同步一下进度 (Allreduce 操作),否则每个 GPU 上的模型只包含自己训练的数据信息。数据并行的频率和通信量介于流水线并行和张量并行之间。
流水线并行示意图(图源:GPipe: Easy Scaling with Micro-Batch Pipeline Parallelism)
数据并行和模型并行示意图(图源:https://www.paddlepaddle.org.cn/support/news?action=detail&id=2913)

上述三种并行方式发展的很成熟,并被应用于现在流行的训练框架中(DeepSpeedMegatron-LM)。除了以上最典型的三种并行方式,随着对大模型训练的研究更加深入,一些训练框架应用了如序列并行(Colossal-AI)以及专家并行(DeepSpeed-MoE)等手段。这些手段通常针对特定场景或模型,因此不再赘述。

现在的 GPU 性能越来越强,单卡训练的速度越来越快,但是想让这些 GPU 一起高效的干活越来越困难了。研究结果表明1,AI 集群的瓶颈往往在 GPU 间的通信上。在学术界,有一个专门的指标来衡量 GPU 的利用率:MFU。字节跳动最新的研究成果2,在多达一万显卡的集群进行优化,将 MFU 提高至55%,也就是说 AI 集群有大约一半的时间,GPU 都在「摸鱼」。

GPU 也要降本增效

不是 GPU 想摸鱼,是工作内容不得不摸鱼。为了不让 GPU 摸鱼,学界和业界可谓是挖空心思降本增效,试图用更少的 GPU 干更多的活:

  • 流水线编排优化:GPU 也要做好任务管理。如果每个 GPU 在流水线中都傻傻地等待其他 GPU 完成任务再开始自己的工作,不就可以「摸鱼」了吗,那怎么行!一些工作(GPipePipeDream)通过发掘不同 GPU 间可以独立完成的工作,尽可能小的减少 GPU 间的工作依赖,让每个 GPU 忙完手里的活就赶紧发给下一个 GPU,而不是等所有工作全部忙完再汇报,大大降低 GPU 的摸鱼时间。
  • 梯度压缩技术:一个合格的打工人,不会不加处理地将工作结果汇报给他人,而是整理出有价值的信息汇报,GPU 也不例外。GPU 的每一轮训练结果不一定全部有用,有很多零值,别的 GPU 不关心。因此,一些工作(OmniReduce)通过各种手段,例如让 GPU 只发送必要的信息,降低 GPU 发送的数据量,避免时间浪费在收发数据上。
  • 网络辅助计算:大厂员工通常会配备实习生干一些杂活,现在可以招募可编程交换机作为 GPU 的实习生了。不同于传统网络设备只负责转发数据,可编程交换机可以从事简单的计算操作。一些工作(ATPSwitchML)基于此特点,在转发 GPU 的数据时提前使用可编程交换机进行计算,从而让 GPU 轻松一点。

除了直接解决 GPU 使用效率不高的问题,业界还会思考一些其他更现实的问题:

  • 异构 GPU 集群增效:鸡蛋不能放在一个篮子里,公司采购的 GPU 也不能是一个厂商的(现在最流行的如 NVIDIA 和华为昇腾)。不同厂商的 GPU 性能指标会有所不同,一些工作提出管理和调度接口,用于统一管理和分配异构 GPU 资源,保证不同型号 GPU 的性能差异不会影响集群整体性能。
  • 提高 GPU 集群弹性:人会生病,GPU 也会。在真实场景下,在 1000 个 GPU 上同时运行程序,很大概率会出现一些 GPU 无法使用。为了让训练进度不被失效的 GPU 拖慢,一些工作(GeminiHoplite)考虑快速地恢复失效 GPU 负责的程序或者重新规划现有 GPU 的训练内容。
  • 提高 GPU 碎片利用率:现在的 GPU 单个算力性能往往过剩,如果一个 GPU 只负责一个任务,算力很难被压榨干净。为了赚更多钱,集群中的 GPU 会同时负责多个模型训练任务 。好钢要用在刀刃上。一些工作(FGDGMLake)考虑如何将这些碎片 GPU 资源分配至不同的训练任务,从而刚好满足每个训练任务的需求,不过度分配资源。

从训练到推理

模型训练和推理的关系就像是人类学习和学以致用的关系。我们花了大量时间学习,最终是为了将学习的知识应用到实际。

学习的时候,关注点在学习内容。学以致用时,关注点在反应时间。面对询问,一个人能够很快地做出反应并给出正确答案,我们会夸这个人聪明。大模型也不例外。这就导致模型训练和推理时,业界的关注目标不一样。作为用户,在各个平台和大模型对话,背后都是一个个推理请求,对应了大模型的推理任务。对于推理任务,无论是用户还是业界,都希望大模型反应速度越快越好,对应的指标就是「推理时延」

从技术的角度,推理任务和训练任务也有所不同,直接给出结论就是:推理任务对内存访问速度的要求更高。所以学界和业界开始意识到,针对推理任务,需要从新的角度进行优化。这些优化近期被提出来,思路简单,却能够取得很好的效果:

  • 解耦处理模型推理中的关键阶段:大模型推理包含两个阶段(Prefill 和 Decoding 阶段),如果不区分这两个阶段,会造成任务的性能干扰。一些工作(SarathiDistServe)在调度推理任务时将这两个阶段分开考虑,交错不同阶段的请求或分配不同的 GPU 避免干扰,均能达到好几倍的加速效果
  • 利用局部性原理优化大模型推理系统:局部性原理可以看成计算机的就近原则。通过将「局部性原理」应用到大模型推理系统中的模型重载、模型迁移、资源分配,ServerlessLLM(OSDI 24)实现了10~200 倍的推理速度提升
  • 使用小模型去代替大模型:大模型在通用任务上的效果卓越,但是在特定场景下的性能能胜过专用小模型吗?Tabi (Eurosys 23)企图分析用户的请求和小模型的性能,优先使用合适的小模型服务用户请求,在必要时才使用大模型。通过这种方式降低平均推理时延 21%-40%

后记

这篇文章的写作契机是刷 5 月 6 日 的派早报,看到其中分享了阿里云在 Eurosys 24 上发表的学术成果。虽然阿里云的这篇论文成果不属于我的研究领域,但是我会阅读 Eurosys 这类系统会议中的其他论文。我着实有点惊讶,少数派对学术会议的关注,也开始考虑,是不是我也可以介绍一些学术成果

曾经有评论问我的研究内容是什么?不太好说清楚,这篇文章可以作为一部分回答。多亏了 OpenAI ,大模型被广为人知,我的研究内容看上去也有了一点价值。除了产生一点学术价值或工业价值,我更希望产生一些社会价值。希望一些「小白」看到这篇文章,对大模型有更深的理解。尚不清楚这篇文章带来的具体价值,或许在吹水时来一句:你知道玩大模型不是卡越多越好吗?能让同伴对你刮目相看——搁这装逼来了。

为了增强可读性,尽可能避免将本文写成文献综述或技术文档,因此想到将 AI 集群类比科技大厂,尝试以较为简单易懂的方式去介绍大模型技术落地过程中面临的挑战。展开来说,这些内容三天三夜都说不完,本文权当抛砖引玉。如果读者想要获取更加专业的内容,可以去 Arxiv 、知乎等平台阅读更加专业的材料,也可以直接和我交流。

> 关注 少数派小红书,感受精彩数字生活 🍃

> 特惠、好用的硬件产品,尽在 少数派 sspai 官方店铺 🛒