MoE 추론 정리
MoE의 총 파라미터와 활성 파라미터가 왜 다른지부터 짚고 top-k 라우팅과 공유 전문가 구성을 정리했다. Dense 대비 메모리와 연산의 트레이드오프도 표로 비교한다.
MoE란
MoE(Mixture of Experts)란 FFN(Feed Forward Network) 레이어를 여러 전문가(Expert)로 나눠 두고 토큰마다 일부만 골라 계산하는 구조
Dense 구조에서는 모델을 키우면 품질과 함께 토큰 하나당 연산도 그대로 불어남.
- 전문가로 쪼개지는 것은 FFN뿐이고 어텐션은 그대로 공유됨
- 토큰마다 라우터(Router)가 쓸 전문가를 고름 → 파라미터는 많은데 계산은 일부만 돎
- 파라미터를 늘려도 토큰당 연산이 그만큼 늘지 않음 → 같은 연산 예산에서 용량을 키우는 수단
- 고르지 않은 전문가도 메모리에는 올라가 있어야 함
총 파라미터와 활성 파라미터
총 파라미터는 모델이 가진 가중치 전부이고, 활성 파라미터는 토큰 하나를 처리할 때 실제로 곱해지는 가중치
- 총 파라미터가 메모리 점유를 정하고, 활성 파라미터가 토큰당 연산량을 정함
- Qwen3.6-35B-A3B는 총 35B에 활성 3B, 이름의 A3B가 활성 3B를 가리킴
- 두 값이 갈라지는 구조가 MoE이고 Dense는 둘이 같음
- 35B 기준으로 연산 비용을 잡으면 과대 추정, 3B 기준으로 메모리 소요를 잡으면 과소 추정
게이팅과 라우팅
게이팅(Gating)이란 토큰마다 어느 전문가로 보낼지 점수를 매겨 정하는 절차
- 라우터가 토큰마다 전문가별 점수를 매기고 상위 k개를 고름(top-k)
- Qwen3.6-35B-A3B는 전문가 256개 중 8개를 고름
- 선택이 토큰 단위 → 같은 문장 안에서도 토큰마다 다른 전문가가 쓰임
- 특정 전문가에 쏠리면 나머지 용량이 낭비됨 → 학습 단계에서 로드 밸런싱으로 분산을 유도
- 추론 시점에는 어느 전문가가 뽑힐지 미리 알 수 없음
전문가 구성
전문가 하나를 얼마나 작게 쪼갤지, 항상 켜두는 전문가를 둘지가 구성의 두 축
- 세분화 전문가(Fine-grained Expert): 전문가 하나를 작게 만들고 개수를 늘리는 방식
- Qwen3.6-35B-A3B의 Expert Intermediate Dimension은 512로, 같은 세대 Dense인 Qwen3.6-27B의 FFN Intermediate Dimension 17408에 견주면 매우 작음
- 전문가가 잘게 나뉘면 고를 수 있는 조합이 늘어 표현력↑
- 공유 전문가(Shared Expert): 라우팅과 무관하게 항상 활성화되는 전문가
- Qwen3.6-35B-A3B의 토큰당 활성 구성은 8 Routed + 1 Shared
- 공유 전문가가 모든 토큰에 공통으로 드는 계산을 맡음 → 라우팅 전문가끼리 같은 것을 중복해 익히는 낭비가 줄어듦
Dense와 비교
같은 세대에 컨텍스트 길이도 같아 구조 차이만 놓고 견줄 수 있음
| 비교 항목 | Qwen3.6-35B-A3B | Qwen3.6-27B |
|---|---|---|
| 구조 | MoE | Dense |
| 총 파라미터 | 35B | 27B |
| 활성 파라미터 | 3B | 27B |
| Hidden Dimension | 2048 | 5120 |
| 레이어 | 40 | 64 |
| FFN 자리 | 전문가 256개, Intermediate 512 | FFN 1개, Intermediate 17408 |
| GGUF 파일 | UD-Q4_K_M 22.13GB | Q4_K_M 16.82GB |
- 총 파라미터도 GGUF 파일도 MoE 쪽이 커서 메모리 요구가 더 큼
- 토큰당 활성은 3B 대 27B → 연산 요구는 MoE가 훨씬 작음
- 크기와 속도의 방향이 반대로 가는데, Dense끼리 견줄 때는 이런 역전이 생기지 않음
메모리와 연산 트레이드오프
메모리를 용량과 대역폭으로 갈라서 봐야 손익이 드러남
| 자원 | 무엇에 비례 | MoE에서의 결과 |
|---|---|---|
| 메모리 용량 | 총 파라미터 | 불리(고르지 않은 전문가도 상주) |
| 메모리 대역폭 | 토큰당 읽는 가중치 | 유리(활성 전문가 몫만 읽음) |
| 연산량 | 활성 파라미터 | 유리 |
| 통신량 | 전문가 배치 위치 | 여러 장치에 흩어지면 불리 |
- 용량은 손해고 대역폭과 연산은 이득 → 어느 쪽이 병목인지가 MoE의 값어치를 정함
- 전문가를 여러 장치에 흩으면 라우팅 결과를 주고받는 통신이 붙음 → 병렬화 축별 통신 패턴은 분산 학습 병렬화와 집합 통신 정리에서 다룸
MoE가 줄이지 못하는 것
활성 파라미터가 깎아 주는 것은 FFN 몫이고, 나머지 비용은 Dense와 같은 값을 냄
- 전문가로 나뉜 것은 FFN뿐 → 어텐션 연산은 활성 파라미터와 무관하게 그대로 듦
- KV cache 크기는 전문가 수가 아니라 레이어·KV 헤드·시퀀스 길이로 정해짐
- 임베딩과 출력 레이어도 라우팅 대상이 아님
- 컨텍스트가 길어질수록 FFN이 아니라 어텐션과 KV cache가 병목을 잡음 → 크기 어림과 decode 대역폭 병목은 LLM 추론 서빙 정리에서 다룸
로컬 추론에서의 MoE
로컬은 가속기 대수가 아니라 한 대의 메모리 용량과 대역폭이 상한을 정하는 환경
- decode는 스텝마다 가중치를 훑는 메모리 대역폭 바운드 → MoE는 활성 전문가 몫만 읽어 스텝당 읽는 양이 작음
- prefill은 연산 바운드 → 활성 3B가 FLOPs를 줄여 첫 토큰 지연(TTFT)에도 이득
- 통합 메모리 환경은 용량이 넉넉한 대신 대역폭이 데이터센터 가속기보다 낮음 → 대역폭을 아끼는 MoE와 궁합이 맞음
- 배치가 커지면 서로 다른 토큰이 서로 다른 전문가를 부름 → 한 스텝에서 깨어나는 전문가가 늘어 이득이 줄어듦
- 로컬은 대개 동시 요청이 적음 → MoE의 이득이 가장 크게 남는 구간
함정: 활성이 3B여도 전부 올려야 함
고를 전문가를 미리 알 수 없어 쓰지 않을 가중치까지 메모리에 상주시켜야 함
- 활성 3B는 연산 쪽 이야기이지 메모리 쪽 이야기가 아님 → UD-Q4_K_M 기준 22.13GB 전부가 상주해야 함
- 토큰마다 전문가가 바뀌므로 필요할 때 디스크에서 꺼내 쓰는 구성은 스텝마다 저장장치를 때림 → 속도 이득이 사라짐
- 전문가 가중치만 시스템 RAM으로 내리는 오프로드는 실용적이고, llama.cpp의
--cpu-moe와--n-cpu-moe가 이 용도 - 토큰당 오가는 것이 활성 전문가 몫뿐이라 Dense를 같은 방식으로 내렸을 때보다 성능 하락이 완만함 → VRAM이 부족한 환경에서는 오히려 MoE 쪽 실행 가능성이 높음
- 통합 메모리에는 CPU·GPU 메모리 구분이 없어 이 오프로드가 해당하지 않음
상황별 권장
용량과 대역폭 중 어느 쪽이 먼저 바닥나는지가 선택을 가름
| 상황 | 추천 | 추천 사유 |
|---|---|---|
| 메모리는 넉넉하고 응답 속도가 중요 | MoE | 스텝당 읽는 양이 작아 decode가 빠름 |
| 메모리가 빠듯하고 컨텍스트가 짧음 | Dense | 같은 품질대에서 총 파라미터가 작음 |
| 동시 요청이 많은 서빙 | Dense 또는 전문가 분산 배치 | 배치가 커질수록 MoE의 활성 이득이 줄어듦 |
| 컨텍스트가 매우 김 | 구조보다 KV cache 설계가 우선 | 병목이 FFN이 아니라 어텐션으로 옮겨감 |
| VRAM이 부족한 단일 GPU | MoE + 전문가 CPU 오프로드 | 토큰당 오가는 양이 활성 전문가 몫뿐 |
결론
- 용량이 넉넉하면 MoE, 용량이 빠듯하면 Dense, VRAM만 빠듯하면 MoE에 전문가 CPU 오프로드
- 활성 파라미터가 깎아 주는 것은 FFN 몫뿐 → 컨텍스트가 길어지면 어텐션과 KV cache가 판을 가져감
- 배치가 커질수록 이득이 옅어짐 → 동시 요청이 적은 로컬 쪽이 MoE와 맞음
- 총 파라미터는 "얼마나 담을 수 있는가", 활성 파라미터는 "얼마나 빨리 답하는가"