探索LLM推理的延迟/吞吐量和成本空间

在这里插入图片描述

Source: https://www.youtube.com/watch?v=mYRqvB1_gRk

时间:2023年10月25日

核心内容

  • 关键指标总结

  • 吞吐量:指每秒可以处理的查询数,目标是最大化批处理任务的吞吐量。

  • 延迟:衡量生成每个token所需的时间,反映系统响应速度。目标是尽可能降低延迟。应低于每分钟250个字。

  • 成本:成本越低越好。

  • 解码过程的关键因素

  • 参数量:以70亿参数的模型为例,推理过程需执行约2P x 批量大小的浮点运算(FLOPS)。

  • 内存加载:执行浮点运算过程中,需要将整个模型参数加载到GPU内存中,涉及的内存移动量与批量大小无关,但加载时间与模型大小和内存带宽有关。

  • 批量大小:在A100 GPU上,硬件可实现的总FLOPS乘以2再除以内存带宽的结果约为400,批量大小在此范围内非常关键,过低会导致计算能力浪费,过高则会增加延迟。

  • LLaMA模型示例分析

  • 模型内存计算:LLaMA模型的内存使用为14GB(70亿参数,FP16)。还需考虑KV缓存,实际内存需求随序列长度和批量元素的增加而变化。

  • 最大批量大小:在24GB内存的A100 GPU上,最大批量大小约为5,而在80GB内存的A100上,最大批量大小约为33,均远低于400。这表明实际推理过程受到内存带宽的限制。

-----

  • 1. 分组查询注意力(Grouped Query Attention)

  • 方法:减少KV缓存大小,通过一个键值对关联一组查询。

  • 应用:LLaMA 2中使用,适用于更大规模的模型。

  • 效果:浮点运算次数不变,内存成本减少四分之一。

  • 2. 量化(Quantization)

  • 方法:使用INT8或INT4版本的模型。

  • 应用:LLaMA发布后出现的现成解决方案。

  • 效果:

  • INT8:模型大小减半,计算速度提高约1.5倍,KV缓存内存增加,加载时间减少。

  • INT4:模型大小减少到四分之一,有些性能损失,但可通过技术恢复。

  • 3. 分页注意力(Paged Attention)

  • 方法:在GPU内存中分配块,而不是固定的矩形内存。

  • 应用:由伯克利的vLLM团队开发。

  • 效果:更好的内存分配粒度和控制,减少内存浪费。

  • 4. 滑动窗口注意力(Sliding Window Attention)

  • 方法:训练模型只使用缓存中的过去K个token。

  • 应用:在Mistral中实现。

  • 效果:允许固定大小的缓存,缓存位置无关紧要,易于实现且效果好。

  • 5. 连续批处理(Continuous Batching)

  • 方法:将预填充阶段的token与解码token一起批处理。

  • 应用:改进vLLM和TGI中的批处理效率。

  • 效果:更有效地分配资源,减少延迟。

  • 6. 代码优化

  • 方法:减少Python代码的开销,使用CUDA Graphs、TensorRT LLM、和自定义内核。

  • 应用:Xformers仓库的例子和NVIDIA的TensorRT LLM。

  • 效果:减少内存带宽使用,提高推理速度。

-----

我将分享一些我在理解模型推理重要性方面获得的有价值洞察。本次演讲的主要内容源自我在网上搜集的资料,以及通过对第一代LLaMA模型和最新Mistral模型的实验所得出的结论。我们一直更注重推理成本而非训练成本。这次演讲将详细介绍推理成本的构成要素,如何平衡吞吐量和延迟,以及这些因素为何至关重要。

在这里插入图片描述

首先,让我们了解一下背景。现在,很多人都想部署大型语言模型。在这次讨论中,我将为大家介绍如何使用开源工具来部署自己的大型语言模型。当然,使用现有的优质公共API也是一种选择,这完全取决于你的需求。我今天要重点讲的是如何部署一个拥有70亿参数的模型,我们将深入探讨这个过程中的关键要点。尽管我的大部分内容也适用于规模更大的模型,但要注意,更大的模型需要更多的GPU资源,同时还有一些额外的注意事项。我会提供一份详细的参考资料,涵盖所有这些细节。不过,我在演讲中展示的大部分信息应该都是通用的。

我们首先会讨论需要关注的关键指标,然后深入分析在硬件和软件层面上影响这些指标的各种因素。接下来,我将介绍一些可以优化性能的技巧。据我了解,有些技巧还没有被广泛应用,但也有很多已经在实践中得到了采用。为了给大家提供一些具体的参考,我昨天特意在不同的硬件平台上运行了一些模型,收集了一些数据。我认为这些实际的例子会让我们的讨论更加生动和有说服力。我会详细分析这些数据,最后对整个内容进行总结。

首先,让我们来看看我们需要关注的关键指标。

第一个是吞吐量,即每秒可以处理的查询数。我们的目标是最大化批处理任务的吞吐量,或者说,让更多用户能够同时使用我们的服务。

第二个是延迟,我们用生成每个token所需的时间来衡量。这个指标反映了系统生成下一个token需要多少秒,直接决定了用户感受到的应用程序响应速度。以ChatGPT为例,它的响应速度相当快。一般来说,模型越小,越容易实现这种快速响应。我们的目标是尽可能降低延迟,以提升用户体验。一个不错的参考标准是每分钟250个字,这大约是普通人的平均阅读速度。只要你的系统能够保持低于这个速度的延迟,用户就不会感到等待的无聊。

最后一个指标是成本:显然,越经济实惠越好。

在这里插入图片描述

接下来,我们将深入探讨影响这些指标的关键因素。在接下来的讨论中,我将主要聚焦于解码过程中最具挑战性的部分,也就是我们将一批token输入网络,以推断出下一批token的过程。需要说明的是,我们这里不讨论查询初始处理阶段,也就是通常被称为“预填充”(prefill)的部分。在预填充阶段,我们会一次性将大量token输入网络。这个阶段的处理通常已经相当优化,因此挑战相对较小。

在这里插入图片描述

考虑到这一点,我们将重点关注参数量为P的模型推理过程。为了便于讨论,我们可以假设P是70亿,这是一个我们比较喜欢的模型规模。在进行一次推理时,我们大约需要执行2P x 批量大小的浮点运算。这里的浮点运算次数,我们用“FLOPS”(每秒浮点运算次数)来衡量。在执行这些浮点运算的过程中,我们需要将整个模型加载到GPU的实际运算部分。这意味着我们需要一次性将全部模型参数转移到GPU内存中,这大约相当于模型参数量的数据移动。

在这里插入图片描述

这两个量的有趣之处在于:第一个量受硬件FLOPS(GPU每秒可执行的浮点运算次数)的限制,并且与批量大小呈线性关系。而内存移动量通常不会随着批量大小的变化而改变,除非你使用了非常大的批量。不过正如我之前所说,这种情况下的处理已经相当优化了,所以我们不太关注它。那么这就是一个固定的量,即模型大小 / 内存带宽,这代表了将所有数据加载到内存所需的最短时间。而且,你每次推理都需要重复这个过程。

例如,在A100 GPU上,硬件可实现的总FLOPS乘以2再除以内存带宽,这个值约为400。

这个批量大小非常关键,因为在此之下,我们几乎是在浪费计算能力。此时我们受内存带宽限制,只能等待数据加载到GPU上,而计算速度过快。图表中的延迟部分在这个范围内保持恒定。如果超过这个批量大小,延迟开始增加,我们就受到计算能力的限制。正好在这个批量大小下,延迟最优,因此用户体验也最佳。同时我们也没有浪费任何计算资源,所以付出的成本是合理的。

然而,这个理想的批量大小400看起来相当大。让我们以LLaMA模型为例进行一些计算。它有70亿参数,虽然与Mistral有所不同,但我们就以LLaMA为例。它有4K的维度和32层。模型使用的内存大小计算很简单:每个模型权重在FP16中占两个字节,所以是2乘以7,总共14GB内存。然后我们还有KV缓存(KV Cache)。KV缓存用于存储计算结果,以便在解码新token时不必重复所有计算。KV缓存的大小是2(因为有key缓存和value缓存),在FP16下再乘以2。每层都有一个KV缓存,我们必须为批量中的每个元素保存每个位置的token,再乘以维度。

在这里插入图片描述

将实际数据代入这个公式,对于最大序列长度为4K的批量元素,大约需要2GB的内存。在有24GB内存的A100 GPU上,最大批量大小约为5,这并不多。即使在内存为80GB的更大A100上,最大批量大小也只有约33,远低于400。这似乎表明,在实际使用7B模型进行推理时,我们的解码将严重受限于内存带宽。这也印证了我们在Mistral从一开始就非常关注的一点:模型和KV缓存的内存大小确实影响允许的最大批量大小,而这个最大批量大小决定了效率。

现在我将深入探讨一些已经使用过的技巧,这些技巧非常有效且值得借鉴。其中一些已经在Mistral中实现,一些在部署软件层面实现,还有一些尚未在Mistral中实现。

**分组查询注意力(Grouped Query Attention)**是一种通过使用更少的查询、更少的键值对来减少KV缓存大小的方法。这种方法在LLaMA 2中使用,但仅适用于更大规模的模型,而不适用于7B模型。在标准的多头注意力中,查询数量与键值对数量相等。而在分组查询注意力中,一个键值对关联一组查询。在Mistral中,我们每个键值对使用四个查询,因此浮点运算次数保持不变,但内存成本只有四分之一。这是一个简单的技巧,不影响性能,所以非常值得使用。

**量化(Quantization)**是另一种技术。我们没有专门研究它,但它发展迅速,尤其是在LLaMA发布后,出现了许多优秀的现成解决方案,用于提供INT8或INT4版本的模型。使用INT8,你可以将模型大小减少一半;使用INT4,可以减少到四分之一。这不会改变最佳批量大小,因为比例只取决于硬件,与其他因素无关。在计算速度方面,理论上应该提高约2倍,但实际上很难达到这个速度。对于我们的模型结构,更合理的期望是提高约1.5倍。使用INT8,你也可以机械地增加KV缓存的可用内存,并且加载模型到内存的时间会立即改善。如果你处于内存受限的状态,一切都会快两倍,这是非常不错的提升。使用INT8几乎没有精度损失,一切似乎都能正常运行。使用INT4会有一些性能损失,但通过QLoRA等技术或仅关注特定用途,可以恢复性能。

**分页注意力(Paged Attention)**是由伯克利的vLLM团队开发的另一个好技巧。如果没有分页注意力,KV缓存是矩形的:你分配一个大的矩形内存,其中一个维度是批量大小(模型一次可以处理的最大序列数),另一个维度是允许用户使用的最大序列长度。当一个新序列进入时,你会为这个用户分配整行内存,这浪费了大量宝贵的设备内存。

分页注意力在GPU内存中分配块。首先加载模型,这样就知道剩余的空间,然后用内存块填充这些空间。这些块可以包含最多16或32个token。当一个新序列进入时,你分配所需数量的块用于提示,并根据需要增长。这些序列不一定分配在连续的块上,但这无关紧要。这允许更好的内存分配粒度和控制。

我们在Mistral中添加的一个技巧是滑动窗口注意力(Sliding Window Attention)。我们训练模型只使用缓存中的过去K个token。这非常好,因为它允许我们拥有一个固定大小的缓存。一旦序列增长超出滑动窗口token数,我们可以在缓存中循环并开始覆盖。缓存中的位置无关紧要,因为所有与位置相关的信息都通过位置嵌入编码,因此很容易实现并且效果很好。

另一个技巧是连续批处理(Continuous Batching)。预填充阶段同时处理的token比解码阶段多,因此你可以尝试将这些token与解码token一起批处理。我在vLLM和TGI中注意到的一点是它们没有分块预填充。如果一个用户发送一个包含4K token的提示,它会增加所有人的延迟,因为我们会一次性处理很多token,这是浪费。分块预填充,即每次只处理K个token,可以更好地分配资源,更有效地批处理解码和预填充。

在这里插入图片描述

代码优化在这些规模的模型中也很重要。Python代码的开销很大。有一些方法可以在不失去太多Python优势的情况下减少开销。Xformers仓库提供了一个很好的例子,使用CUDA Graphs来实现零开销。NVIDIA一直在预告它们的TensorRT LLM,这是另一种通过模式匹配自动加快推理速度的方法。你还可以使用恰当的自定义内核,如融合操作来减少内存带宽使用,这样就不必在内存中来回移动数据,可以在数据已经加载时进行激活等操作。通常,你可以在网上找到这些方法并直接使用。

总的来说,影响吞吐量和延迟的关键因素是硬件的固定浮点运算次数与内存带宽比。这给我们一个最小批量大小 ( B^* ) ,可以避免浪费浮点运算能力。这个值仅取决于硬件,与模型无关,除非你使用的是非Transformer的特殊架构。我们受限的设备内存使得达到最佳批量大小并不容易。在我检查的两个开源模型部署库中,它们仍在运行Python代码,这在这些规模下会带来大量开销。我还查看了FasterTransformer,它没有这种开销,但部署难度更大。

让我们谈谈吞吐量-延迟平面,这是我通常观察这些指标的方式。在这个平面中,x轴表示延迟,y轴表示吞吐量。我们希望向上和向左移动,那里代表更高的吞吐量和更低的延迟。

如果你买更好的硬件,它会使你的曲线整体移动。对于固定硬件,左下角的固定延迟状态是内存受限状态。随着批量大小增加,你会进入浮点运算受限的线性状态。

如果你购买更好的硬件,它会花费更多,但整体性能会向上和向左移动,这可能有意思也可能无关紧要。

如果你得到更好的代码或更好的模型,大部分改进会在低吞吐量状态下发生,你会看到吞吐量的增加。在大批量大小下影响较小,因为这些情况已经很容易优化。

在这里插入图片描述

我要说明一些示例结果和免责声明:这些结果是我昨天匆忙完成的,因为我已经预先准备好了Mistral和Llama模型。这个过程很简单,然后我运行了vLLM的基准测试脚本。我不能确定这些结果是否是我们能得到的最佳结果,但我认为它们的趋势是正确的。我复制了Matplotlib生成的图表,所以看完之后你可能会觉得有点眼花缭乱。

在这里插入图片描述

这里展示的是Mistral与Llama的对比。仅仅是GQA(分组查询注意力)的改变,就使我们在vLLM上获得了约1.5倍的吞吐量提升,图中的黑色条表示人类的平均阅读速度。

在这里插入图片描述

这张图展示的是硬件的对比,即A10与A100在运行相同模型时的表现。我们可以看到,尽管A100价格昂贵得多,但它的速度也非常快,所以升级硬件而不是购买更多旧硬件可能是值得的。

总结一下,使用开源代码在小规模实例上运行小型模型真的很容易。它无需任何特殊操作就能很好地工作。我估计,我可以让Mistral 7B模型在A10上每天处理100万次请求,成本大约15美元,这并不算高。如果改变精度,处理的请求数量几乎可以翻倍。开源部署解决方案在易用性方面做得非常出色。我认为在实际模型代码部分还有很多优化空间,我已经提到了许多已经实现或即将实现的技巧。因此,我相信大家的运行速度会越来越快,这是一个好趋势。

问题:如何为特定模型选择最佳处理器?在什么情况下我们应该使用像SambaNova这样的专用AI加速器系统?

我个人还没有测试过专用的AI硬件,仅测试了一些GPU。我甚至没有在自己的MacBook上运行过任何模型,因为目前还没有发现这么做的必要性,不过将来可能会尝试。我认为,对于普通用户来说,如果只是想与模型进行对话,在MacBook上运行可能是更经济的选择。我之前提到的最低配置要求是在A10 GPU上每天处理一百万次请求,大约需要15美元。如果你能承受每天15美元的成本,那么可以考虑这个方案,因为部署过程相当简单,而且效果也不错。至于选择什么样的硬件,我的建议是从最经济实惠的配置开始,如果无法达到所需的吞吐量或速度,再逐步升级硬件配置。这种方法可以帮助你找到最适合自己需求的硬件方案,同时避免不必要的过度投资。

问题:为什么公司认为开源LLM具有战略意义,特别是考虑到你们刚刚这样做了?背后的逻辑和考虑是什么?

我们认为我们开发的这个7B参数模型性能优秀,而且非常有潜力。同时,我们还有很多其他正在进行的项目。开源这个模型能让社区在我们的工作基础上进行更多的创新和开发。这种策略对Llama模型来说效果显著,它的使用量大幅增加。我之前提到的量化工作,以及所有这些优秀的部署方法,实际上都因为开源而得到了极大的推动。开源使得部署高质量模型变得非常容易。比如Llama.cpp项目让人们可以在Mac上运行模型,这真的是一个很棒的进展。

问题:为了减少Python的开销,你推荐使用Mojo吗?你有没有尝试过?

完全没有。我首次尝试减少开销时选择了CUDA Graphs。虽然当时调试起来有些棘手,但现在情况已经改善很多,我认为XFormers的案例是一个很好的示范。此外,我也认为在某些情况下,Torch.compile可能是一个不错的选择。虽然我不清楚他们在可变序列长度等方面的最新进展,但我现在确实推荐首先尝试CUDA Graphs。

问题:选择最佳处理器用于特定模型的最佳方法是什么?

我通常会按照成本和可用性递增的顺序进行尝试。例如,我提到的一个观察是,从成本效益的角度来看,使用A100比使用多块A10更为划算。然而,问题往往在于处理器的可用性。因此,我会根据成本和可用性递增的顺序进行尝试。如果你尝试20分钟,成本相对较低。这大约是运行基准测试所需的最大时间,之后你就能得到针对你用例的确切成本和性能数据,我认为这样更为合理。

问题:如果我们希望LLM具备多语言能力,比如理解法语,最有效的策略是什么?目前,数据集主要是英文的,所以使用非英文数据进行微调效果不佳。

任何赋予LLM新能力的方法都与数据密切相关。第一步是获取目标语言的数据。我认为所有的LLM都是在维基百科上训练的,这是一个很好的基础,因此,例如,即使没有太多的努力,模型也可以说一些法语。让它们更加多语言化是有权衡的;只要你开始让它们在法语方面变得更好,它们在其他语言方面的表现就会有所下降。也许不是特别明显,但如果你的目标是针对基准测试,你可能会在英语方面失去0.1%的表现,但在其他语言方面获得10%的提升。首先,获取一些多语言数据,然后在此基础上进行训练。如果你在英语方面损失了0.1%,这可能不算太糟糕,因为你在其他语言方面会有很大的提升。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值