본문 바로가기

04. weight와 runtime memory

핵심 질문
  • GPU 메모리(VRAM)를 차지하는 것은 가중치뿐인가? 아니라면 또 무엇이 있는가?
  • "이 모델은 몇 GB짜리"라는 말은 실제 서빙에 필요한 메모리와 같은가?

목표
  • 런타임 메모리를 가중치·activation·KV·workspace·allocator 여유로 분해한다.
  • "가중치 크기"와 "실제 필요 메모리"를 구분하는 습관을 세운다.

여정에서의 위치

03장에서 decode가 memory-bound로 기우는 경향을 봤습니다. 그 "메모리"가 대체 무엇으로 채워지는지 이 장에서 분해합니다. 워커가 가중치를 GPU에 올리는 순간(01장의 여정)부터, VRAM에는 여러 손님이 자리를 잡습니다.

flowchart TB
    VRAM[VRAM 총량]:::mem --> W[가중치<br/>weights]:::mem
    VRAM --> A[activation<br/>중간 계산값]:::comp
    VRAM --> KV[(KV 캐시)]:::mem
    VRAM --> WS[workspace<br/>커널 임시 버퍼]:::comp
    VRAM --> FR[allocator 여유<br/>단편화·예약]:::danger

    classDef mem fill:#e5dbff,stroke:#7048e8,color:#000;
    classDef comp fill:#d0ebff,stroke:#1971c2,color:#000;
    classDef danger fill:#ffc9c9,stroke:#e03131,color:#000;

다섯 손님

1. 가중치(weights)

학습된 파라미터. 크기는 대략 파라미터 수 × 파라미터당 바이트 수입니다. 파라미터당 바이트는 dtype이 정합니다: FP32=4 byte, FP16/BF16=2 byte, INT8=1 byte, INT4=0.5 byte.

🔎 약어 풀이 — dtype
  • FP32/FP16/BF16: 32/16 bit 부동소수점(floating point). BF16은 FP16과 bit 수는 같지만 지수부가 넓어 큰 값에 강합니다.
  • INT8/INT4: 8/4 bit 정수. 양자화에 쓰입니다(11장).
  • 같은 파라미터라도 dtype이 절반이면 가중치 크기도 대략 절반.

2. activation(활성값)

forward pass 도중 레이어 사이를 흐르는 중간 계산 결과입니다. 배치 크기·시퀀스 길이·hidden 차원에 비례해 잠깐 생겼다 사라집니다. 학습과 달리 추론에서는 대개 활성값을 오래 붙들 필요가 적지만, prefill에서 많은 토큰을 한꺼번에 처리하면 순간적으로 커질 수 있습니다.

3. KV 캐시(KV cache)

앞 토큰들의 key/value 상태. 요청·컨텍스트 길이·동시 요청 수에 따라 커지며, 런타임에 동적으로 자라는 가장 골치 아픈 손님입니다. 다음 장(05)의 주인공입니다.

4. workspace(작업 버퍼)

커널(행렬 곱 등)이 계산 중 잠시 쓰는 임시 버퍼. 라이브러리·커널 구현에 따라 크기가 달라집니다.

5. allocator 여유·단편화(fragmentation)

메모리 할당기가 예약해 두거나, 조각나서 실제로는 못 쓰는 공간. "총 VRAM − 다른 넷 = KV에 쓸 수 있는 공간"이 깔끔하게 떨어지지 않는 이유입니다. PagedAttention(09장)이 겨냥하는 문제가 바로 KV 영역의 단편화입니다.

표로 정리

손님무엇에 비례하나성격관련 장
가중치파라미터 수 × dtype 바이트정적, 로드 시 고정11(양자화)
activation배치·시퀀스·hidden일시적, phase 의존03
KV 캐시레이어·KV head·토큰·동시요청·dtype동적 성장05·06
workspace커널·구현일시적
allocator 여유할당기·단편화낭비되기 쉬움09

⚠️ "가중치 크기 = 필요 메모리"라는 착각

"7B FP16 모델은 약 14GB니까 16GB GPU에 올라간다"는 계산은 가중치만 본 것입니다. 실제 서빙에서는 activation·KV·workspace·allocator 여유가 더 필요하고, 특히 KV 캐시가 동시 요청과 컨텍스트 길이에 따라 크게 부풀 수 있습니다. 가중치가 겨우 들어가는 GPU는 실제 요청을 몇 개 처리하기도 전에 KV 공간이 부족해질 수 있습니다.

🔬 증거 읽기 (주장 유형)
  • "가중치 ≈ 파라미터 수 × dtype 바이트"는 calculated입니다(입력과 식이 명확). 이 장에서 안심하고 쓸 수 있습니다.
  • "그래서 이 GPU에 이 모델이 몇 개 동시 요청까지 된다"는 measured/calculated 혼합이며, KV·activation·단편화 가정이 모두 명시돼야 합니다. 조건 없이 "이 GPU면 충분"이라고 단정하는 자료는 신뢰도를 낮춰 읽으세요.
⚖️ 절충(tradeoff) 미리보기
VRAM은 유한 자원입니다. 가중치를 줄이면(양자화, 11장) KV·배치에 쓸 공간이 늘지만 품질 리스크가 따라옵니다. KV를 줄이면(GQA/MLA 06장, PagedAttention 09장, prefix caching 10장) 더 많은 동시 요청이 가능하지만 각기 다른 비용을 치릅니다. 이 장은 "무엇을 줄일 후보가 있는가"의 지도입니다.

📌 핵심

  • VRAM은 가중치 + activation + KV + workspace + allocator 여유로 나뉜다.
  • 가중치는 정적이고 계산 가능(파라미터 수 × dtype 바이트), KV는 런타임에 동적 성장.
  • "가중치 크기"는 "실제 필요 메모리"의 하한도 아니다 — 나머지가 반드시 더 필요하다.
  • 각 손님을 줄이는 기법이 이후 장들의 주제(양자화·attention 변형·PagedAttention·prefix caching).

🔎 이 장의 '지지하지 않는 결론'

  • 이 장은 메모리를 분해했을 뿐, "이 GPU에 이 모델이 뜬다/안 뜬다"를 판정할 수 없습니다 — 그건 KV·배치·단편화 가정이 명시된 measured 근거가 필요합니다(범위 밖: 프로덕션 사이징).

✍️ 확인 문제

  1. VRAM을 차지하는 다섯 손님을 들고, 그중 "런타임에 동적으로 자라는" 것을 고르세요. 왜 그것이 사이징을 어렵게 만듭니까?
  2. FP16 7B 모델의 가중치 크기를 어림하는 식을 쓰세요. 이 값이 "필요 VRAM"과 같지 않은 이유 두 가지는?
  3. (조건 유형) "이 16GB GPU면 이 모델 서빙에 충분하다"는 주장이 참이 되려면 어떤 조건들이 명시돼야 합니까? 최소 세 가지.
다음 장: 05 · KV 캐시 — 동적으로 자라는 손님을 정면으로 봅니다.