LLM 공부 06 | MoE와 GPU 클러스터: 거대 모델은 어떻게 나뉘어 도는가
여기까지 오면 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 문제가 더 커진다.
정리
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.