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 는 4분의 1 수준입니다.

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분의 1 수준으로 줄입니다. KV 캐시 양자화는 dtype 바이트를 줄여 INT8 이면 절반, INT4 면 4분의 1 입니다. 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요청

이 계산이 알려 주는 것

넘쳤을 때 무슨 일이 일어나나

vLLM 은 KV 가 부족하면 선점(preemption) 합니다. 진행 중인 요청 하나를 골라 캐시를 버리고, 나중에 처음부터 다시 계산합니다.

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

이 로그가 자주 보이면 동시성이 용량을 넘은 것입니다. 지연이 튀는데 GPU 사용률은 높게 나와 "잘 쓰고 있다" 로 오독하기 쉽습니다. 선점 횟수를 지표로 두는 것 이 이 상태를 알아채는 방법입니다.

다음 실습에서 할 것

공식을 코드로 구현하고 여러 시나리오를 계산합니다. 7B 4K 가 2GiB 임을 검증하고, 128K 를 계산하고, GQA 와 INT8 을 적용하고, 마지막에 80GB GPU 에서 가능한 최대 동시 요청 수를 구합니다.