跳至内容

Llama 的推理特性

作者: Aman Sanger归入研究

关于推理数学的入门指南,以及对 Llama 出乎意料成本的剖析。

Llama-2-70B 是一个颇具吸引力的 GPT-3.5 替代方案,但如果你在寻找低成本的语言模型,可能并不值得偏离 OpenAI 的 API。

在权衡价格与延迟时:

对于以补全为主的负载,不应使用 Llama-2 来提供服务

相较之下,Llama 最适合以提示为主导的任务,例如分类。当出现以下情况时,选择 Llama‑2 也可能合理:

  1. 你的工作负载没有提示令牌(看起来不直观,但我们稍后会解释)
  2. 你正在执行批处理作业

否则,GPT-3.5 通常更便宜且更快。

先简单声明一下:选择 Llama 而非 GPT-3.5 的一个理由是微调 1。不过在这篇文章中,我们只讨论成本和延迟。我没有将 Llama-2 与 GPT-4 对比,因为它更接近 3.5 级别的模型。基准测试结果也支持这一点:

Figure 1: GPT-3.5 dominates Llama in all benchmarks here.
Figure 1: GPT-3.5 dominates llama in all benchmarks here.

我将通过在延迟大致相近的情况下,对比提供 Llama-2-70B 与 GPT-3.5-turbo 的成本来证明这些论断。我们在两块 80GB 的 A100 GPU 上部署 Llama,因为这是在内存中容纳 Llama(16 位精度)所需的最低配置 3。

在 2×A100 上,我们发现 Llama 的补全 token 定价比 GPT-3.5 更不划算。我们推测在 8×A100 上可能具有竞争力的定价,但代价是不可接受的高延迟。

另一方面,就提示令牌而言,Llama 的成本比 GPT-3.5 低超过 3 倍。

Transformer 数学入门

通过一些简单的数学,我们将针对 Llama-2 展示如下结论。对于序列长度为NN、批量大小为BB的情况:

每个 token 的 FLOPS=140109 FLOPs\text{每个 token 的 FLOPS}=140⋅10^9 \text{FLOPs}
每个 token 的内存带宽=140 GB/s+320NB KB/s\text{每个 token 的内存带宽} = 140 \text{ GB/s} + 320⋅N⋅B \text{ KB/s}

140140源自模型参数数量的两倍,320 KB/s 则通过一些算术推导而来。下一节我们将解释这些数值的推导过程。

还有其他论文和/或博文非常出色地讲解了 Transformer 的数学原理。对于推理,Kipply 的文章是很好的参考。此外,我认为 Scaling Laws 推广了用于计算 Transformer FLOPs 的简化公式。

为验证这些数值,我们从 Llama 的架构细节开始。隐藏维度为 4096,注意力头数量为 64,层数为 80,每个注意力头的维度为 128:

dmodel=4096d_{model}=4096
nh=64n_h=64
nl=80n_l=80
dhead=128d_{head}=128

计算模型 FLOPs

一次前向传播的 FLOPs 数量为2P≈2P,其中PP是模型中的参数数量。我们模型中的每个参数都属于某个权重矩阵MRm×nM∈R^{m×n},并且对于每个输入 token,每个矩阵都会与表示该 token 的向量进行一次矩阵乘法,且仅使用一次。

对于每个MM,我们用一个维度为xx的向量在左侧相乘mm。该向量-矩阵乘法的总 FLOPs 为2mn62mn 6,即权重矩阵条目数的 2 倍。Transformer 中所有权重矩阵的总条目数即参数总数PP,从而在不计注意力的情况下,总 FLOPs 为2P2P

对于像 Llama 这类在(相对)较短序列上运行的大型模型,注意力机制对 FLOPs 的贡献可以忽略不计。对于每一层和每个注意力头,注意力操作为:

softmax(QTKdhead)V\text{softmax}\left(\frac{Q^T K}{\sqrt{d_{\text{head}}}}\right) V

QTKQ^TK需要将一个dheadd_{head}向量与一个dhead×Nd^{head}×N矩阵相乘,需要2dheadN2dheadN次 FLOPs。缩放因子和 Softmax 可忽略不计。最后,将 Attention 向量与VV相乘还需要额外的2dheadN2d_{head}N次 FLOPs。对所有注意力头和层求和,我们得到4dmodelnlN=1.3N4⋅d_{model}⋅nl⋅N=1.3⋅NMFLOPs。因此,对于我们最大的 8192 序列,注意力仍只占 140 GFLOPs 总量中的 10.5 GFLOPs。其占比足够小,为简化起见可忽略。

补全所需内存高于提示所需内存

在生成令牌时,我们需要为每个令牌重新读取模型的全部权重以及 KV 缓存。这意味着什么?要执行任意矩阵乘法,我们必须把每个矩阵的权重从 RAM 加载到 GPU 的寄存器中。当独立矩阵足够多时,真正的瓶颈变成了权重的加载,而不是矩阵乘法本身。那么让我们对比一下一个令牌在模型中的路径:用于提示(prompts)时与用于补全(completions)时分别如何。

通过 Transformer 生成 Token 的记忆路径

为说明这一点,我们可以沿着一个(非常粗略勾勒的)简单单层 Transformer 在生成一批 token 时的流程来进行讲解:

  1. 我们读取输入嵌入矩阵,WeW_e并为批次中的每个输入计算对应的嵌入向量。
  2. 我们从内存中读取每个Wq,Wk,WvW_q,W_k,W_v矩阵,为批次中的每个输入计算qi,ki,viq_i,k_i,v_i(向量)。
  3. 我们执行注意力操作——该过程需要读取已缓存的键和值。这会为每个输入返回一个向量。
  4. 我们从内存中读取WoW_o,并与上一步的输出相乘
  5. 我们读取第 1 步的输出并将其与第 4 步的输出相加,然后执行 layernorm。
  6. 我们读取Wff1W_{ff_1}并进行乘法,得到第一层前馈网络的输出。
  7. 我们读取Wff2W_{ff_2},并进行乘法以得到第二个前馈层的输出。
  8. 我们读取第 5 步的输出并将其与第 7 步的输出相加,然后执行 layernorm。
  9. 我们读取反嵌入层,WeTW_{e}^{T}然后进行矩阵-矩阵相乘,以获得批次中每个输入的 token 对数概率。
  10. 我们对下一个令牌进行采样,并将其反馈到第 1 步。

来逐一计算内存需求。在第 1、2、4、6、7 和 9 步中,我们大致各读取一次模型的全部参数。在第 3 步中,我们读取每个批次元素的 KV 缓存。在所有步骤中,我们还会读取中间激活,但与模型规模相比可以忽略不计。因此,内存带宽需求约等于 模型权重 + KV 缓存。随着批量大小增大,除 KV 缓存外,其他内存需求基本保持不变!我们稍后会回到这个问题。请注意,这是每个 token

通过 Transformer 处理提示词 Token 的内存路径

在处理提示时,我们只读取一次模型的全部权重,但会承担注意力机制的内存开销。可以参考一批序列经过同一个 transformer 的大致流程:

  1. 我们读取输入的嵌入矩阵 We,并为批次中的每个序列计算对应的嵌入矩阵。
  2. 我们从内存中读取每个Wq,Wk,WvW_q,W_k,W_v矩阵以计算Qi,Ki,ViQ_i,K_i,V_i(它们是矩阵)
  3. 我们执行注意力操作
  4. 我们从内存中读取 Wo,并与上一步的输出相乘
  5. 我们读取第 1 步的输出并将其与第 4 步的输出相加,然后执行 layernorm
  6. 我们读取Wff1W_{ff_1}并进行乘法,得到第一层前馈网络的输出
  7. 我们读取Wff2W_{ff_2}并进行乘法,得到第二个前馈层的输出
  8. 我们读取第 5 步的输出并将其与第 7 步的输出相加,然后执行层归一化(layernorm)
  9. 我们读取反嵌入层,Wu=WeTW_u=W_{e}^{T},然后相乘以获得提示序列的 token 对数概率

在步骤 1、2、4、6、7 中,我们会读取模型的所有参数。在步骤 3,我们执行注意力算子;借助 FlashAttention,相比于读取模型权重(在合理的序列长度和批大小下),其所需的内存带宽要少得多。在所有步骤中,我们都会读取激活(activations),这些矩阵与模型规模相比可以忽略不计(同样在合理的序列长度和/或批量下)。请注意,这是针对所有 token的内存需求。

总结一下:在处理提示词时,每个 token 的内存需求显著低于生成 token 的阶段,因为对于提示,我们会在序列维度上对矩阵乘法进行批处理!

模型权重所需的内存带宽

以 16 位精度存储的模型权重将占用270=1402⋅70=140 GB 的内存。

KV 缓存所需的内存带宽

我们的 KV 缓存大小指的是在神经网络的所有层、所有注意力头中、针对所有先前的 token 所包含的全部 key 和 value 的总大小,即每个 token 和每个 batch 元素为 320 MB。

Llama 2 决定移除多头注意力。但它并未采用多查询注意力,而是使用分组查询注意力,从而提升了性能。这样一来,键和值会有 8 个头(或分组),ngng,而不是多头注意力常见的 128 个,也不是多查询注意力的 1 个。

对于NN个 token,我们的 KV 缓存大小为2ngnldheadN=1.6N1052 n_g n_l d_{\text{head}} N = 1.6 N \cdot 10^5。使用 16 位精度,即320N320NKB。给定批量大小BB,我们得到320NB320⋅NBKB。

对于补全,这会带来每个 token 的内存需求:

每个 token 的内存=140GB+320NB KB\text{每个 token 的内存}=140GB+320⋅N⋅B \text{ KB}

对于较短的序列或小批量,第一项占主导。否则,第二项会大得多。不过,由于我们只有 160 GB 内存且模型本身占用 140 GB,在我们的实验中,KV 缓存会对内存带宽施加较小的开销。

提示的内存带宽大约为:

每个 token 的内存=140N GB\text{每个 token 的内存} = \frac{140}{N} \text{ GB}

沟通开销

为简化起见,我们忽略通信开销,因为考虑模型并行会显著增加复杂度。合理假设它不会对我们的计算造成足以影响结果的额外减速(尤其是我们只在 2 块 GPU 上拆分 Llama)。

提示处理成本非常低

提示处理,亦即首个 token 出现时间(time to first token),是 Transformer 推理中效率最高的环节,相较于 GPT-3.5,你应预期价格将下降至原来的三分之一(约 3 倍降幅)。

对于参数规模为PP,提示长度为NN的模型,处理一个提示的内存需求约为2P2P字节,计算需求为2PN2PNFLOPs。由于 A100 可处理 312 TFLOPs 的矩阵乘法并提供 2 TB/s 的内存带宽,当序列长度 N>156 时,我们受限于计算。9

在 A100 上,FLOPs 利用率通常会在略低于 70% 的 MFU 处达到上限,约为 200 TFLOPs。两张 80 GB 的 A100 成本约为 $4.42/小时 10,折合为 $0.0012/秒。Llama 的 FLOPs 需求是 140 TFLOPs/每 token。根据两张 A100 的总 FLOPs,我们可以计算出每秒可生成的 token 数应为:

22001012/140109=2.86103 词元 / 秒2⋅200⋅10^{12}/140⋅109=2.86⋅10^3 \text{ 词元 / 秒}

这相当于以下价格:

$0.00042 / 每 1K 个令牌

相比 GPT-3.5 的$0.0015,这简直太划算了!准确来说,价格几乎下降了 4 倍!

延迟表现也相当不错!在我们使用 2 块 GPU、批大小为 1 的情况下,处理 512 个 token 约需 170ms,处理 1536 个 token 约需 530ms。

让我们用实际数据来验证这些说法。我们使用 huggingface 的 text-generation-inference 仓库的内部分支来测量 Llama-2 的成本与延迟。

Figure 2: Each datapoint measures a different batch size. For prompt tokens, we always do far better on pricing than gpt-3.5, but trail slightly behind on gpt-3.5's latency of 0.4s for 3.6K tokens.
Figure 2: Each datapoint measures a different batch size. For prompt tokens, we always do far better on pricing than GPT-3.5, but trail slightly behind on GPT-3.5's latency of 0.4s for 3.6K tokens.

正如我们所见,价格相比 GPT-3.5 的 $0.0015/1k tokens 显著更低!对于更长序列,我们的首 token 延迟似乎略有落后,但解决办法相当直接:将 Llama 的并行度从 2 个 GPT 提升到 8 个,将带来近 4 倍的加速,这意味着在提示场景下 Llama-2 将全面超越 GPT-3.5!

生成 tokens 既慢且成本极高

理论上,补全方面有可能获得与 GPT-3.5 相当的定价,但在实际操作中,你很可能会更吃亏。

在生成 token 时,我们会从计算受限转为内存受限。11. 假设批大小为 1,让我们确定可达到的吞吐量。

每个 80 GB 的 A100 在每块 GPU 上的峰值内存带宽为 2TB/s。不过,类似于 FLOPs 的利用率,在推理工作负载中实际可达的通常只有该值的 60–70%(约 1.3 TB/s)。由于在小批量情况下 KV 缓存可以忽略不计,我们在 2 块 A100 上的吞吐量将为:

21.31012B/s140109B/token=18.6tokens/s\frac{2 \cdot 1.3 \cdot 10^{12} \,\text{B/s}}{140 \cdot 10^{9} \,\text{B/token}} = 18.6 \,\text{tokens/s}

我们的新价格要糟糕得多。以 $0.0012/秒 来算,我们得到的成本是……

$0.066 / 每千个 tokens

对于一个相当于 GPT-3.5 水平的模型来说,这样的定价和速度糟糕透顶!但请记住之前关于批量大小的说明。我们受到内存的严重瓶颈限制,因此可以在不降低生成速度的情况下增大批量大小。批量越大,成本越低。

我们无法无限增大,因为我们的 KV 缓存最终会占满全部 GPU 显存。幸运的是,分组查询注意力(grouped-query attention)有助于缓解这一问题。对于 N 个 token、批大小为BB,且使用 16 位精度时,我们的缓存大小为3.2NB1053.2⋅N⋅B⋅105字节。以 4096 个 token 为例,批大小为 1 时约等于 1.3 GB 内存。我们的 2×A100 机器上共有 160 GB 空间。模型占用其中的 135 GB,留给 KV 缓存的仅有 25 GB。由于内存存储中还有额外低效因素,长序列情况下我们的最大批大小约为 8。

鉴于(大约)8 倍的加速,我们可以预计价格为$0.00825 / 1K tokens。这仍不如 GPT-3.5-turbo 划算,但更接近了。对于更短的序列长度(总计 1k tokens),我们应该可以把批量大小提高到 32,对应的价格为$0.00206 / 1K tokens。理论上,这与 GPT-3.5-turbo 具有竞争力。

另一种解决方案是增加 GPU 数量。通过租用 8 块 80 GB 的 A100,我们可获得 1.28TB 的内存。扣除模型权重后,剩余用于 KV 缓存的内存超过 1TB,这意味着可支持超过 512 个 token 的批大小。需要注意的是,成本并不会实际下降 512 倍,因为此时 KV 缓存占用的内存带宽是模型大小的 8 倍,因此成本下降更接近 64 倍。

投入更多算力也能解决延迟问题。GPT-3.5 大约可达到 70 TPS。将模型从 2 张 GPU 拆分到 8 张 GPU,应能把速度提升到约 74.4 令牌/秒。

在进行这项实验时,我们没有 8 块 A100 可用,但我们可以先看看在 2 块 80 GB A100 上的指标:

已测量的生成性能

Figure 3: For all datapoints, we measure price per generated tokens when generating 512 tokens.
Figure 3: For all datapoints, we measure price per generated tokens when generating 512 tokens.

根据内存带宽的计算结果,这些数字与预期相当接近。

可以看到,增大批量大小会直接带来几乎线性下降的每 1K tokens 价格成本。不过,我们与 GPT-3.5 每 1K tokens $0.002 的定价仍有不小差距——尤其在更长序列长度情况下。

批量过大会导致不可接受的延迟

以大批量运行生成可实现接近 GPT-3.5 的竞争性定价,但会显著拉长首个 token 的等待时间。随着批量增大,成本线性下降,但首 token 出现所需时间也线性增加。

批量大小为 64 时,我们的定价优于 GPT-4。但是,批量大小为 64 会带来:

  • 仅有 512 个 token,首个 token 的生成时间竟接近3 秒
  • 对于 3596 个 token,批量大小为 64 的耗时为20.1 秒

因此,相较于使用 OpenAI 的 API,Llama‑2 更适合的工作负载类型包括:

  1. 提示很长但几乎不生成任何 token —— 处理纯提示的方式非常简单。
  2. 在使用极短甚至无提示词生成 tokens 的场景下——我们可以将批量大小调至 >64,在不牺牲延迟的前提下,实现与 GPT-3.5-turbo 具有竞争力的价格。
  3. 对延迟不敏感的离线批处理作业。

要提高批处理大小,需要持续的大规模工作负载,而大多数初创公司并不具备!对大多数用户和大多数工作负载而言,使用模式极其突发。一个可行的方案当然是针对按需 GPU 进行自动伸缩,但即便如此,考虑到冷启动时间,你平均每块 GPU 也大概率只能达到约 50% 的最大吞吐量。

我们的建议是:提示密集型任务优先使用开源模型,而生成密集型任务交给像 GPT-3.5 这样的闭源模型。

量化

大多数量化方法都是有损的,这意味着会有一定的性能下降。我们很可能通过 8 位量化实现基本不输的性能,并让所有测算成本降低 2 倍!量化损失与利用率不完美大体能相互抵消,也就是说同时考虑两者后,我们预计价格将与我们的实测相近!

然而,大多数开源量化方法的目标,是便于在少量/小型消费级 GPU 上轻松部署,而非在大规模场景中优化吞吐量。

有多個開源函式庫可以在維持效能的同時,進一步優化為更低精度的量化。不過,這些函式庫的優化方向是讓模型能在少數/小型的非資料中心 GPU 上服務,而不是在大規模情況下追求高吞吐量。具體而言,它們針對低批次推論情境進行優化(主要是批次大小為 1)。即使在最佳情況下可提供 3–4 倍的加速,換算後價格仍約為 $0.017/每 1K tokens。

比特与字节

Bits and Bytes 提供(实际意义上)无损量化,这意味着性能没有差异。不过,它的主要优势是降低内存占用,而非提升速度。比如,近期的 NF4 表示法带来的加速仅体现在矩阵乘法(matmul)速度上,而不是推理吞吐量。根据经验观察,人们似乎并没有在后者方面测得加速效果。

其在更大批量场景下的可扩展性仍不明朗。

Llama.cpp

我认为 Llama.cpp 主要针对 Apple 硬件进行了优化。他们也支持 Cuda,并在推理中支持快速的 4 位精度,但我怀疑在这里使用朴素量化会导致性能显著下降。

此外,该库针对小批量场景进行了优化。

GPT-Q

GPT-Q 是另一款量化库。我尚未测试 GPT-Q,但计划这么做。希望我们在这里能看到价格降低一倍!

再次强调,该实现针对小批量场景进行了优化。此外,论文报告的超过 3 倍的加速仅适用于 3 位量化,而这对于我们的用例来说损失过大。

闭源模型究竟为何更便宜?

闭源模型有多种方法可以显著加速推理

量化

如前所述,现有多种稳健的开源量化方法——但我怀疑 OpenAI 的量化实现对大批量处理做了更优的优化。

专家混合模型(Mixture of Experts)

普遍猜测 GPT-4 采用了专家混合(Mixture of Experts,MoE)架构 15。如果 GPT-3.5-turbo 也使用 MoE,那么在相同性能水平下,你可以部署一个小得多(因此更快)的模型

推测式采样

Speculative sampling 是另一种有趣的技巧,它通过让一个较小的模型连续起草多个 token,来绕过语言模型缓慢的解码时间。16。请注意,在极限情况下,这并不会显著提升吞吐量,但可以大幅降低延迟。作为参考,这个仓库实现了它的一个简化版本。

大规模推理的高级技巧

在大规模推理时,OpenAI 很可能会做一些高级调度,例如先为一批请求的预填充分配若干个 8-GPU 节点,然后再为该批请求的生成阶段分配单个 8-GPU 节点。这样即可兼得两方面优势:既能使用大于 64 的批大小,又能保持极低的首个 Token 延迟。

结语

我们据此研究结果,制定了在 Anysphere 何时以及如何采用开源模型的决策标准。

总结一下,我们发现对于提示负载较重的任务(例如分类重排序

加入 Anysphere,与我们一起工作!

我们正在构建Cursor,一款以 AI 为先的代码编辑器。当我们从根本上重新想象开发环境时,能够着手解决大量非常有趣的问题。比如,以 OpenAI API 成本的一小部分来微调并部署模型;或者,基于 OpenAI API 设计用于创建复杂链路与智能体的全新抽象

我们是一支位于旧金山的9人小团队,并获得了 OpenAI 的支持。如果感兴趣,请联系hiring@anysphere.co

或者,如果你想聊聊语言模型的干货,欢迎在Twitter上给我发私信。

附录

下方是关于 Llama-2-70B 延迟的测量数据点表格,以及一些额外的计算指标

批量大小提示词 Token 数补全 Token 数首个 Token 延迟完成所需时间Token/秒提示阶段 TFLOPs/GPU提示阶段内存带宽/GPU提示阶段 FLOPS 利用率提示阶段内存利用率价格/每 1k 提示词 Token价格/每 1k 补全 Token

1

128

242

0.084

12.636

19.151

106.156

1.341

0.340

0.894

$0.00081

$0.06412

2

128

512

0.116

27.751

18.450

154.478

1.291

0.495

0.861

$0.00056

$0.03328

4

128

512

0.216

28.154

18.186

165.706

1.273

0.531

0.849

$0.00052

$0.01688

1

128

242

0.084

12.661

19.114

106.122

1.338

0.340

0.892

$0.00081

$0.06425

2

128

512

0.116

27.824

18.402

154.196

1.288

0.494

0.859

$0.00056

$0.03337

4

128

512

0.215

28.205

18.153

167.074

1.271

0.535

0.847

$0.00051

$0.01691

1

512

512

0.217

27.752

18.449

164.996

1.291

0.529

0.861

$0.00052

$0.06656

2

512

512

0.392

28.543

17.938

183.068

1.256

0.587

0.837

$0.00047

$0.03423

4

512

512

0.734

29.042

17.630

195.345

1.234

0.626

0.823

$0.00044

$0.01741

1

512

304

0.225

16.393

18.545

158.940

1.298

0.509

0.865

$0.00054

$0.06622

8

512

512

1.445

29.753

17.208

198.402

1.205

0.636

0.803

$0.00043

$0.00892

8

512

512

1.460

29.740

17.216

196.344

1.205

0.629

0.803

$0.00044

$0.00892

16

512

512

3.081

32.708

15.654

186.149

1.096

0.597

0.731

$0.00046

$0.00490

16

512

512

3.038

32.661

15.676

188.776

1.097

0.605

0.732

$0.00046

$0.00490

16

512

512

3.068

32.708

15.654

186.887

1.096

0.599

0.730

$0.00046

$0.00490

32

512

512

6.363

41.302

12.396

180.256

0.868

0.578

0.578

$0.00048

US$0.00310

32

512

512

6.632

41.099

12.458

172.931

0.872

0.554

0.581

$0.00050

$0.00308

1

1024

512

0.397

28.961

17.679

180.727

1.238

0.579

0.825

$0.00048

¥0.06946

1

1024

512

0.396

28.982

17.666

181.017

1.237

0.580

0.824

$0.00047

$0.06951

2

1024

512

0.732

29.674

17.254

195.759

1.208

0.627

0.805

$0.00044

$0.03559

4

1024

512

1.471

30.159

16.977

194.904

1.188

0.625

0.792

$0.00044

$0.01808

8

1024

512

3015

31.167

16.428

190.223

1.150

0.610

0.767

$0.00045

$0.00934

16

1024

512

6.541

35.111

14.582

175.325

1.021

0.562

0.681

$0.00049

US$0.00526

1

3595

512

1.430

34.210

14.966

175.929

1.048

0.564

0.698

$0.00049

$0.08205

2

3595

512

2.841

34.964

14.644

177.168

1.025

0.568

0.683

$0.00049

$0.04193

4

3595

512

5.846

35.795

14.304

172.199

1.001

0.552

0.667

$0.00050

$0.02146

1

7584

166

3.081

13.641

12.170

172.330

0.852

0.552

0.568

$0.00050

$0.10091

2

7584

512

6.296

43.482

11.775

168.642

0.824

0.541

0.550

$0.00051

$0.05214

归类于: 研究

作者: Aman Sanger