견적서에 H100 8장이 적혀 있어요. 왜 8장이냐고 물으면 "32B 모델이면 넉넉히 잡아야죠"라는 답이 돌아오고, 다른 쪽 견적서에는 같은 모델에 2장이 적혀 있어요. 둘 다 근거를 못 대니 결정이 안 나요.
고객사 이야기가 아니라 폐쇄망 LLM 도입 검토에서 자주 보는 장면이에요. 저희가 이 자리에서 꺼내는 건 숫자 세 개예요. 가중치 크기, 토큰당 KV 캐시, 동시 요청 수 × 컨텍스트 길이. 이 셋이면 GPU 몇 장인지는 한 줄 계산으로 나와요. 공개 모델 두 개로 직접 계산해 봤어요.
가중치는 들어가는데 사용자는 못 들어가요
GPU 메모리를 먹는 건 셋이에요. 모델 가중치, 요청마다 쌓이는 KV 캐시, 계산 중간값이 머무는 작업 공간이에요. 가중치는 파라미터 수에 바이트를 곱하면 끝이라 다들 여기까지는 계산해요. 32.8B 인 Qwen3-32B 를 BF16(2바이트)으로 올리면 65.6 GB, 80 GB 짜리 H100 한 장에 들어가요. 그래서 "1장이면 되겠네"가 돼요.
문제는 KV 캐시예요. 모델이 앞 토큰을 다시 읽지 않으려고 토큰마다 키와 값을 저장해 두는데, 이건 요청이 늘 때마다, 토큰이 늘 때마다 자라요. NVIDIA 기술 블로그의 공식은 토큰 하나당 2 × 레이어 수 × KV 헤드 수 × 헤드 차원 × 바이트예요. Qwen3-32B 의 config.json 을 열면 레이어 64, KV 헤드 8, 헤드 차원 128 이니 2 × 64 × 8 × 128 × 2바이트 = 262,144바이트, 토큰 하나에 256 KiB 예요.
컨텍스트 32K 를 꽉 채운 요청 하나가 8.6 GB 를 들고 있는 거예요. 서빙 엔진은 GPU 를 다 쓰지도 않아요. vLLM 기본값은 메모리의 92% 까지만 잡으니 예산이 73.6 GB 고, 작업 공간 2 GB 를 빼면 KV 에 남는 건 6 GB 예요. 32K 요청은 한 개도 못 들어가요.
두 장을 사기 전에 FP8 을 먼저 켜요
견적서의 장수 차이는 대부분 가중치 정밀도와 동시 요청 가정의 차이예요. 말로 다투는 대신 표로 만들기로 했고, 공개 공식만 쓰니 열 줄이면 돼요.
GB = 1e9
layers, kv_heads, head_dim = 64, 8, 128 # Qwen3-32B config.json
params = 32.8e9
budget = 80 * 0.92 - 2.0 # vLLM 기본 92%, 작업 공간 2 GB 가정
def kv_per_token(kv_bytes): # NVIDIA 블로그 공식
return 2 * layers * kv_heads * head_dim * kv_bytes
for w_bytes, kv_bytes in [(2, 2), (1, 2), (1, 1), (0.5, 1)]:
kv_budget = budget - params * w_bytes / GB
per_req = kv_per_token(kv_bytes) * 32_768 / GB
print(w_bytes, kv_bytes, round(kv_budget, 1), int(kv_budget // per_req))
이걸 돌리니 "몇 장"이 아니라 "몇 명"이 먼저 나왔어요.
| Qwen3-32B, H100 80 GB | 가중치 | KV 예산 | 8K 요청 | 32K 요청 |
|---|---|---|---|---|
| 1장 · BF16 가중치 · BF16 KV | 65.6 GB | 6.0 GB | 2개 | 0개 |
| 1장 · FP8 가중치 · BF16 KV | 32.8 GB | 38.8 GB | 18개 | 4개 |
| 1장 · FP8 가중치 · FP8 KV | 32.8 GB | 38.8 GB | 36개 | 9개 |
| 1장 · INT4 가중치 · FP8 KV | 16.4 GB | 55.2 GB | 51개 | 12개 |
| 2장 텐서 병렬 · BF16 가중치 · BF16 KV | 65.6 GB | 77.6 GB | 36개 | 9개 |
| 2장 텐서 병렬 · FP8 가중치 · FP8 KV | 32.8 GB | 110.4 GB | 102개 | 25개 |
한 장에 FP8 가중치와 FP8 KV 캐시를 켠 줄과, 두 장에 BF16 으로 올린 줄이 같은 숫자예요. GPU 한 장 값이 정밀도 설정 하나와 맞먹는 거예요. vLLM 은 --kv-cache-dtype fp8 로 KV 캐시 정밀도만 따로 낮출 수 있고, 보정 데이터셋으로 스케일을 잡는다고 문서에 적혀 있어요. 그래서 저희 순서는 장수를 늘리는 게 아니라 정밀도를 낮추고, 그 모델이 골든셋을 통과하는지 먼저 보는 쪽이에요. 양자화한 모델도 "다른 모델"이라 모델 교체 평가 게이트와 같은 절차를 태워요.
117B 가 80 GB 한 장에 들어가는 이유는 아키텍처예요
파라미터 수로 GPU 를 세면 틀리는 두 번째 이유가 있어요. gpt-oss-120b 는 총 117B 인데 모델 카드가 80 GB GPU 한 장에 맞게 설계했다고 적어요. 배포된 가중치 파일 합이 65.3 GB 예요. 토큰마다 쓰이는 파라미터는 5.1B 뿐인 MoE 라 전문가 가중치를 4비트(MXFP4)로 눌렀고, 그래서 32B 모델의 BF16 가중치와 비슷한 크기예요.
KV 캐시는 더 달라요. 레이어 36, KV 헤드 8, 헤드 차원 64 라 토큰당 72 KiB 로 Qwen3-32B 의 3분의 1 이 안 돼요. 게다가 레이어 절반은 128 토큰짜리 슬라이딩 윈도라 긴 컨텍스트에서 거의 자라지 않아요. 6.3 GB 남짓한 KV 예산으로 32K 요청 5개, 128K 요청도 1개가 들어가요. 총 파라미터는 3.6배인데 긴 요청은 더 많이 받는 거예요.
올가을 나온 오픈 웨이트 모델이 대부분 이 구조예요. deepset 정리에 따르면 7월 말 이후 아홉 연구소가 모델을 냈고, Meta Muse Spark Open 은 816B 에 활성 42B, NVIDIA Nemotron 3.5 Bolt 는 74B 에 활성 9B 예요. "총 파라미터 × 2바이트"로 세면 두 배씩 틀려요. config.json 네 줄이 견적서보다 빨라요.
바로 믿으면 안 되는 세 가지
첫째, 이 계산은 들어가느냐만 답해요. 초당 토큰 수는 메모리 대역폭과 배치가 정하고, H100 SXM 의 3.35 TB/s 가 생성 속도의 천장이에요. 요청 25개가 들어간다는 것과 25명이 쓸 만하다는 건 다른 말이라 처리량은 실제 하드웨어에서 재야 해요. 저희도 이 글에서 GPU 를 돌리지 않았어요.
둘째, 작업 공간 2 GB 는 가정값이에요. 모델과 배치에 따라 달라지고 긴 프롬프트를 한 번에 처리할 때 더 커져요. 표의 요청 수는 그만큼 흔들려요.
셋째, 이 표는 PagedAttention 처럼 KV 캐시를 조각 단위로 관리하는 엔진을 전제해요. vLLM 팀은 2023년 글에서 기존 서빙 시스템이 단편화와 과잉 예약으로 KV 메모리의 60~80% 를 버린다고 썼어요. 그런 엔진이면 표의 숫자를 절반 이하로 봐야 해요.
| AS-IS | TO-BE | |
|---|---|---|
| 산정 근거 | 파라미터 수 × 2바이트, 넉넉히 두 배 | 가중치 + 토큰당 KV × (동시 요청 × 컨텍스트) + 작업 공간 |
| 조정 손잡이 | GPU 장수 | 가중치 정밀도 → KV 정밀도 → 컨텍스트 상한 → 장수 |
| 검증 | 벤더 말 | config.json 계산 → 골든셋 → 실측 처리량 |
파일럿에서 운영으로 넘어갈 때 무너지는 지점에 GPU 를 적어 둔 이유도 이거예요. 파일럿은 사용자 한 명이라 KV 캐시가 보이지 않아요. 에이전트 비용이 대화 길이의 제곱으로 붙는 것과 같은 이유로, 온프레미스에서는 그 길이가 요금이 아니라 메모리로 청구돼요.
8장과 2장 중 어느 쪽이 맞느냐로 돌아오면, 답은 "동시에 몇 명이 몇 토큰을 쓰느냐를 먼저 정하라"예요. GPU 산정은 하드웨어 문제가 아니라 사용 시나리오를 숫자로 적는 일이고, 그 숫자는 도입 뒤에도 계속 고쳐 쓰는 숫자예요.
자주 묻는 질문
Q. 폐쇄망이라 vLLM 같은 오픈소스 엔진을 못 쓰면요? A. 공식은 엔진과 무관해요. 다만 KV 캐시를 조각 단위로 관리하지 않는 엔진이면 동시 요청 수를 표의 절반 이하로 잡고, 엔진이 메모리를 몇 % 까지 쓰는지 문서에서 확인하세요.
Q. 컨텍스트를 128K 로 열어 두면 안 되나요? A. 열어 둘 수는 있지만 요청 수 계산에 최악값으로 들어가요. Qwen3-32B 는 128K 요청 하나가 34 GB 예요. 실제 사용 분포를 보고 상한을 정하고, 긴 문서는 RAG 로 자르는 쪽이 GPU 를 덜 써요.
Q. FP8 이나 INT4 로 낮추면 품질이 떨어지지 않나요? A. 떨어질 수 있어요. 그래서 "안 떨어진다"가 아니라 "우리 골든셋에서 얼마나 떨어지는지 재고 결정한다"가 원칙이에요. 슬라이딩 윈도 레이어는 KV 양자화에 민감하다고 vLLM 문서가 적어 두니 그 레이어만 제외하는 옵션부터 써 보세요.
Sources
- Hugging Face, Qwen/Qwen3-32B 모델 카드 · config.json (파라미터 32.8B, 레이어 64, Q 64 / KV 8 헤드, 헤드 차원 128, 컨텍스트 32,768 · YaRN 131,072, Apache 2.0) — https://huggingface.co/Qwen/Qwen3-32B
- Hugging Face, openai/gpt-oss-120b 모델 카드 · config.json · 파일 목록 (117B / 활성 5.1B, MXFP4, 80 GB GPU 한 장, 레이어 36 · 슬라이딩 윈도 128 교차, KV 헤드 8 · 헤드 차원 64, safetensors 합 65.3 GB) — https://huggingface.co/openai/gpt-oss-120b
- NVIDIA Technical Blog, "Mastering LLM Techniques: Inference Optimization" (KV 캐시 토큰당 크기 공식), 2023-11-17 — https://developer.nvidia.com/blog/mastering-llm-techniques-inference-optimization/
- vLLM, "vLLM: Easy, Fast, and Cheap LLM Serving with PagedAttention" (기존 시스템의 KV 메모리 60~80% 낭비), 2023-06-20 — https://vllm.ai/blog/2023-06-20-vllm
- vLLM Docs, Engine Arguments (
--gpu-memory-utilization기본 0.92,--kv-cache-dtype) — https://docs.vllm.ai/en/stable/configuration/engine_args.html - vLLM Docs, Quantized KV Cache (FP8 E4M3 / E5M2, 보정 스케일, 슬라이딩 윈도 레이어 제외 옵션) — https://docs.vllm.ai/en/stable/features/quantization/quantized_kvcache.html
- NVIDIA, H100 Tensor Core GPU 사양 (SXM 80 GB · 3.35 TB/s, NVL 94 GB) — https://www.nvidia.com/en-us/data-center/h100/
- deepset, "What Are Open-Weight Models? The Latest Releases, and Why They Matter for Sovereign AI" (7월 말 이후 아홉 연구소, Muse Spark Open 816B/42B, Nemotron 3.5 Bolt 74B/9B), 2026-10-27 — https://www.deepset.ai/blog/open-source-llm-open-weight-models

