2022年11月,ChatGPT横扫全球,成为应用人工智能(AI)领域迄今为止最令人惊叹的“哇!”时刻,也是当前科技投资激增的催化剂。2023年11月,首席执行官Sam Altman宣布该产品周用户量达到1亿,这在该领域内的增长速度是前所未有的。随着用户量爆炸性增长,真正的扩展挑战是什么呢?为了深入了解,我再次采访了Evan Morikawa,他是ChatGPT发布和扩展过程中的应用工程团队负责人。那么,让我们听听Evan的分享。
1. 关于OpenAI和Evan的简介
Evan是如何加入OpenAI,并最终领导应用工程团队的?这个团队也参与了ChatGPT的构建。
OpenAI是ChatGPT的创造者,ChatGPT只是公司众多产品之一。其他产品包括DALL·E 3(图像生成)、GPT-4(一种高级模型)以及OpenAI API,开发者和公司利用这个API将AI整合到他们的流程中。ChatGPT和API都提供了多种模型类别:GPT-3、GPT-3.5和GPT-4。
负责制作和扩展这些产品的工程、产品和设计组织称为“应用”,成立于2020年GPT-3发布时。它的主要任务是安全地将OpenAI的研究成果推向世界。OpenAI本身成立于2015年,今天公司的核心仍然是一个研究实验室,旨在创建一个安全且对齐的人工通用智能(AGI)。
2. ChatGPT是如何工作的?回顾一下。
对于那些没有从头开始构建ChatGPT的人来说,它是如何工作的?
为了引入一些扩展话题,让我简单介绍一下这些AI模型是如何工作的。如果你已经熟悉基础知识,可以跳到第3部分。
当你向ChatGPT提问时,会发生几个步骤:
输入。我们从文本输入中获取你的文本。
分词。我们将其切分成令牌。一个令牌大致对应几个Unicode字符。你可以将其视为一个词。
创建嵌入向量。我们将每个令牌转换成一系列数字,这被称为嵌入向量。
通过模型权重乘以嵌入向量。然后,我们将这些嵌入向量与数以百亿计的模型权重相乘。
抽样预测。在这些乘法操作结束时,数字向量代表了下一个最可能令牌的概率。接下来最可能的令牌是从ChatGPT中输出的下几个字符。
让我们可视化这些步骤。前两步比较简单:
步骤1和2:当你向ChatGPT提出问题时发生的事情
注意,分词不一定意味着将文本分成单词;令牌也可以是单词的子集。
嵌入向量是大型语言模型(LLM)的核心,我们在下一步从令牌中创建它们:
步骤3:当你向ChatGPT提出问题时发生的事情。嵌入向量代表了令牌作为向量。上述嵌入向量中的值是示例
一个嵌入向量是令牌的多维表示。我们明确训练一些模型,以显式允许捕获单词或短语之间的语义意义和关系。例如,“狗”和“小狗”的嵌入向量在几个维度上比“狗”和“电脑”更接近。这些多维嵌入向量帮助机器更有效地理解人类语言。
模型权重用于计算加权嵌入向量矩阵,这用于预测下一个可能的令牌。对于这一步,我们需要使用OpenAI的权重矩阵,该矩阵由数以百亿计的权重组成,并将其与我们从嵌入向量构造的矩阵相乘。这是一次计算密集型的乘法操作。
步骤4:当你向ChatGPT提出问题时发生的事情。权重矩阵包含数以百亿计的模型权重抽样预测是在我们进行了数十亿次乘法操作后完成的。最终向量代表了下一个最可能令牌的概率。抽样是我们选择下一个最可能的令牌并将其发送给用户的过程。ChatGPT中的每个单词都是通过每秒多次重复这个过程生成的。
预训练和推理
我们如何生成这套复杂的模型权重,其值编码了大部分人类知识?我们通过一个称为预训练的过程来完成。预训练的目标是构建一个模型,它可以预测下一个令牌(你可以将其视为一个词),对于互联网上的所有单词都是如此。
在预训练期间,通过梯度下降,权重会逐渐更新,这是一种数学优化方法。梯度下降的类比是一位徒步旅行者被困在山上,他们正试图下山。然而,由于浓雾限制了他们的视野,他们只能看到周围的一小片区域。梯度下降意味着查看徒步旅行者当前位置的坡度,并朝着最陡峭的下降方向前进。我们可以假设从简单的观察中并不明显坡度,但幸运的是,这位徒步旅行者有一个测量坡度的仪器。然而,进行单次测量需要时间,他们希望在日落前下山。因此,这位徒步旅行者需要决定多久停下来测量一次坡度,以便他们还能在日落前下山。
一旦我们有了我们的模型,我们就可以在其上运行推理,这是当我们用文本提示模型时发生的事情。例如,提示可能是:“为Pragmatic Engineer写一篇客座文章。”这个提示然后要求模型预测下一个最可能的令牌(单词)。它基于过去的输入做出这个预测,并且这个过程反复进行,一个接一个地令牌,一个接一个地单词,直到它吐出你的帖子!
自我关注的可扩展性挑战
在底层,我们使用的是Transformer架构,其关键特性是每个令牌都知道每个其他令牌。这种方法被称为自我关注。一个后果是,你的文本越长——或上下文越多——需要的数学运算就越多。
不幸的是,自我关注的规模呈二次方增长。如果你想让模型预测第100个令牌,它需要做大约10,000次操作。如果你想让它预测第1,000个令牌,它需要做大约1,000,000次操作。
起初,这听起来像是坏消息。然而,我们可以使用一些巧妙的方法来规避这个二次方规模问题。在我们讨论如何解决它之前,我们需要讨论为ChatGPT提供动力的基础设施。
3. GPU的重要性
GPU(图形处理单元)是ChatGPT及其构建的API的生命线。GPU的极度短缺、它们的怪癖和成本主导了我们的运营和扩展方式。
为了铺垫,让我介绍一下我们使用的一种GPU。
NVIDIA H100。NVIDIA H100。它配备了特殊的高带宽内存(HBM),每个GPU都附加了HBM内存。GPU之间可以通过一种高带宽互连叫做NVLink进行通信,它们可以通过一种特殊的以太网替代品叫做Infiniband与外界通信。我们在单个节点中打包了8个这样的GPU。Nvidia销售了一种类似的配置,称为DGX H100。对我们来说,每一点增加的计算或带宽直接影响ChatGPT用户体验。
4. 五大扩展挑战
有很多关于GPU的扩展挑战需要讨论。我们关注的是:
#1:GPU RAM和KV缓存
#2:批量大小、操作:字节比和算术强度
#3:衡量正确指标的重要性
#4:在任何地方寻找GPU
#5:缺乏自动扩展
在我们扩展ChatGPT时,理解这些是至关重要的。让我们深入了解!
挑战#1:KV缓存和GPU RAM
我们的一个大挑战是自我关注的规模呈二次方增长,这意味着我们生成的令牌越多,我们需要的操作就越多(大约对于第100个令牌是~10,000次操作,但对于第1,000个令牌是大约1,000,000次)。我们如何提高性能?
一个初始的解决方法是缓存我们为所有先前令牌所做的数学运算;即KV缓存。我们在我们的机器学习(ML)模型中使用注意力机制。有了这个模型,我们使用三个向量:
Q:与我们包含的内容相关
K:与我们用作输入到输出的内容相关
V:学到的向量;计算的输出
我们可以缓存K和V,因此得名“KV缓存”。然而,我们不能缓存Q,因为这个向量每次都会改变。
我们必须将KV缓存存储在GPU RAM中。这是因为在GPU RAM中移动数据的速度大约为3TB/秒,当我们使用高带宽内存(HBM)时。然而,如果我们将数据通过PCIe总线(PCI Express:一种高速总线标准,常见于主板上用于数据传输)推送,我们得到的速度大约为30GB/秒。使用HBM的速度大约快两个数量级(大约100倍)!
为什么HBM这么快?它是通过堆叠层与GPU物理绑定的,拥有数千个引脚,用于大规模并行数据吞吐量。
这种GPU HBM RAM非常昂贵且相当有限。大多数HBM RAM也用于保存模型权重。就像任何缓存一样,当它填满时,我们通过“过期”最旧的数据来释放空间。
“缓存未命中”对我们的用例来说非常昂贵。缓存未命中是指系统尝试从缓存中检索数据——比如KV缓存——但没有缓存任何内容的事件。通常是因为我们不得不“过期”这个值,并将其从我们的HBM内存中踢出来以释放空间。如果发生缓存未命中,我们需要重新计算整个ChatGPT对话!而且我们处于第1,000个字符,所以那可能更接近1,000,000次操作!
我们的基础设施在用户之间共享GPU RAM。这意味着作为用户,如果你的对话闲置时间过长,你的对话可能会从系统(GPU缓存)中被逐出,因为我们需要为其他对话释放空间。
这种缓存方法有几个含义:
GPU RAM是最宝贵的商品。实际上,GPU RAM而不是计算资源,是LLM操作最常见的瓶颈。
缓存未命中率非常重要!缓存未命中是指系统尝试从缓存中检索数据——如KV缓存——但没有缓存任何内容的事件。缓存未命中对GPU工作量的影响是巨大的,非线性的。缓存未命中率越高,GPU需要做的工作就越多,呈二次方而非线性。
这意味着在扩展ChatGPT时,没有一些简单的CPU利用率指标可以查看。我们不得不关注KV缓存利用率,以及如何最大化GPU RAM。
挑战#2:优化批量大小
批量大小是扩展ChatGPT时需要平衡的第二个指标。粗略地说,批量大小是我们通过GPU运行的并发请求的数量。H100 GPU最多可以在一秒钟内将3.35TB的RAM移动到其寄存器中。GPU寄存器是快速的片上内存,存储计算核心将要执行的操作数。在数据移动到寄存器的同一秒钟内,H100可以乘以1.98千万亿个8位浮点数。让我们将这1.98千万亿次操作除以移动的3.35TB数据;H100可以在移动1字节所需的时间内执行591次浮点运算。H100的操作:字节比为591:1。如果你要花时间移动1GB,你应该至少每秒执行591亿次浮点运算(FLOPS)。如果做得少于这个数值,意味着浪费了GPU FLOPS。然而,如果你做得更多,你就在等待内存带宽。在我们的模型中,我们移动的内存量相对固定,大约是我们模型权重的大小。通过调整我们的批量大小,我们对这个过程有一定的控制,这改变了涉及的数学计算量。
在扩展ChatGPT时,我们需要充分“饱和”GPU,这意味着监控我们的批量大小,以便我们有正确的FLOPS,这样GPU就不会因为计算而未被充分利用,也不会因为等待内存带宽而过度利用。
实际上,要真正维持盒子上打印的flop数字是几乎不可能的。我们可以使用数学来接近,但在生产中需要大量实验来微调一切。
挑战#3:衡量正确的指标
批量大小和KV缓存利用率的组合是我们关注的主要指标。这是我们用来确定服务器负载的两个数字。我们并没有一开始就得到这个指标;花了时间才发现它对我们最有效。最初,我们有一个类似于标准CPU利用率指标的更简单的gpu利用率指标。然而,它证明是误导性的,因为简单的利用率只说明了GPU在一个时间段内是否在进行数学计算。它没有告诉我们:
我们是否已经饱和了算术强度;浮点运算与总数据移动量的比率:FLOPS/字节。基本上,GPU利用率没有告诉我们我们是否在计算上未被充分利用,或者是否被内存饿死。
我们是否正在耗尽KV缓存。这是一个问题,因为有了KV缓存未命中,GPU需要进行更多的计算来计算未缓存的结果。
还有其他瓶颈。KV缓存和批量大小并不是我们发现的唯一瓶颈。在现实世界中,我们遇到了来自:
- 内存带宽
- GPU之间的网络带宽
- 节点(机器)之间的网络带宽
……只是列举了三个!
让情况变得更复杂的是,瓶颈的位置经常变化。例如,要求ChatGPT总结一篇论文与要求它写一篇论文的性能特性截然不同。我们不断调整LLM变压器模型架构的特定细节,这些变化会影响瓶颈出现的地方。
在LLM的问题空间中,你会遇到的约束的变化范围出奇地广泛。这使得我们难以解决问题,也使得芯片制造商难以设计出能够实现最佳平衡的芯片。
例如,NVidia的新H100芯片是A100芯片之后的一代。H100在计算(即FLOPS)上增加了大约6倍,而内存大小保持不变,内存带宽只增加了1.6倍。由于我们经常受到内存的限制,FLOPS(和成本)的戏剧性增加往往未被充分利用。
事实是,像NVIDIA H100这样的顶级芯片今天的设计是几年前就锁定的。当H100芯片设计时,NVIDIA无法知道内存的重要性的发现,因为未来的架构很难预测。最近宣布的H200芯片增加了内存;然而,该行业花了一段时间才更好地理解这些独特的瓶颈,以大规模运行LLM。
挑战#4:在任何地方寻找GPU
与GPU相关的另一个挑战是在哪里找到它们!我们的公司——以及整个AI领域——的增长速度远远超过了供应商,如NVIDIA,或完整的TSMC供应链,可以生产GPU的速度。对于像半导体和数据中心这样复杂的供应链,瓶颈会发生在许多地方。
一种解决方案是从我们能找到的任何地方获取GPU。我们使用Microsoft Azure作为我们的云提供商,它在许多不同的地理区域和数据中心都有GPU。因此,我们很快就发现自己遍布全球的许多地区。
从第一天起,我们的小团队被迫采取多区域、多集群和全球分布的做法。我们的kubernetes集群很快就从被视为宠物转变为更像牲畜。
一个平衡良好的GPU舰队比分配附近的GPU更重要。对于ChatGPT来说,响应时间的最大瓶颈是GPU可以多快地逐个输出令牌。这意味着GPU地理位置靠近最终用户的优先级较低,因为网络请求的往返时间影响较小,而GPU“随时准备好”更重要。我的职业生涯教会了我计算在边缘的重要性,出于延迟原因。这对于这些工作负载来说不太相关,尤其是在GPU如此受限的情况下。
挑战#5:无法自动扩展
最后一个主要挑战是无法扩展我们的GPU舰队。简单地说,就是没有更多的GPU可以购买或租用,因此没有GPU可以自动扩展到。获得GPU的困难持续到今天,看起来没有缓解的迹象。需求的指数当前看起来比供应的指数大。不仅有更多的用户,而且更大的模型需要更多的计算,新技术如代理每个用户需要大量更多的计算。
所以,如果你看到ChatGPT的“我们已满载”消息,这是一个正确的陈述!这意味着我们没有地方可以扩展,因为我们当时已经利用了所有的GPU。
不幸的是,像GPT-4这样的模型需要如此多的计算,以至于GPU目前是我们唯一的选择,以便在规模上提供我们的服务。普通CPU将慢几个数量级。
5. 学到的经验
扩展ChatGPT当然不是你平均的软件工程扩展问题。然而,它一直是工程扩展的速成课,有很多经验可以在其他情况下应用。这里是我们学到的关键经验。
在早期扩展中,森林和树木都很重要。低级细节(树木),如KV缓存优化和CUDA内核,与更高级别的系统细节(森林)一样重要,例如全球数据中心战略。我们团队在堆栈中跳跃的能力——从GPU的最低级别,一直到产品决策——是至关重要的。
以一种适应性的方式考虑系统的约束。在加入OpenAI之前,我习惯于做一些事情,如:
调整系统以达到大约80%的CPU利用率指标——通常被认为是“好的”。一旦达到这个指标,就坐下来,而该指标保持不变。
自动扩展到一个“无限大”的云;意味着总是可以配置更多的机器。
优先考虑边缘计算:将其移动得非常靠近用户,以减少往返请求的延迟,并改善用户体验。
在OpenAI,这些做法都不适用!我们需要提出新的方法,这些方法既实用又易于衡量和扩展。
而且,就在我们弄清楚有效的东西时,模型架构会发生变化,或者会提出一个新的推理想法,或者产品决策会改变系统的使用方式。因此,我们需要一次又一次地适应。
深入挖掘。在我们运作的问题空间中,最低级别的实现细节真的很重要。将ChatGPT视为一个“黑盒”,它将文本作为输入,并在另一端吐出稍微聪明一些的文本,这很诱人。然而,越多的人深入到“黑盒”究竟如何工作的最小细节,我们就越能成为一个更好的团队和产品。
这还只是早期。挑战的规模只会增长。随着从GPT-2、3到4的每一次跳跃,我们需要完全新的方法来训练和运行模型以实现规模。这将在未来的版本中继续。我们所有的新模式,如视觉、图像和语音,都需要重新架构系统,同时解锁新的用例。
OpenAI的发展速度——以及整个生态系统——正在加速。我们将看到下一个10倍规模的挑战是什么!
ChatGPT的工作方式并不神奇,值得了解。像大多数人一样,我第一次尝试ChatGPT时的反应是它感觉很神奇。我输入了问题,并得到了感觉像是来自人类的答案!ChatGPT在处理人类语言方面做得非常出色,并且可以访问比任何一个人都多的信息。它在编程相关的问题上也很擅长,有一段时间我怀疑ChatGPT是否可以在编程等领域比人类更有能力,直到现在?
为了了解ChatGPT的局限性,你需要了解它是如何工作的。ChatGPT和其他LLM不会像人类那样“思考”和“理解”。然而,ChatGPT确实会根据下一个最可能的单词是什么,根据输入和到目前为止生成的所有内容来生成单词。
在关于ChatGPT如何工作的一篇精彩深入文章中,WolframAlpha的创造者Stephen Wolfram总结了ChatGPT:
“ChatGPT的基本概念在某种程度上相当简单。从网上、书籍等处获取大量人类创建的文本样本。然后训练一个神经网络生成“类似于此”的文本。特别是,让它能够从一个“提示”开始,然后继续输出“像它所训练的那样”的文本。
正如我们所看到的,ChatGPT中的实际神经网络由非常简单的元素组成——尽管有数十亿个。神经网络的基本操作也非常简单,基本上由将输入派生自到目前为止生成的文本“一次通过其元素”(没有任何循环等)的每一个新单词(或单词的一部分)生成。但令人惊讶的是——出乎意料的是——这个过程可以产生成功地“类似于”网络、书籍等上的文本。
ChatGPT的具体工程使其相当引人注目。但最终(至少在它可以使用外部工具之前)ChatGPT只是从它积累的“常识统计”中提取出一些“连贯的文本线索”。但结果的人类化程度令人惊叹。”
扩展ChatGPT的工程挑战是可以理解的。当扩展一个系统时,这些是常用的技术:
- 通过交换内存以节省重复的、昂贵的计算操作(记忆化),反之亦然;如果内存不足且有大量未使用的计算,使用计算来节省内存
- 购买更多硬件以横向扩展
- 找出要衡量的正确事物,并进行改进,使这些指标朝着正确的方向发展;冲洗并重复
OpenAI的工程团队采用了所有这些技术来扩展该产品。
一些扩展挑战可以简化为解决一个数学问题。在挑战#2中——优化批量大小——解决最大利用率的问题归结为在操作和内存带宽之间进行最大化。一旦你知道了操作和内存带宽的值,这就成了一个优化练习。
当面临优化效率的挑战时,可以从这种方法中汲取灵感。弄清楚你的系统的特性——吞吐量、延迟、CPU利用率、内存利用率和其他相关值——并弄清楚改变一个将如何改变另一个。更高的CPU利用率(使用更少的机器)意味着什么?每台机器增加或减少内存会怎样?等等。
即使是OpenAI也在努力寻找GPU硬件。大型语言模型需要大量的计算,GPU芯片是这种用例最适合的硬件。今天,NVIDIA的H100——一种高性能GPU——是大多数投资大量AI的公司的硬件选择。
对H100的需求超过了供应,尤其是像Meta这样的公司在获取它们上花费了巨额资金。我们最近报道了Meta希望到2024年底拥有350,000个H100单位。
尽管与Microsoft有着强大的合作伙伴关系并拥有大量资金,OpenAI也面临着获取足够GPU的挑战。
NVIDIA应该从需求中获得巨大利润,但我们可以期待其他玩家加大力度,设计芯片与之竞争。实际上,Meta正在构建自己的定制AI芯片,AWS也是如此。主要芯片制造商也没有闲着:AMD在2023年12月推出了MI300X处理器,早期基准测试显示其性能优于H100。Intel正在开发Gaudi3处理器,旨在与H100竞争,并计划在2024年晚些时候推出。
尽管有新GPU进入市场,但扩大大规模生产还需要更多时间。AI领域的公司可能在未来一两年内仍然可以预期GPU的稀缺。
由于硬件稀缺而导致的工程挑战往往会导致巧妙的解决方案。今天,由于云提供商的存在,几乎没有软件工程师熟悉硬件稀缺,因为没有计算或存储容量的短缺。如果需要更多的CPU或存储,问题是它将花费多少,而不是是否有容量可用。
同时,我们之前也看到了行业范围内硬件稀缺的挑战。这样的约束促使工程师提出巧妙的效率胜利。例如,虚拟化诞生于更好地利用硬件资源的努力,正如我们在《现代后端实践的过去和未来》中所涵盖的那样。
我希望看到OpenAI等公司因必要而产生的更多巧妙解决方案,这将导致即使是更复杂的AI应用也需要更少的计算。我对应用AI应用带来的未来感到兴奋,但希望实用的AI应用不需要消耗比当前计算基础设施多几百倍的能源来运行的计算基础设施。计算机是高效的机器,可以用相对较少的能源完成大量工作。希望我们保持这种方式,即使在构建更好、更有能力的AI应用的竞赛中也是如此。