Kimi-K3
Kimi-K3
Kimi-K3은 Moonshot AI의 플래그십 하이브리드 MoE 비전-언어 모델로, 2.8조 파라미터, 토큰당 활성 전문가 16/896개, Kimi-K2 대비 약 2.5배의 스케일링 효율을 가지는 모델이에요. 이 페이지에서는 SGLang에서 Kimi-K3를 설치·배포·호출하는 방법과 추론, 툴 호출, HiCache, PD 분리, VLM 서빙, 대규모 서빙 프리셋까지 상세히 설명해요.
출처: 문서
본문
Deployment (배포)
SGLang 설치
설치 방법과 하드웨어 플랫폼에 대한 모든 내용은 공식 SGLang 설치 가이드를 참고해요. 아래 두 경로는 명령 패널의 Python / Docker 토글과 일치해요.
Python (pip / uv) — 우선 Python 환경에 SGLang을 설치해요.
pip install --upgrade pip
pip install uv
uv pip install --prerelease=allow sglang
그런 다음 아래 명령 패널의 Python 출력을 해당 환경에서 실행해요.
Docker — NVIDIA와 AMD용 Docker 이미지를 받아요.
docker pull lmsysorg/sglang:latest # NVIDIA (CUDA)
docker pull lmsysorg/sglang-rocm:v0.5.19-rocm720-mi35x-20260916 # AMD MI350X / MI355X (ROCm)
이미지 실행 방법은 Install → Method 3: Using Docker를 참고해요. 내부의 sglang serve ...를 아래 명령 생성기가 만든 결과로 대체해요.
NPU — Ascend 시리즈용 이미지를 받아요.
docker pull quay.io/ascend/sglang:main-cann9.0.0-a3 # Ascend A3 Series
docker pull swr.cn-southwest-2.myhuaweicloud.com/base_image/dockerhub/lmsysorg/sglang:cann9.1.0-950-B070 # Ascend 950PR/DT Series
호스트와 플랫폼 설정은 NPU 설치 가이드와 퀵 스타트 가이드를 참고해요.
NPU 가중치 (Weights): Kimi-K3 (950PR/DT Series, MXFP4) · Kimi-K3-W4A8 (A3 Series, W4A8, 1.49 TB) · Kimi-K3-DSpark (DSPARK draft, 4.5 GB)
하드웨어 선택
하드웨어를 고른 다음 배포 형태(shaping)와 운영 지점을 선택해요. 노드 수는 하드웨어 레시피를 따라가므로 별도 선택이 아니에요 (B200 2×8, GB200 4×4, H100 4×8, B300 1×8, H200 2×8 — Unified High-Throughput에서는 4×8, GB300 2×4, MI350X/MI355X 1×8, Ascend A3 Series 4×8 — 32 카드 / 64 다이, Ascend 950PR/DT Series 4×8). NVFP4 체크포인트(nvidia/Kimi-K3-NVFP4, 아래 패널의 Quantization 행)를 서빙한다면 lmsysorg/sglang:dev-dev-kimi-k3-nvfp4 이미지를 사용해요.
PD Mode — Unified는 prefill과 decode를 함께 서빙해요. Prefill / Decode는 이들을 전용 풀로 분리해요(PD disaggregation 참고). Prefill은 두 가지 전략을 제공하며 둘 다 16k로 청킹되요. 8-GPU 플랫폼(B300 1×8, GB300 2×4)에서 Default는 TP8, Long-Context는 --pp-size 8 --tp-size 1이에요. 16-GPU 플랫폼(B200 2×8, GB200 4×4)에서는 둘 다 --pp-size 16 --tp-size 1이며 --mem-fraction-static(0.85 vs 0.90)만 달라요 — 거기서 deep PP는 long-context 전용이 아니라 처리량 형태예요(Deep PP 참고).
Strategy — 그 형태 안에서의 운영 지점이에요.
- Low-Latency — DCP가 없어 MLA KV가 TP-replicated 상태로 유지돼요. 채팅용. B200은 두 노드를 PP2 × TP8로 나누고, 다른 모든 플랫폼은 평평한 TP예요.
- Balanced — 정확도 보존 기본값: B200에서 PP2 × DCPEP8(두 파이프라인 스테이지와 DCP8이 KV와 KDA 상태를 나눔), GB200에서 TP16/DCP16, B300/GB300에서 TP8/DCP8, MI35x에서 TP8/DCP8 ROCm/AITER.
- High-Throughput — 대규모 레인: Playground에서 Cluster Size와 Large-Scale Preset을 골라요. 셀 자체는 Balanced이며, H100(
extra_buffer_lazy추가)과 H200(4×8 TP32/EP32,--mem-fraction-static 0.90)은 예외예요.
Long-Context는 Prefill PD 모드에서만 나타나요. B200에서 long-context unified 서빙을 하려면 High-Throughput에서 시작해 --context-length를 높여요.
Spec Decode — B200을 제외한 모든 플랫폼에서 전략을 바꾸지 않고 그 위에 얹어요. DSPARK는 스텝당 7개의 드래프트 토큰을 제안하며(Playground에서 튜닝) pp_size == 1을 요구해요. 그래서 B200에서는 파이프라인을 버리고 같은 16개 GPU를 평평하게 재배치해요: PP2 × TP8 → TP16, PP2 × DCPEP8 → DCPEP16. DFLASH는 Kimi-K3-DFlash 드래프트를 block size 8로 사용해요. 파이프라인 병렬이나 DP attention을 아직 지원하지 않으므로 pipelined B200 Unified 레시피에서는 사용할 수 없어요. Blackwell에서만 검증되었기 때문에 Hopper와 AMD 레시피에는 아직 없어요. 이득은 짧은 인터랙티브 트래픽에서 가장 크고 프롬프트가 길어질수록 줄어들어요.
AMD AITER with DCP8
MI350X/MI355X unified Balanced 레시피는 TP8/DCP8을 AITER prefill과 decode attention과 함께 사용해요. DCP는 타깃 MLA KV cache를 샤딩하고, RadixArk DSPARK 드래프트 KV는 replicated로 유지돼요. 고정된 v0.5.19-rocm720-mi35x-20260916 이미지는 SGLang 리비전 e7f7447333을 기록하며, 여기에는 AITER DCP support (#34432)와 DCP KV-free fix (#38941)가 포함돼요. DCP에 소스 오버레이(source overlay)는 필요 없어요.
이 이미지에서는 SGLANG_K3_KDA_FUSED_BACKEND를 설정하지 않은 채로 유지해요. 별도의 fused-KDA 옵트인은 deferred-gate fix (#39066)가 필요하며, 이 이미지에는 포함되지 않아요. 이 업데이트된 레시피는 여전히 Final Verification In Progress 상태이며, 기록된 속도 수치는 원래 구성을 사용하고 새 이미지나 DCP8 레시피를 검증하지 않아요.
Mamba ratio calculator
--mamba-full-memory-ratio 계산 방법 — 이 값은 KDA 상태 풀과 MLA KV 풀 사이의 비율이에요. 아래 파라미터 중 L을 제외한 모든 값은 Deploy 패널과 Playground 선택에서 실시간으로 읽히며, balanced 값은 요청당 비용 비율이에요:
ratio = (S + D) x state_bytes / (L x (mla_kv_bytes / DCP + draft_kv_bytes))
S— 요청당 KDA 상태 슬롯:extra_buffer=5,extra_buffer_lazy=4,no_buffer=3, radix cache 비활성=1.SGLANG_OPT_MAMBA_SKIP_DECODE_LOCK은 extra-buffer 전략에서 슬롯 하나를 해제해요. overlap 스케줄러가 꺼져 있거나(pp > 1이면 비활성) track 버퍼가 슬롯 하나 대신 두 개를 차지해요.D— 추측 디코딩 아래의 verify 중간 상태: 비활성이면0, 그 외에는 DSPARK block size + 1(7기본값에서8). ReplaySSM(--enable-linear-replayssm-spec)은 이를 슬롯당 링으로 접어D를0으로 돌려요.state_bytes— K3의 고정 지오메트리, attention-TP 폭, SSM dtype에서 나오는 상태 슬롯 하나의 바이트.mla_kv_bytes— 토큰 하나의 MLA latent KV 바이트(KV-dtype 의존). DCP가 이를 rank들로 샤딩해요. DSPARK 드래프트 모델의 KV(토큰당 약 1.4 KB)는 모든 rank에 replicated되므로 평평하게 들어가요 — DCP 없이는 무시할 수 있고, DCP8 아래에서는 샤딩된 MLA share와 같은 차수예요.L— 토큰 단위 평균 총 요청 길이: 입력 + 출력.
Advanced Features Playground
Playground는 배포 행렬을 넘어선 SGLang 기능을 실험하는 곳이에요. 위의 Deploy 패널은 SGLang 팀이 수렴 중인 레시피를 내보내고, Playground는 Deploy 패널이 현재 보여주는 셀 위에 추가 노브를 켤 수 있게 해줘요.
1. Model Introduction (모델 소개)
Kimi-K3는 Moonshot AI의 플래그십 하이브리드 MoE 비전-언어 모델이에요: 2.8조 파라미터, 토큰당 활성 전문가 16/896개, Kimi-K2 대비 약 2.5배의 스케일링 효율. 백본은 93개 레이어에 걸쳐 **Kimi Delta Attention (KDA)**과 MLA를 인터리브해요(Attention Residuals와 Stable LatentMoE 포함). 서빙은 이미지 입력과 prefix caching이 있는 1M-토큰 윈도우를 지원해요. 가중치는 MXFP4로 배포돼요: FlashInfer MXFP4(trtllm-gen SiTU) 러너가 Blackwell에서 서빙하고, Marlin(W4A16)은 그 외, MegaMoE는 short-context 배치 처리량용이에요.
K3는 항상 thinking을 활성화하고, 추론 깊이는 reasoning_effort(low / high / max; 기본 max)로 제어돼요.
B300 1×8 Unified Low-Latency와 Balanced 셀은 Verified — 최종 가중치에 대한 속도 라운드가 아래 게시돼요. 다른 모든 셀은 여전히 Final Verification In Progress로 표시돼요: 레시피는 실행되지만 최종 가중치와 현재 코드에 대한 서빙 라운드는 여전히 열려 있어요. 어느 셀에서도 정확도는 재측정되지 않았어요 — 의존하기 전에 재측정해요.
권장 생성: temperature=1.0, top_p=0.95, presence_penalty=0, frequency_penalty=0(모델이 고정 — 정보용이며 샘플 코드에 하드코딩하지 말 것).
리소스: HuggingFace · Kimi-K3 Quickstart
2. Configuration Tips (설정 팁)
메모리: 두 풀, 하나의 플래그. K3는 정적 메모리를 worst-case 예약 KDA 상태 풀(동시성 상한을 설정)과 페이징 MLA KV 풀로 나누며, --mamba-full-memory-ratio로 나눠요. 명령 패널은 이 플래그를 계산기의 출력에 고정해요 — 평균 요청 길이를 거기 설정하고, 나머지 계산기 입력은 패널을 따르면 돼요. (Ascend NPU 레시피에서는 계산기와 ratio 플래그가 없어요: Ascend 경로가 두 풀을 자체적으로 크기 조정해요 — A3 Series는 --max-mamba-cache-size를 고정하고, A5 레시피는 radix cache를 꺼요.) 부팅 후 max_total_num_tokens(KV 쪽)와 수용된 요청 상한(상태 쪽)을 읽어 확인해요.
용량 레버는 모두 Playground에 있어요. 각각은 정밀도나 캐시 동작을 용량으로 바꾸므로, 워크로드에서 정확도를 재검증해요.
| 레버 | 효과 |
|---|---|
--mamba-radix-cache-strategy extra_buffer_lazy |
요청당 상태 슬롯 5개 대신 4개 |
--mamba-ssm-dtype bfloat16 |
상태 바이트 절반으로; 스펙 켜면 KDA 검증이 fused 커널에서 Triton으로 폴백 |
--kv-cache-dtype fp8_e4m3 |
토큰당 KV 바이트 절반; PD 아래에서는 두 역할 모두 connect에서 일치해야 함 |
--mem-fraction-static 0.90–0.92 |
부팅 로그에 큰 유휴 avail mem이 보일 때 가장 싼 첫 승리 |
SGLANG_OPT_MAMBA_SKIP_DECODE_LOCK=1 |
요청당 슬롯 하나 더 해제 (실험적, 검증 중) |
추측(Speculation): DSPARK는 요청당 block size + 1 (= 8)개의 중간 상태를 보유해요 — 계산기가 이를 반영해요 — 그리고 설정하지 않은 --max-running-requests는 스펙 아래에서 48로 리셋돼요 (명령 패널이 알려주며, 높이려면 명시적으로 설정해요).
MoE 러너. Blackwell에서 --moe-runner-backend를 설정하지 않은 채로 둬요: FlashInfer MXFP4(W4A8, 공식 trtllm-gen SiTU 커널)가 선택되고, H100/H200은 Marlin을 고정해요. B200 Balanced와 High-Throughput 셀은 flashinfer_mxfp4을 명시적으로 고정하는데, 그것이 이들이 구축된 형태이기 때문이에요.
Attention 백엔드. Blackwell에서 세 attention 노브를 모두 설정하지 않은 채로 둬요: K3는 prefill, decode, 그리고(DSPARK 아래) 검증을 하나의 세트로 해결해요(trtllm_mla 전체; cutedsl_mla는 DCP 아래 decode와 검증을 담당). 비-DCP 레시피에서 셋 중 하나를 설정하면 나머지의 자동 해결이 취소돼요. B200 Balanced와 High-Throughput 셀은 --decode-attention-backend cutedsl_mla를 고정하는데, 이것이 자동 해결이 그 DCP 레시피에 대해 선택하는 것과 같아요 — 해결을 바꾸기 때문이 아니라 이들이 구축된 형태이기 때문에 적어둔 거예요. H100/H200은 decode에 flashmla를 고정해요.
컨텍스트 길이. --context-length은 수용되는 가장 긴 요청과 일부 컨텍스트 스케일 버퍼를 제한해요. KV 풀 크기를 정하지는 않아요. long context에서 용량을 추가하는 레버는 fp8_e4m3 KV예요.
DSPARK. 보여지는 전략 위에 --speculative-algorithm DSPARK와 드래프트 체크포인트를 추가해요. --speculative-draft-attention-backend는 설정하지 않은 채로 둬요. 게시된 B300 DSPARK 수치는 SGLANG_SIMULATE_ACC_LEN으로 수용 길이를 고정하므로, 실제 워크로드에 대한 측정 수용률은 아직 없어요 — 채택 전에 NOSPEC과 같은 레시피로 측정해요.
플랫폼별 참고:
| 플랫폼 | 토폴로지 | 참고 |
|---|---|---|
| B300 1×8 | TP8 (+DCP8) | Low-Latency와 Balanced에서 accuracy-first 기본값 |
| GB300 2×4 | TP8/DCP8 | MNNVL 전송과 cuMem 자동 감지 |
| B200 2×8 | Low-Latency에서 PP2 × TP8, Balanced·High-Throughput에서 PP2 × DCPEP8. DSPARK가 같은 16개 GPU를 TP16 / TP16+DCP16+EP16으로 재배치. PD prefill은 TP1 × PP16 | Unified가 세 운영 지점을 모두 서빙; Long-Context는 Prefill-only 전략 |
| GB200 4×4 | TP16/DCP16 | MNNVL 자동 감지 |
| H200 2×8 (Unified High-Throughput에서 4×8) | TP16/EP16 + symm-mem, Marlin + FlashMLA; High-Throughput은 4노드에 걸쳐 TP32/EP32, mem-frac 0.90, extra_buffer_lazy |
모든 노드에서 같은 block; 노드 간 NIC export(GLOO_SOCKET_IFNAME / NCCL_SOCKET_IFNAME, SGLANG_HOST_IP); NCCL_MNNVL_ENABLE=1 NCCL_CUMEM_ENABLE=1 유지 |
| H100 4×8 | TP32/EP32, Marlin + FlashMLA | K3 이미지의 SM90a 빌드; 모든 노드에서 NCCL/Gloo를 같은 NIC에 고정; post-weight headroom이 가장 작음 (80 GB) |
| MI350X/MI355X 1×8 | TP8/DCP8 ROCm/AITER (Unified Balanced) | AITER A8W4 FlyDSL MoE, 샤딩된 타깃 MLA KV를 사용하는 AITER prefill/decode attention, graph bs 최대 256, fp8 kvcache; DSPARK 지원. Activation-quant 및 fused-KDA-decode 노브: AMD ROCm/AITER 환경 |
| Ascend A3 Series 4×8 (32 cards / 64 dies) | TP64/DP4 + DeepEP | PD-mixed Unified only; DSPARK 내장; 모든 노드에서 GLOO/HCCL_SOCKET_IFNAME 고정 |
| Ascend 950PR/DT Series 4×8 | TP32/dp1 + DeepEP | PD-mixed Unified only; DSPARK 내장; 공유 experts / dense MLP가 attention-TP에 걸쳐 샤딩(--shared-experts-tp-size 4); radix cache 꺼짐; 모든 노드에서 GLOO/HCCL_SOCKET_IFNAME 고정 |
Blackwell DCP 참고 — DCP 셀은 모든 Blackwell 플랫폼의 Balanced와 High-Throughput이며, Unified와 Decode 역할 모두에서:
- DCP는 TP-replicated MLA KV를 샤딩하는 유일한 축이에요. Low-Latency는 이를 건너뛰어요.
--dcp-comm-backend는 설정하지 않은 채로 둬요(fabric-resolved: GB200/GB300에서fi_a2a, B200/B300에서a2a).- DCP 아래에서는
--enable-symm-mem없음(decode-graph 정확성을 위해 강제 비활성). - 명시적
tokenspeed_mla는--kv-cache-dtype을 fp8로 강제 재작성해요. 기본cutedsl_mla는 어느 dtype이든 서빙해요. - 여기서 계산기 비율은 1을 훨씬 웃돌아요(
r > 1합법):bfloat16상태는 수용을 사고,fp8KV는 컨텍스트를 사요. - a2a backend와 EP를 함께 쓰지 마요: a2a 버퍼가 DCP가 확보한 KV를 다시 가져가요. 측정 목적으로만 구성해요. a2a backend는
--moe-a2a-backend가 설정될 때 켜져요.
검증된 두 B300 1×8 Unified 셀을 제외하고, 이 정확한 형태로 서빙 라운드가 있는 셀은 없어요 — 이것들을 시작점으로 여기고 검증해요.
AMD ROCm/AITER 환경 (MI350X / MI355X). MI35x 셀은 SGLANG_USE_AITER=1 SGLANG_AITER_K3_OPT=1 AITER_FLYDSL_FORCE=1 AITER_SITUV2_A8W4=1을 내보내요 — 처음 셋은 AITER ROCm 경로, 그것의 K3 특화 fused 커널, FlyDSL MoE 커널을 켜요. 이 표의 나머지는 그 위에서 바꿀 수 있는 항목이에요. 여기 모든 것은 gfx950/ROCm 전용이며 다른 곳에서는 무효해요. 이 노브들은 위에서 고정한 20260903 일일 ROCm 이미지에 처음 포함돼요 — 오래된 이미지에서는 단순히 읽히지 않아요 — 그리고 두 SiTU 행은 ROCm/aiter#4534(FlyDSL 0.3.0) 이상의 AITER 리비전도 필요해요.
| Env var | 기본값 | 효과 |
|---|---|---|
AITER_SITUV2_A8W4=1 |
unset | GU-interleaved preshuffled weight layout의 AITER에서 A8W4 활성화 양자화를 가진 SiTU v2 MoE. 셀이 배포하는 성능 기본값. |
AITER_SITUV2_A4W4=1 |
unset | 대신 A4W4, 범용 separated shuffle layout. 수치적으로 맞지만 A8W4보다 느림 (8×MI35x에서 중간 출력 530.8 vs 537.3 tok/s). 둘 다 설정하면 A8W4가 우선 — SGLang은 AITER를 따르고 GU-interleaved layout을 유지. |
SGLANG_K3_KDA_FUSED_BACKEND=aiter |
unset | fused ROCm KDA decode 경계에 옵트인: f_b projection이 gfx950 FlyDSL 커널로 지연되어 decode가 f_b + convolution + recurrent state update + gated RMSNorm을 융합. 다른 값(또는 unset)은 unfused KDA 경로 유지. |
SGLANG_K3_FLYDSL_SOURCE |
auto |
fused decode를 뒷받침하는 FlyDSL 구현: auto는 SGLang vendored 커널을 선호하고 AITER 모듈로 폴백, sglang / aiter는 하나를 고정. 둘을 bisect하지 않는 한 건드리지 마요. |
fused KDA backend는 두 수준에서 fail-closed돼요: 모델 초기화 중에 플래그가 정확히 aiter 이고 gfx950 FlyDSL 커널이 importable일 때만 arm되고, 각 decode 단계는 dispatch 전에 shapes, dtypes, strides, state indices, 출력 버퍼를 재검증해요 — 예상치 못한 것은 에러 대신 스톡 KDA 구현으로 폴백돼요. Batch size 2는 별도로 검증된 커널 스케줄을 자동 선택하고, 다른 모든 배치는 원래 빌드 옵션을 유지해요. 69-레이어 그래프에서 측정 시 fused 경계는 9.20 → 8.38 µs/layer (−8.9%)이고, GSM8K 1319는 0.950.
3. Advanced Usage (고급 사용법)
3.1 Reasoning
K3는 항상 생각하며, kimi_k3 reasoning 파서(Playground의 Parsers 카드에서 Reasoning Parser 토글)가 그 thinking을 최종 답변에서 분리해요 — thinking은 message.reasoning_content에, 답변은 message.content에 들어가요. 추론 깊이는 reasoning_effort(low / high / max; 기본 max)로 제어해요.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
resp = client.chat.completions.create(
model="moonshotai/Kimi-K3",
messages=[{"role": "user", "content": "What is 15% of 240?"}],
reasoning_effort="high", # "low" | "high" | "max" (default max)
)
msg = resp.choices[0].message
print("Reasoning:", getattr(msg, "reasoning_content", None))
print("Answer:", msg.content)
Pending update...
3.2 Tool Calling
kimi_k3 tool-call parser를 활성화(Playground의 Parsers 카드에서 Tool Call Parser 토글)하면 message.tool_calls를 통해 구조화된 툴 호출이 표시돼요. K3는 thinking 모델이므로 후속 턴은 reasoning_content와 content 모두에 텍스트를 넣을 수 있어요 — 둘 다 출력해요. (Ascend NPU 레시피 — A3 및 A5 — 에서는 아직 지원되지 않아요.)
from openai import OpenAI
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
resp = client.chat.completions.create(
model="moonshotai/Kimi-K3",
messages=[{"role": "user", "content": "What's the weather in Beijing?"}],
tools=tools,
)
msg = resp.choices[0].message
print("Reasoning:", getattr(msg, "reasoning_content", None))
print("Tool calls:", msg.tool_calls)
Pending update...
3.3 HiCache (Hierarchical KV Caching)
K3의 하이브리드 HiCache는 페이징 MLA KV 와 KDA/mamba 상태를 L1 (GPU) / L2 (host) / L3 (Mooncake)에 계층화해요 — 긴 다중 턴 워크로드를 위해 Playground의 HiCache 카드에서 활성화해요.
- DCP 레시피(Blackwell Balanced / High-Throughput,
Unified와Decode역할)에서 L1+L2는 DCP를 유지해요, Spec Decode는 off 또는 DSPARK. B200에서는 DSPARK 파이프라인 붕괴도 이를 확장해요 (PP2 × DCPEP8 → DCPEP16). - 이 레시피에서 L3는 DCP 플래그를 없애요 (스토리지 키가 아직 dcp_rank-aware 하지 않음; 명령 힌트가 이를 알려주고 요청당 KV 용량이 줄어요). DCP만 빠져요: MLA KV는 TP-replicated로 되돌아가고 셀의 다른 병렬성은 유지되므로, B300/GB300/GB200은 순수 TP로, B200 Unified는
--pp-size 2/--ep-size를 유지해요. - Low-Latency와 Hopper 레시피는 모든 티어를 그대로 가져요.
3.4 PD Disaggregation
PD는 prefill과 decode를 별도 서버 그룹으로 분리해요. K3는 하이브리드이므로 전송은 페이징 MLA KV 와 KDA recurrent state 둘 다 옮겨요.
- 전송: 셀은 NiXL(RDMA)을 내보내요. Mooncake은 Playground에서 계속 선택 가능해요.
- 포트: prefill
30000, decode30100(파생 ZMQ/dist 범위는 공유 호스트에서 충돌하지 않아야 해요).--prefill뒤의 위치8998은--disaggregation-bootstrap-port와 일치해야 해요, 그렇지 않으면 decode 워커만 등록돼요. - Decode 상태 풀: chunk cache — 요청당 슬롯 하나.
--mamba-radix-cache-strategy는 무효해요.--disaggregation-decode-extra-slots를 고정해 두세요: 고정하지 않으면 32개 미만 요청에서 배치의 두 배로 기본값이 되고 그 이상에서는 0으로 돼요.
Deep PP for prefill
Deep PP는 GPU당 하나의 파이프라인 스테이지를 갖는 --tp-size 1이에요 — B300/GB300에서 --pp-size 8, B200/GB200에서 --pp-size 16. TP/EP collective과 달리 Pipeline P2P는 다음 microbatch의 compute와 겹치고, 각 스테이지는 전체 레이어(KV와 상태의 깔끔한 슬라이스)를 소유해요. --tp-size 1은 또한 컨텍스트를 사는 요인이에요: TP1 위에서는 MLA KV가 TP rank에 걸쳐 replicated되므로 TP2 × PP8은 같은 메모리에서 TP1 × PP16의 토큰 수의 절반 정도를 보유해요.
- GPU당 한 스테이지를 사용해요. 얕은 분할은 여전히 in-stage all-reduce를 지불하고 평평한 TP에 질 수 있어요.
- 여러 요청이 flight에 있을 때만 이득이 돼요. 8-GPU 플랫폼에서 그래서
Default가 TP8을 유지하고, 16-GPU 플랫폼에서 deep PP는 Default 운영 지점에서도 승리하므로 두 전략 모두 이를 사용해요 — GB200에서 ISL 8192 / concurrency 32, PP16 × TP1은 4550 prefill tok/s/GPU에 도달했고, PP8 × TP2는 3596, TEP16은 2407, TP16은 1652. concurrency ~8 미만에서는 파이프라인이 채워지지 않아 TEP16이 대신 리드해요 (1947 vs 1227) — 그럴 때는--tp-size 16 --ep-size 16을 사용해요. - DSPARK off(
pp_size == 1필요) — B200/GB200에서는Default에도 적용돼요. - 하나의 prefill 역할을 여러 decode 역할로 팬아웃하고, decode 쪽의 in-transfer KV를 예산에 반영해요.
python3 -m sglang_router.launch_router \
--pd-disaggregation \
--prefill http://<prefill-host>:30000 8998 \
--decode http://<decode-host>:30100 \
--host 0.0.0.0 --port 8000 \
--disable-circuit-breaker \
--health-check-interval-secs 999999
그런 다음 클라이언트는 개별 역할 서버 대신 라우터(:8000)로 요청을 보내요.
3.5 VLM Serving Profiles
오픈소스 K3 서빙 계약은 현재 이미지 입력만 지원해요 — 프로세서는 비디오와 오디오 입력을 거부해요.
VLM feature transport
명령 선택기에서 VLM Transport를 사용해요. Auto는 토폴로지 인식 시작점이며, 어떤 구성이 모든 워크로드에서 가장 빠르다는 주장은 아니에요.
| Picker 선택 | Processor-to-scheduler feature path |
|---|---|
| Auto · single-node Unified CUDA | CUDA IPC |
| Auto · Unified GB200/GB300 | IMEX가 있으면 CUDA VMM, 아니면 CPU |
| Auto · PD 또는 다른 토폴로지 | CPU |
| CPU | CPU, GPU feature pool 없음 |
CUDA IPC와 CUDA VMM은 베이스 GPU에서 최대 SGLANG_MM_FEATURE_CACHE_MB(기본 1 GiB)를 예약하고, 꽉 차면 텐서별로 CPU로 폴백해요. 이 설정은 EPD 인코더 출력이나 PD KV/KDA 전송을 제어하지 않아요. K3는 이미 기본적으로 2개의 processor 워커와 16개의 I/O 워커를 사용하므로, 튜닝하지 않으면 이 플래그들을 설정하지 않은 채로 둬요.
VLM compatibility
| Feature | K3 동작 |
|---|---|
| PD | 지원. 이미지 처리와 ViT는 prefill에서 실행되고, PD 전송은 PD disaggregation에서 설명한 대로 페이징 MLA KV와 KDA recurrent state를 모두 옮겨요. |
| EPD | 공개 kimi-k3 브랜치에서 지원. --encoder-only 비전 역할과 --language-only prefill 역할을 사용하고, 전체 EPD를 위해 일반 decode 역할을 추가해요. EPD 가이드 참고. |
| MM encoder DP | 내장. K3는 TP rank에 걸쳐 완전한 이미지를 샤딩하므로, unified, PD-prefill, encoder-only 역할에서 --mm-enable-dp-encoder를 설정하지 않은 채로 둬요. |
| MM feature transport | Processor-to-scheduler features 전용. EPD 인코더 출력과 PD KV/KDA 전송은 자체 backend를 사용해요. |
| ViT BCG | unified와 encoder-only 역할과 호환되지만, 아래 HBM trade-off를 측정한 후 반복되는 encoder 모양에만 권장. |
Should ViT BCG be enabled?
일반 서빙에서는 ViT BCG를 끄고, 반복되는 이미지 모양과 여유 HBM이 있는 ViT-only / EPD encoder 워크로드에만 SGLANG_VIT_ENABLE_CUDA_GRAPH=1을 활성화해요.
- 이득은 encoder에 국한돼요 — full-model 서빙에서 안정적인 end-to-end TTFT/TPOT 이득은 없어요.
- 각 캡처된 그래프는 HBM(graph + 항목별 메타데이터)을 유지해요. 자신의 모양에서 측정해요.
- 기본 캐시는 두 번의 hit 후 캡처하고 6,144 토큰을 넘으면 eager로 폴백해요. 측정 없이 키우지 마요.
Low-HBM VLM
이 프로필은 피크 동시성보다 HBM 헤드룸 유지가 더 중요할 때 사용해요. GPU feature pool을 제거하고, ViT BCG를 비활성화하고, 컨텍스트 윈도우를 절반으로 줄이고, 동시성을 상한하고, 정적 메모리 타깃을 낮춰요:
sglang serve \
--trust-remote-code \
--model-path moonshotai/Kimi-K3 \
--tp-size 8 \
--context-length 65536 \
--enable-symm-mem \
--mem-fraction-static 0.82 \
--mm-feature-transport cpu \
--reasoning-parser kimi_k3 \
--tool-call-parser kimi_k3 \
--host 0.0.0.0 \
--port 30000
--mem-fraction-static 0.82는 보수적인 B300 시작점이며 휴대용 최솟값이 아니에요: 시작 시 메모리 부족이 보고되면 0.85 쪽으로 올리고, HBM을 다른 워크로드에 돌려줘야 하면 컨텍스트/동시성을 먼저 줄여요. 정밀도 레버(fp8_e4m3 KV, bfloat16 SSM state)는 훨씬 더 많이 절약하지만 accuracy-gated 상태로 남아요.
3.6 Large-Scale Serving Presets (16–64 GPUs, Blackwell)
KDA 상태 풀은 동시성 상한이에요 — DP, EP, DCP는 이를 샤딩하지 않아요. 오직 attention-TP 폭, SSM dtype, 캐시 전략만 GPU당 비용을 바꿔요. MLA KV는 싸게 줄이거나(fp8) 중복 제거(DCP)할 수 있어요.
N = 8k GPU에서 두 개의 프리셋이 나와요:
| 프리셋 | 무엇을 맞바꾸는가 | 용도 |
|---|---|---|
Peak Throughput — dp = k, attention-TP 8 |
상태가 8-way 샤딩. 단계별 KDA all-reduce는 하나의 8-GPU B200/B300 노드 안에 머물거나, MNNVL을 통해 두 4-GPU GB200/GB300 노드에 걸침. --kv-cache-dtype fp8_e4m3이 핵심 — bf16 KV는 replica당 128 요청에 맞지 않음. |
최대 지속 TPS — 기본 대규모 형태. |
Peak Capacity (+DCP8) — dp = k + --dcp-size 8 |
attention-TP 그룹의 MLA KV를 중복 제거: 같은 엔진 처리량에서 동시성 상한 +72%, 약 1.8× ITL. | 컨텍스트 ≥ ~16K, 또는 replica당 동시성이 128 초과. |
- Radix cache는 프리셋과 독립적이에요: prefix-free 트래픽(오프라인 배치, evals)에서는 꺼요(Playground의 Prefix Cache 카드) — 요청당 4–5개 대신 상태 슬롯 하나.
- 완전 data-parallel 극한(
--dp-size= GPU 수, attention-TP 1) — 64-GPU 스윕의 GPU당 ~3K tok/s 뒤의 형태 — 은 프리셋이 아니에요: 288 GB GPU 전용, radix 강제 off, 프리셋 형태와의 head-to-head 없음.
B200/B300에서 32 GPU의 Peak Throughput 프리셋 (4 노드 × 8; 모든 노드는 자신의 --node-rank로 같은 명령 실행). GB200/GB300에서 같은 32-GPU 모양은 8 노드 × 4를 사용하고, Playground는 --nnodes 8을 내보내요:
SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK=20480 \
sglang serve \
--trust-remote-code \
--model-path moonshotai/Kimi-K3 \
--tp-size 32 --ep-size 32 \
--enable-dp-attention --dp-size 4 --enable-dp-lm-head \
--nnodes 4 --node-rank <rank> --dist-init-addr <node0-ip>:20000 \
--moe-a2a-backend megamoe --moe-runner-backend deep_gemm \
--kv-cache-dtype fp8_e4m3 \
--mamba-ssm-dtype bfloat16 \
--mamba-radix-cache-strategy extra_buffer_lazy \
--mem-fraction-static 0.92 \
--reasoning-parser kimi_k3 --tool-call-parser kimi_k3 \
--host 0.0.0.0 --port 30000
per-replica 형태를 고정하고 replica 수만 옮겨서 확장해요. 풀 크기 조정은 계산기 기반 --mamba-full-memory-ratio에 달려 있으며, 이것은 DP, DCP, 정밀도, 추측을 반영해요:
| GPUs | B200/B300 nodes | GB200/GB300 nodes | --tp-size / --ep-size |
--dp-size |
|---|---|---|---|---|
| 16 | 2×8 | 4×4 | 16 | 2 |
| 32 | 4×8 | 8×4 | 32 | 4 |
| 64 | 8×8 | 16×4 | 64 | 8 |
Peak Capacity에서는 --dcp-size 8을 추가하고 Mamba ratio calculator로 풀 분할을 다시 도출해요.
두 프리셋 모두 Playground에서 한 번 클릭으로 사용할 수 있어요: Cluster Size와 Large-Scale Preset을 고르면 전체 명령이 보여지는 셀 위에 구성돼요.
프리셋이 이미 내린 결정:
- MegaMoE +
deep_gemm— K3의 SiTU 활성화로 이 대규모 DP/EP 처리량 프리셋이 사용하는 fused DeepGEMM all-to-all/MoE 경로. - SP-MoE와 shared-expert overlap은 EP a2a 아래에서 자동으로 작동해요. K3 all-reduce fusion은 그렇지 않아요.
- Spec Decode는 Deploy 노브를 따름. 대형 배치에서 수용이 얇아져요. spec × EP × DP-attention은 8-GPU EP8 × DP2(전체 GSM8K)에서만 검증돼요 — 이 규모에서는 실험적.
더 알아보기 (Learn more)
- Kimi-K3 (HuggingFace) — 모델과 공식 문서
- Kimi-K3 Quickstart — 빠른 시작
- Kimi-K3-DFlash (HuggingFace) — DFLASH 드래프트 모델
- 공식 SGLang 설치 가이드 — SGLang 설치 방법
- EPD 가이드 — 인코더-프리필-디코드 분리