LLM 공부 06. MoE와 GPU 클러스터는 거대 모델을 나누어 실행한다
이 글의 핵심은 거대 LLM serving이 모델 계산 문제이면서 GPU memory, sharding, replication, routing을 다루는 분산 시스템 문제라는 점입니다.
여기까지 오면 LLM은 더 이상 하나의 함수처럼 보이지 않습니다.
tokenizer가 입력을 token으로 자르고, embedding이 벡터를 만들고, Transformer block이 attention과 MLP로 벡터를 갱신합니다. prefill은 긴 입력을 읽고, decode는 KV cache를 보며 token을 하나씩 씁니다. batch와 sequence length는 GPU memory와 latency를 흔듭니다.
이제 질문이 바뀝니다.
그 큰 모델은 실제로 어디에 올라가 있을까?
한 GPU에 다 들어가지 않는 모델은 여러 GPU에 쪼개야 합니다. 여러 사용자를 받으려면 여러 replica도 필요합니다. MoE 모델이라면 token마다 선택되는 expert가 달라지고, expert가 다른 GPU에 있으면 token을 보내고 다시 받아야 합니다.
이 지점에서 LLM serving은 신경망 문제가 아니라 분산컴퓨팅 문제가 됩니다.
MoE expert는 보통 MLP/FFN expert입니다
먼저 MoE부터 정리하겠습니다.
MoE는 Mixture of Experts의 줄임말입니다. 이름 때문에 "수학 expert", "코딩 expert", "의학 expert" 같은 주제별 전문가를 떠올리기 쉽습니다.
하지만 Transformer block 안에서 말하는 expert는 보통 MLP/FFN expert에 가깝습니다.
3편에서 Transformer block은 크게 attention과 MLP/FFN으로 나뉜다고 했습니다.
dense Transformer block:
self-attention
-> MLP / FFN
MoE 모델에서는 이 MLP 부분이 바뀝니다.
MoE Transformer block:
self-attention
-> router
-> 여러 expert MLP 중 일부 선택
-> 선택된 expert 출력의 가중합
expert 하나하나가 독립된 MLP/FFN이라고 보면 됩니다. expert들이 직렬로 이어져 하나의 큰 MLP가 되는 것이 아닙니다. 병렬 후보들이 있고, router가 token별로 일부 expert를 고릅니다.
token A -> expert 3, expert 17
token B -> expert 2, expert 9
token C -> expert 17, expert 41
선택된 expert만 계산하면 전체 parameter는 크지만 active compute는 줄일 수 있습니다. 그래서 MoE는 큰 모델을 더 효율적으로 serving하는 중요한 구조가 됩니다.
여기서 sparsity는 두 가지 의미로 쓰입니다. 하나는 MoE나 pruning 같은 방법론이고, 다른 하나는 전체 parameter 중 token 하나가 실제로 활성화하는 비율을 나타내는 숫자입니다.
전체 expert 64개
토큰당 active expert 2개
active ratio = 2 / 64
sparsity multiplier = 64 / 2
Serving 성능 모델에서 sparsity를 batch size에 곱한다고 말할 때는 보통 마지막 값, 즉 sparsity multiplier를 뜻합니다. 전체 parameter가 크더라도 token 하나가 실제로 지나가는 active parameter가 작으면 같은 GPU 시간에 더 많은 token을 태울 수 있습니다.
MoE의 sparsity는 전체 expert 중 token 하나가 실제로 지나가는 expert 비율로도 읽힙니다. Router 품질과 load balancing이 함께 따라와야 합니다.
Dense 모델은 모두 지나가고, MoE 모델은 일부를 고릅니다
dense 모델에서는 모든 token이 같은 MLP를 지납니다.
모든 token
-> 같은 attention
-> 같은 MLP
MoE 모델에서는 token마다 일부 expert만 지납니다.
모든 token
-> 같은 attention
-> router
-> 선택된 expert MLP
이 차이는 계산량을 줄입니다. 하지만 새로운 문제가 생깁니다.
token을 expert가 있는 곳으로 보내야 합니다.
expert가 같은 GPU에 있으면 단순합니다. 하지만 거대 모델에서는 expert들이 여러 GPU에 나뉘어 있을 수 있습니다. 심하면 여러 서버나 rack에 분산될 수 있습니다.
그러면 router가 고른 token 표현을 해당 expert가 있는 GPU로 보내고, 계산 결과를 다시 받아야 합니다.
token representation
-> router
-> selected expert GPU로 dispatch
-> expert MLP 계산
-> 결과 gather
-> residual stream에 더함
이 통신이 latency를 만듭니다.
물론 sparsity가 무조건 품질을 높이는 것은 아닙니다. router가 필요한 expert를 잘못 고르거나 active expert 수가 너무 적으면 그 layer에서 필요한 feature transformation이 부족해질 수 있습니다. 그래서 MoE 학습과 serving은 보통 router 품질, load balancing, capacity factor, shared expert, top-k routing 같은 장치를 함께 봅니다.
장점:
토큰당 active compute 감소
더 큰 total parameter를 더 싸게 serving 가능
위험:
router 선택 오류
expert 쏠림
active compute 부족
그래서 MoE의 핵심은 "expert를 최대한 적게 켜는 것"이 아니라, 품질이 유지되는 범위에서 token당 active compute를 줄이는 것입니다.
Dense도 분산되면 통신 문제가 생깁니다
MoE만 통신 문제가 있는 것은 아닙니다.
dense 모델도 너무 크면 여러 GPU에 나뉩니다. layer를 나누거나, matrix를 나누거나, attention head를 나누거나, pipeline/tensor parallelism을 씁니다.
그래서 dense 모델도 통신합니다.
차이는 통신 패턴입니다.
dense 모델:
모든 token이 같은 경로를 지나므로 통신 패턴이 비교적 고정적이다
MoE 모델:
token마다 expert routing이 달라져 dispatch/gather가 더 동적이다
고정적인 통신은 최적화하기 쉽습니다. 동적인 통신은 load balancing과 routing이 더 어렵습니다.
어떤 expert에 token이 몰리면 그 expert가 병목이 됩니다. 어떤 GPU는 바쁘고 어떤 GPU는 놀 수 있습니다. expert가 rack 바깥에 있으면 네트워크 latency가 decode 속도에 직접 영향을 줍니다.
그래서 MoE serving은 모델 architecture 문제이면서 scheduler 문제입니다.
Transformer block은 GPU 안의 부품이 아닙니다
"Transformer block이 GPU 안에 있나요?"라는 질문은 좋은 질문입니다.
정확히는 Transformer block은 GPU 안의 물리 부품이 아닙니다. 모델 architecture 안의 계산 구조입니다.
추론 때는 그 block을 구성하는 weight가 GPU memory에 올라갑니다. GPU는 그 weight와 입력 activation을 사용해 attention, MLP, normalization, projection 계산을 실행합니다.
모델 파일 / checkpoint
-> weight를 GPU memory에 load
-> 입력 token activation과 matrix multiplication
-> output hidden state 생성
큰 모델에서는 모든 weight가 한 GPU에 들어가지 않습니다.
그래서 쪼갭니다.
layer sharding
tensor parallelism
pipeline parallelism
expert parallelism
KV cache placement
이제 "모델이 어디에 있나"는 단순한 질문이 아닙니다. 어떤 weight가 어느 GPU에 있고, 어떤 activation이 언제 이동하고, 어떤 KV cache가 어디에 저장되는지의 문제입니다.
10T 모델은 weight만으로도 거대합니다
10T parameter 모델을 예로 들어 보겠습니다.
T는 trillion, 즉 1조입니다. 10T는 10조 parameter입니다.
weight만 대략 계산해도 큽니다.
10T parameters x 2 bytes(BF16/FP16)
= 약 20TB
FP8/INT8이면 대략 절반, 4-bit 계열이면 더 줄 수 있습니다. 하지만 단순 weight만 본 계산입니다. 실제 serving에는 KV cache, activation, runtime buffer, fragmentation, communication buffer, scheduler overhead가 추가됩니다.
한 GPU가 80GB, 141GB, 180GB memory를 가진다고 해도 20TB weight를 한 장에 올릴 수는 없습니다. 여러 GPU가 필요합니다.
가중치 sharding:
하나의 model replica를 여러 GPU에 쪼개 올린다
여기에 여러 사용자 요청을 처리하려면 replica도 필요합니다.
replication:
같은 model serving bundle을 여러 cluster/region에 복제한다
이 둘을 구분해야 합니다.
Sharding과 replication은 다른 말입니다
sharding은 하나의 model replica를 여러 GPU에 나누는 것입니다.
하나의 모델 실행 인스턴스
GPU 1: 일부 layer / 일부 matrix / 일부 expert
GPU 2: 일부 layer / 일부 matrix / 일부 expert
GPU 3: 일부 layer / 일부 matrix / 일부 expert
replication은 같은 모델을 여러 곳에 복제해 트래픽을 나눠 받는 것입니다.
서울 region replica
도쿄 region replica
미국 region replica
유럽 region replica
한 사용자의 한 요청이 보통 전 세계 여러 region의 weight를 동시에 섞어 쓰지는 않습니다. 특정 region 또는 cluster에 있는 완성된 replica 하나로 라우팅됩니다.
대형 프론티어 모델 회사가 수만 개의 서로 다른 모델을 띄워둔다기보다, 소수의 큰 checkpoint를 수많은 shard와 replica로 운영한다고 보는 편이 정확합니다.
그리고 KV cache는 weight처럼 전 세계에 복제되는 것이 아닙니다.
weight:
model serving을 위해 미리 배치된 정적 상태
KV cache:
특정 요청을 처리하는 동안 해당 replica 근처에 생기는 동적 상태
이 구분이 없으면 프론티어 인프라를 잘못 상상하게 됩니다.
동시 사용자 수는 가입자 수가 아니라 tokens/sec 문제입니다
"10T 모델 하나로 몇 명까지 서비스할 수 있나요?"라는 질문도 자연스럽습니다.
하지만 여기서 "몇 명"은 전체 가입자 수가 아닙니다. 동시에 token을 생성 중인 활성 사용자 수입니다.
간단히 보면 이렇게 잡을 수 있습니다.
동시 생성 사용자 수
~ cluster 전체 output tokens/sec
/ 사용자 1명에게 제공할 tokens/sec
물론 실제로는 훨씬 복잡합니다.
prompt length
output length
reasoning effort
KV cache 크기
batch scheduling
latency 목표
cache reuse
model precision
MoE active parameter
network topology
짧은 질문을 하는 사용자 1,000명과, 100k context로 긴 코딩 작업을 돌리는 사용자 1,000명은 전혀 다릅니다.
그래서 LLM 서비스 용량은 user count보다 workload distribution으로 봐야 합니다.
또 하나의 관점은 compute와 memory의 균형입니다. Decode에서 batch가 너무 작으면 weight와 KV cache를 읽는 memory 시간이 지배적이 되고 GPU compute가 유휴 상태가 됩니다. Batch가 커지면 같은 weight read로 더 많은 token을 계산하므로 compute 활용이 좋아집니다. 어느 지점부터는 compute 시간이 병목이 됩니다.
small batch
-> memory-bound
balanced batch
-> t_mem ~= t_compute
large batch
-> compute-bound
MoE처럼 token당 active parameter가 줄어드는 구조에서는 같은 effective batch를 만들기 위해 더 큰 global batch가 필요할 수 있습니다. expert별로 token이 나뉘기 때문입니다. 그래서 frontier serving에서 중요한 숫자는 전체 가입자 수가 아니라, 특정 순간에 각 GPU/expert가 받는 token workload와 그 workload가 memory bandwidth와 compute를 얼마나 균형 있게 쓰는지입니다.
LLM serving은 분산 시스템입니다
여기까지 오면 질문 목록이 완전히 바뀝니다.
weight를 어떻게 쪼갤 것인가
expert를 어디에 둘 것인가
KV cache를 어디에 저장할 것인가
prefill과 decode를 분리할 것인가
긴 context 요청을 어떻게 routing할 것인가
batch 안의 sequence를 어떻게 교체할 것인가
tail latency를 어떻게 줄일 것인가
이 질문들은 neural network 이론만으로 풀리지 않습니다.
분산 시스템의 언어가 필요합니다.
placement
routing
load balancing
replication
sharding
network bandwidth
tail latency
fault isolation
cache locality
LLM이 커질수록 모델 품질만큼 인프라 설계가 중요해집니다. 특히 long-context와 agentic workload에서는 KV cache가 커지고, tool result가 늘고, 여러 step이 이어지기 때문에 memory와 routing 문제가 더 커집니다.
LLM serving은 모델 계산과 분산 시스템을 함께 다룹니다
MoE는 Transformer block의 MLP/FFN 부분을 여러 expert MLP로 나누고, router가 token별로 일부 expert를 선택하는 구조입니다. expert는 주제별 사전이라기보다 계산 경로의 후보 MLP에 가깝습니다.
dense 모델도 분산되면 통신 문제가 생깁니다. MoE는 token별 routing 때문에 dispatch/gather가 더 동적이고 load balancing이 더 어렵습니다.
큰 LLM은 한 GPU에 들어가지 않습니다. weight는 여러 GPU에 shard되고, 서비스 전체에서는 같은 model replica가 여러 region과 cluster에 replicate됩니다. KV cache는 정적 weight가 아니라 요청 중 생기는 동적 상태입니다.
그래서 LLM serving은 모델 계산 문제이면서 분산컴퓨팅 문제입니다.
다음 글에서는 이 분산 인프라 위에서 사용자가 체감하는 "더 깊게 생각한다"는 말로 돌아갑니다. reasoning effort는 layer 수를 늘리는 것인가, decode step을 늘리는 것인가, reasoning token을 더 쓰는 것인가를 구분합니다.
이어 읽기
시리즈는 순서대로, 편집 추천은 맥락대로, 비슷한 주제는 태그 기준으로 정리합니다.
시리즈 전체
LLM 공부 시리즈6/9편- 1.LLM 공부 01. LLM은 검색기가 아니라 다음 토큰 생성기다
- 2.LLM 공부 02. 토큰이 비용을 만든다
- 3.LLM 공부 03. Transformer 안에서 문맥이 섞이는 방식
- 4.LLM 공부 04. Prefill과 Decode는 LLM이 읽고 쓰는 두 단계다
- 5.LLM 공부 05. Batch와 Sequence Length가 속도와 비용을 정한다
- 6.LLM 공부 06. MoE와 GPU 클러스터는 거대 모델을 나누어 실행한다
- 7.LLM 공부 07. Reasoning Effort가 의미하는 추론 예산
- 8.LLM 공부 08. 학습 Batch와 Distillation은 모델을 어떻게 바꾸는가
- 9.LLM 공부 09. RAG와 Vector DB는 LLM 밖에서 근거를 찾는다
비슷한 주제의 글
태그가 겹치는 글입니다. 시리즈와 편집 추천에 이미 나온 글은 제외합니다.
AI 웹개발 기초 프론트엔드 1.1. 프론트엔드는 왜 이렇게 복잡해졌을까
프론트엔드가 React나 Next.js 같은 기술명 묶음이 아니라, 웹 문서가 구조, 표현, 동작, 상태, API 통신, 성능, 배포 책임을 차례로 떠안으며 커진 문제 해결의 축적임을 설명하는 AI 웹개발 기초 시리즈 프론트엔드 1-1.
AI 웹개발 기초 프론트엔드 1.2. DOM은 화면이 아니라 브라우저의 작업 모델이다
HTML source가 곧 화면이 아니라 DOM, CSSOM, render tree, layout, paint, composite, accessibility tree를 거쳐 화면과 보조기술 의미로 바뀌며, DOM 조작이 reflow, XSS, event delegation, 성능 지표와 어떻게 연결되는지 설명하는 AI 웹개발 기초 시리즈 프론트엔드 1-2.
AI 웹개발 기초 프론트엔드 1.3. jQuery에서 React로 넘어간 진짜 이유
jQuery의 DOM 직접 조작과 AJAX가 해결한 문제를 인정하고, UI가 커지면서 React, Vue, Angular 같은 state/data 기반 component UI가 왜 필요해졌는지 설명하는 AI 웹개발 기초 시리즈 프론트엔드 1-3.