TT Lab
开始
学习 学习路径 课程

LLM 服务

用手立一份显存预算

在 TT Lab 中继续学习

一句话总结

GPU内存预算有三个项目:模型权重、KV缓存和激活和开销。第二个项目最大,也是最常被忽视的。

为什么需要这个?

为了回答“A100 80GB一张可以装70B模型吗?”的问题,需要计算一下。光看权重,以fp16为基准是140GB,所以不能装。如果量化成4位,好像可以装大约35GB。但是忘了KV缓存了。

不计算后开始的话,在发布当天就会遇到OOM。而且OOM是当负载集中时出现的,所以是在最糟糕的时间点出现的。

怎么行动

模型加权是参数数量乘以dtype字节。如果是7B fp16,是14GB,如果是70B fp16,是140GB。量化的话,这个值会变小——INT8是一半,INT4是四分之一。

KV现金公式如下。

KV 바이트 = 2 x 레이어 수 x 은닉 차원 x 시퀀스 길이 x 배치 x dtype 바이트

前面2是指两个键和值的意思。以7B(32层,隐秘4096) fp16为基准计算的话是这样的。

上下文 配置1 配置8
4K 2 GiB 16 GiB
32K 16 GiB 128 GiB
128K 64 GiB 512 GiB

如果在128K上下文中分配8个,则为512GiB。转发14GB模型时,KV缓存为512GB。为什么长上下文很难,就在这张表里。

减少的方法有三个。GQA将键值头以组共享,8组的话减少到8分之一。KV缓存量化减少dtype字节,如果是INT8的话是一半,如果是INT4的话是四分之一。PagedAttention虽然大小本身没有减少,但减少了碎片化,提高了实际使用效率。

叠加这些的话可以节省很多。从作者的例子来看,基本1,280GB变为GQA-8为320GB,INT8为160GB,PagedAttention实际使用标准约为128GB,INT4的话为80GB。

在现场相遇的样子

在实际工作中,最经常需要计算确定同时请求数量。从GPU总内存中减去权重和开销后,就会得出KV缓存预算,将其除以每个请求的KV大小,就会得出最大同时请求数量。这个值是max_num_seqs是限额,也是容量计划的起点。

量化选择也从这个计算中得出。GPTQ和AWQ只量化权重,KV缓存量化是单独设置的。如果混淆这两个,就会说“换成了4位,内存没有明显减少”——因为在语境较长的工作负载中,KV缓存占主导地位。

制定预算的办法

GPU内存分为三个部分。按顺序计算的话,可以同时处理的请求数量是 出来了。

1. 가중치 = 파라미터 수 × (비트수 ÷ 8)
   7B × 2바이트(FP16)  = 14.0 GB
   7B × 0.5바이트(INT4) =  3.5 GB

2. 여유 = 활성화 + 단편화 ≈ 전체의 5~10%

3. KV 캐시로 쓸 수 있는 몫 = 전체 − 가중치 − 여유

KV现金一个令牌所消耗的大小是这样的。

토큰당 = 2(K와 V) × 레이어 수 × KV 헤드 수 × 헤드 차원 × 정밀도 바이트

예: Llama-3 8B (32레이어, KV헤드 8, 헤드차원 128, FP16)
    = 2 × 32 × 8 × 128 × 2 = 131,072 바이트 ≈ 128 KB/토큰

GQA(Grouped-Query Attention)在这里造成了很大的差异。如果KV头有32个的话 虽然是512KB/令牌,但8个是128KB。最近型号使用GQA的原因就是这个。

24GB 카드, 8B 모델 FP16:
  가중치 16GB + 여유 2GB → KV 로 6GB
  6GB ÷ 128KB = 약 49,000 토큰
  → 문맥 4K 면 동시 12요청, 문맥 8K 면 6요청

这个计算告诉我们的东西

溢位的时候会发生什么事呢?

如果KV不足,vLLM会先占用(preemption)。选择一个正在进行的请求 扔掉现金,以后从头重新计算。

로그: Sequence group ... is preempted by PreemptionMode.RECOMPUTE

如果经常看到这个日志,说明同步性超过了容量。延迟会增加,GPU使用率 因为写得很高,很容易误读为“正在好好使用”。以抢先使用次数为指标 这是识别这种状态的方法。

下次实验要做的事情

将公式实现为代码,计算多个场景。验证7B 4K为2GiB,计算128K,应用GQA和INT8,最后在80GB GPU上计算出可能的最大同步请求数。