본문 바로가기
C.W.K.
Stream
Lesson 07 of 07 · published

성능과 메모리 — 무엇이 RAM을 먹고 왜 먹나

~16 min · memory, kv-cache, wired-memory

Level 0호기심
0 XP0/51 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

추론 중 통합 메모리를 쓰는 세 주인공

  1. 모델 가중치. 크게 변하지 않는 상수야. 7B Q4 모델은 약 5 GB, 70B Q4는 약 50 GB를 써. foundations.lesson4의 냅킨 계산으로 얻은 값이야.
  2. KV 캐시. 문맥 창의 모든 토큰에 대한 key와 value를 들고 자라는 버퍼야. 문맥 길이에 비례하고 층마다 더해져. 32k 문맥의 7B 모델에서는 극단적으로 모델 자체보다 커질 수 있어.
  3. 활성값 메모리. 순전파 한 번 동안 잠깐 쓰는 버퍼야. 추론에서는 KV 캐시보다 작지만 분명히 차지해.

여기에 macOS가 운영체제와 다른 앱을 위해 고정 메모리를 남겨둬. prod.lesson2에서 그 천장을 자세히 볼 거야. 여기서는 직접 통제할 수 있는 KV 캐시 크기와 측정법에 집중해.

메모리는 추측하지 말고 측정해

MLX는 mx.get_active_memory()mx.get_peak_memory()를 제공해. 앞의 값은 현재 할당된 GPU 메모리 바이트, 뒤의 값은 마지막 초기화 뒤 가장 높았던 바이트 수야. 생성 전후에 읽으면 모델, KV 캐시, 활성값이 정확히 얼마나 썼는지 알 수 있어.

사무실 Mac에서 1B Q4 시연 모델로 검증한 값은 이랬어.

  • 불러온 뒤 — 현재 약 663 MB
  • 짧은 생성 뒤 — 현재 약 663 MB
  • 200토큰 생성 뒤 — 현재 약 663 MB, 최고 약 685 MB

1B 모델의 KV 캐시는 보통 문맥 길이에서 전체 메모리를 좌우할 만큼 크지 않아. 하지만 32k 문맥의 7B 이상 모델로 커지면 가중치보다 KV 캐시가 더 중요한 숫자가 될 수 있어.

고정 메모리 천장도 있어

macOS는 GPU가 통합 메모리 100%를 잠그지 못하게 해. 기본 iogpu.wired_limit_mb가 Mac 모델별 비율에 따라 GPU가 쓸 수 있는 메모리를 제한해. 192 GB Mac Studio도 천장이 192 GB에 가깝지만 정확히 전부는 아니야. 냅킨 계산상 들어가는데 실제 생성에서 실패한다면 이 고정 메모리 한도가 흔한 원인이야. prod.lesson2에서 전체 진단을 다룰 거야.

그래서 무엇을 해야 하나

  • 가중치와 KV 캐시를 추정한 뒤 foundations.lesson3의 규칙대로 통합 메모리 약 70% 안에 들어오는 모델을 골라.
  • 긴 문맥을 쓸 때는 fp16보다 Q4처럼 더 강하게 양자화한 모델을 골라 캐시 공간을 남겨.
  • 모델이 들어간다고 선언하기 전에 mx.get_peak_memory()로 재. 냅킨 계산의 신뢰 범위는 약 ±10%이고 실제 최고값은 놀랄 수 있어.
  • 천장에 닿으면 시스템 설정부터 건드리지 말고 양자화를 더 강하게 하거나 문맥을 줄여.

Code

모델을 불러오고 생성할 때의 메모리 측정·python
import mlx.core as mx
from mlx_lm import load, generate


def mem_mb():
    return mx.get_active_memory() / (1024 * 1024)


def peak_mb():
    return mx.get_peak_memory() / (1024 * 1024)


# Reset peak counter and measure baseline
mx.reset_peak_memory()
print(f"baseline                    : active {mem_mb():.1f} MB, peak {peak_mb():.1f} MB")

model, tok = load("mlx-community/Llama-3.2-1B-Instruct-4bit")
print(f"after load                  : active {mem_mb():.1f} MB, peak {peak_mb():.1f} MB")

generate(model, tok, prompt="Hello.", max_tokens=10, verbose=False)
print(f"after short generate (10)   : active {mem_mb():.1f} MB, peak {peak_mb():.1f} MB")

generate(model, tok, prompt="Tell me a story:", max_tokens=200, verbose=False)
print(f"after longer generate (200) : active {mem_mb():.1f} MB, peak {peak_mb():.1f} MB")

# Verified output (2026-05-03, M3 Ultra Studio):
#   baseline                    : active 0.0 MB, peak 0.0 MB
#   after load                  : active 663.0 MB, peak ~675 MB
#   after short generate (10)   : active 663.0 MB, peak ~680 MB
#   after longer generate (200) : active 663.0 MB, peak ~685 MB
Mac의 GPU 고정 메모리 한계 살피기·bash
# How much unified memory total?
sysctl -n hw.memsize | awk '{ printf "Unified memory: %.1f GB\n", $1/1024/1024/1024 }'

# What's the GPU wired-memory cap (the hard ceiling for MLX kernels)?
sysctl iogpu.wired_limit_mb
# A value of 0 means "system default" — typically a fraction (e.g. ~75%) of total RAM.
# Non-zero values are explicit overrides; raising this is reckless on small Macs.

# Sample (M3 Ultra Studio, 512 GB):
#   Unified memory: 512.0 GB
#   iogpu.wired_limit_mb: 0      (using system default ceiling)

External links

Exercise

현재 Mac에서 같은 1B Q4 모델로 메모리 측정 코드를 실행해. 다음에는 mlx-community/Llama-3.2-3B-Instruct-4bit나 캐시에 있는 다른 3B Q4 모델로 바꿔 다시 돌려. 불러온 뒤 현재 메모리와 200토큰 생성 뒤 최고 메모리를 비교해. 모델이 약 세 배 크니 값도 세 배에 가까워야 해. 훨씬 더 높다면 KV 캐시가 존재감을 드러내기 시작한 거야. 측정 결과를 두 문장으로 적어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.