Mixture-of-Experts kernel engineering on Amazon SageMaker AI
Quick Summary
AWS는 Amazon SageMaker AI의 fused MoE 추론을 위해 행렬 배치, FP8 백엔드 라우팅, Triton JIT 재컴파일을 최적화했으며, H200에서 최대 10%의 처리량 향상과 최대 9%의 TTFT 개선을 보고했다.
🖼️ 인포그래픽

🖼️ 4컷 인포그래픽

💡 한 줄 요약
AWS는 Amazon SageMaker AI의 fused MoE 추론을 위해 행렬 배치, FP8 백엔드 라우팅, Triton JIT 재컴파일을 최적화했으며, H200에서 최대 10%의 처리량 향상과 최대 9%의 TTFT 개선을 보고했다.
📌 핵심 요약
- MoE는 토큰당 연산량을 낮게 유지하면서 LLM 용량을 확장하는 희소 활성화 구조다. 토큰 라우팅, 데이터 재배치, 전문가 연산을 통합하는 fused MoE는 지연 시간을 줄이지만, 높은 GPU 활용률을 얻으려면 하드웨어에 맞춘 커널 최적화가 필요하다.
- Swap-AB는 행렬곱의 피연산자를 전치해 Hopper WGMMA의 고정된 64행 배치 제약에 맞춘다. H200의 대규모 MoE 모델에서 종단 간 출력 처리량을 2~4% 높였으며, vLLM 0.24.0 이상에서 제공된다.
- Hopper의 FP8 텐서 양자화 MoE에서는 특히 낮은 동시성 조건에서 Triton이 기본 FLASHINFER_CUTLASS 경로보다 우수한 성능을 보였다. 커널 코드 수정 없이 백엔드 라우팅 정책을 변경해 H200에서 종단 간 처리량을 10% 높였으며, AWS Large Model Inference(LMI) v28 컨테이너에서 제공된다.
- _fused_inv_rope_fp8_quant_per_head 커널의 가변 길이 매개변수에 do_not_specialize를 적용해 새로운 num_tokens 값마다 발생하던 Triton JIT 재컴파일을 제거했다. H200의 8방향 텐서 병렬 구성에서 TTFT가 9% 개선됐으며, 관련 변경은 PR #42849와 vLLM 0.22.0 이상에 반영됐다.
- AWS는 vLLM 커뮤니티와 협력해 이러한 최적화를 공개하고 Amazon SageMaker AI의 LMI Deep Learning Container에 적용했다. 글은 전체 성과를 처리량 최대 10% 향상과 TTFT 최대 9% 개선으로 제시한다.
🧩 주요 포인트
- 디코딩의 작은 토큰 행 수와 WGMMA의 64행 제약이 충돌하므로, 수학적 결과를 유지하는 행렬 배치 변경이 GPU 활용률 개선으로 이어진다.
- FP8 연산의 융합 방식과 작은 배치 처리 능력이 백엔드 성능을 좌우하므로, 실행 경로 선택 자체가 처리량 최적화 수단이 된다.
- 가변 num_tokens에 대한 JIT 특수화는 8방향 텐서 병렬 구성에서 GPU 간 대기로 이어지므로, 컴파일 정책도 초기 응답 지연의 최적화 대상이다.
🧠 상세 정리
1. MoE의 연산 효율과 fused MoE 최적화의 출발점
MoE는 일부 전문가만 활성화하는 방식으로 토큰당 연산량을 낮게 유지하면서 대규모 언어 모델의 용량을 확장하는 구조다. 글은 MoE 연산이 전체 계산 시간에서 큰 비중을 차지하므로, 이 부분의 비효율이 요청 지연 시간과 비용을 직접 높이며 커널 엔지니어링이 성능 개선의 주요 기회라고 설명한다. Fused MoE는 토큰 라우팅, 데이터 재배치, 전문가 신경망 계산을 GPU의 단일 배치 연산으로 통합해, 각각의 작업을 순차적인 반복 연산으로 실행하던 방식을 대체한다. 이러한 통합은 지연 시간을 줄이는 이점이 있지만 커널 구현과 디버깅을 복잡하게 만들며, 높은 GPU 활용률을 얻으려면 하드웨어별 최적화가 필요하다. AWS는 대표적인 MoE 모델을 중심으로 행렬 배치, 양자화 백엔드 선택, 컴파일 동작이라는 서로 다른 최적화 지점을 제시한다.
2. Hopper WGMMA의 비대칭 구조와 작은 디코딩 배치
NVIDIA Hopper의 WGMMA 명령은 128개 스레드로 구성된 협력적 워프그룹에서 실행되며, 피연산자 배치에는 명령어 집합 수준의 비대칭성이 존재한다. 원문에 따르면 하드웨어는 행 차원 M을 64 단위로 고정하고 열 차원 N에는 더 큰 가변성을 허용하며, 피연산자 A는 고정된 M 차원에, 피연산자 B는 가변적인 N 차원에 대응한다. 일반적인 전문가 연산 A[M,K] × B[K,N]에서 M은 토큰 행 수, K는 은닉 특징 차원, N은 전문가 출력 차원을 뜻한다. 디코딩에서는 사용자 시퀀스마다 한 번에 한 토큰만 처리하므로 M이 64보다 작아지거나 1까지 줄어들며, 예를 들어 A가 1×4096인 경우 고정된 64행 배치를 채울 수 없다. 글은 이때 상당수 Tensor Core 실행 공간이 비어 있게 되어, 큰 전문가 가중치 행렬이 존재해도 하드웨어 활용률이 낮아진다고 설명한다.
3. 전문가별로 분산된 연산과 Swap-AB의 수학적 전환
일반적인 밀집 LLM 계층은 하나의 연속적인 가중치 행렬을 사용하지만, MoE 계층은 여러 독립적인 전문가로 작업이 나뉘어 메모리와 데이터 배치의 제약이 더 복잡해진다. Fused MoE 커널은 전문가마다 별도 커널을 실행하는 부담을 피하기 위해 활성 전문가들의 계산을 묶어서 수행하며, 글은 이때 유효 N 차원을 선택된 전문가 수와 전문가 중간 차원의 곱으로 설명한다. 따라서 topk=8 같은 구성에서는 유효 N이 수만 또는 수십만 규모로 커져, M=1인 디코딩 토큰 차원과의 불균형이 극단적으로 커질 수 있다. Swap-AB는 A[M,K] × B[K,N] → C[M,N]을 Bᵀ[N,K] × Aᵀ[K,M] → Cᵀ[N,M]으로 바꾸는 전치 성질을 이용한다. 이 변환은 모델의 수학적 연산 관계를 유지하면서 큰 전문가 차원을 첫 번째 피연산자 위치로 옮겨, Hopper가 선호하는 배치에 연산을 맞추는 접근이다.
4. Swap-AB가 활용률과 프리페칭에 미친 효과
AWS는 행렬곱이 PTX 어셈블리 계층에 도달하기 전에 피연산자의 순서와 전치를 바꾸어 소프트웨어 배치를 Hopper 하드웨어 구조에 맞췄다고 설명한다. 첫 번째 효과는 예시에서 N=8192인 큰 전문가 차원을 첫 번째 피연산자로 이동시켜, 하드웨어가 요구하는 64행 배치를 충분히 채우는 것이다. 두 번째 효과는 큰 연속 가중치 블록을 앞쪽에 배치함으로써, 원문이 설명하는 공유 메모리에서 레지스터로의 비동기 프리페칭을 원활하게 하고 계산 파이프라인에 데이터를 지속적으로 공급하는 것이다. 글은 이러한 배치가 CPU 개입 없이 계산 흐름을 유지하는 데 도움이 됐으며, H200의 대규모 MoE 모델에서 종단 간 출력 처리량을 2~4% 높였다고 보고한다. 이 최적화는 vLLM에 업스트림으로 반영됐으며, 사용 가능한 버전은 vLLM 0.24.0 이상으로 명시돼 있다.
5. FP8 양자화에서 Triton 백엔드가 유리했던 이유
커널 내부 구현뿐 아니라 어떤 백엔드가 MoE 계산을 실행하는지도 성능에 큰 영향을 주며, vLLM의 MoE oracle은 양자화 방식에 따라 Triton, FlashInfer+CUTLASS 등의 경로를 선택한다. AWS의 프로파일링에서는 Hopper의 FP8 텐서 양자화 모델에 대해 Triton이 기본 FLASHINFER_CUTLASS 경로보다 일관되게 우수했으며, 글은 특히 낮은 동시성의 MoE 작업에서 그 이유를 설명한다. 원문에 따르면 CUTLASS의 표준 C++ 템플릿 구조는 FP8 텐서 스케일링, 행렬곱, 전문가 결과 집계를 별도 연산으로 다루는 반면, Triton은 이를 레지스터 수준에서 융합한다. Triton 경로는 데이터를 전역 고대역폭 메모리에서 한 번 가져온 뒤 GPU의 빠른 로컬 저장 공간에서 처리하고 최종 출력 위치로 기록하는 방식으로 제시된다. 글은 이러한 융합이 중간 스케일링 단계에서 발생하는 전역 메모리 읽기·쓰기 왕복을 줄여 해당 조건의 성능 우위로 이어졌다고 주장한다.
6. 작은 배치의 동적 스케줄링과 라우팅 정책 변경
원문은 Triton의 연산 융합뿐 아니라 가변적인 토큰 묶음에 맞춘 동적 스케줄링도 작은 디코딩 배치에서 중요한 역할을 한다고 설명한다. CUTLASS는 크고 조밀하며 예측 가능한 행렬 차원에 최적화돼 있어, M<64 또는 M=1처럼 매우 얇은 배치를 처리할 때 기본 블록 타일링과 스레드 매핑으로 인해 워프 활용률 저하나 메모리 패딩 부담이 생길 수 있다는 설명이다. 반면 Triton MoE 백엔드는 작고 분산된 토큰 배열을 활성 전문가 가중치에 동적으로 매핑해, 낮은 배치 크기에서도 프리페칭과 Tensor Core 계산 흐름을 유지하는 데 유리하다고 제시된다. AWS는 이러한 관찰을 바탕으로 커널 코드를 수정하지 않고 FP8 텐서 양자화 모델의 백엔드 라우팅 정책만 변경했다. 그 결과 H200의 FP8 양자화 fused MoE 모델에서 종단 간 처리량이 10% 향상됐으며, 해당 개선은 AWS LMI v28 컨테이너에서 제공된다고 명시한다.
7. 가변 토큰 수가 유발한 Triton JIT 재컴파일 제거
Triton은 기본적으로 정수 인자를 특수화하므로, 특수화 대상 매개변수에 이전에 보지 못한 값이 들어오면 새로운 JIT 컴파일을 수행한다. 시퀀스 길이와 배치 크기가 계속 변하는 추론 서비스에서는 이러한 동작이 반복적인 컴파일 부담을 만들고, 특히 첫 토큰까지 걸리는 시간인 TTFT를 늘릴 수 있다. MoE 서빙에서는 회전 위치 임베딩과 FP8 양자화를 융합하는 _fused_inv_rope_fp8_quant_per_head 커널이 새로운 num_tokens 값마다 재컴파일되고 있었다. AWS는 가변 길이 매개변수에 do_not_specialize 주석을 추가해 해당 재컴파일을 제거했으며, H200의 8방향 텐서 병렬 구성에서 TTFT가 9% 개선됐다고 보고한다. 관련 변경은 PR #42849로 제시되며 vLLM 0.22.0 이상에 포함돼 있어, 글은 작은 코드 변경으로도 컴파일러 동작을 조정해 지연 시간을 개선할 수 있음을 보여준다.
8. 다중 GPU 동기화의 영향과 공개된 적용 경로
8개 GPU가 함께 실행되는 구성에서는 각 GPU의 커널 실행이 마이크로초 수준으로 동기화돼야 하므로, 한 GPU의 재컴파일이 다른 GPU의 대기로 확산될 수 있다. 글은 한 GPU의 로컬 토큰 배치 수가 바뀌어 _fused_inv_rope_fp8_quant_per_head 커널을 다시 컴파일하면, 나머지 7개 GPU도 기다리게 된다는 사례로 초기 응답 지연의 원인을 설명한다. 클러스터 전체에서 이러한 재컴파일을 제거하면 GPU 간 조정 부담이 완화되며, 이는 앞서 제시한 9%의 TTFT 개선을 설명하는 근거다. AWS는 vLLM 커뮤니티와 협력해 여러 fused MoE 최적화를 구현하고 공개했으며, 이를 Amazon SageMaker AI의 LMI Deep Learning Container에 적용했다고 밝힌다. 결론에서 제시한 전체 성과는 처리량 최대 10% 향상과 TTFT 최대 9% 개선이며, 사용자 지정 모델 호스팅의 시작점으로 Amazon SageMaker AI 호스팅 문서를 안내한다.
🧾 핵심 주장 / 시사점
- MoE의 희소 활성화만으로 높은 GPU 효율이 보장되지는 않는다. 디코딩의 작은 토큰 차원과 전문가 가중치 배치를 하드웨어 명령의 제약에 맞추는 작업이 추가로 필요하다.
- FP8 백엔드 사례는 성능 개선이 커널 코드 변경에만 달려 있지 않음을 보여준다. 양자화 방식과 동시성 조건에 맞는 실행 경로 선택도 종단 간 처리량에 영향을 준다.
- JIT 재컴파일은 개별 GPU의 컴파일 비용을 넘어 병렬 GPU 전체의 대기 원인이 될 수 있다. 따라서 컴파일 특수화 정책과 GPU 간 동기화를 함께 살펴볼 필요가 있다.
✅ 액션 아이템
- H200 기반 MoE 추론에서 vLLM 0.24.0 이상의 Swap-AB 적용 가능 여부 검토.
- Hopper의 FP8 텐서 양자화 MoE를 대상으로 낮은 동시성에서 Triton과 FLASHINFER_CUTLASS의 처리량 비교 및 LMI v28 적용 검토.
- 8방향 텐서 병렬 구성에서 num_tokens 변화에 따른 JIT 재컴파일 여부와 vLLM 0.22.0 이상의 do_not_specialize 반영 여부 확인.
❓ 열린 질문
- H200에서 보고된 Swap-AB의 2~4% 처리량 향상은 모델과 토큰 행 수에 따라 어떻게 달라지는가?
- Hopper의 FP8 텐서 양자화 MoE에서 Triton의 성능 우위는 낮은 동시성 이외의 조건에서도 유지되는가?
- H200의 8방향 텐서 병렬 구성에서 나타난 9%의 TTFT 개선은 num_tokens의 변화 양상에 따라 어떻게 달라지는가?