Kimi K3 studies / 02

Memory: Kimi K3
on 512 GB200s

FP32 where training keeps its history. BF16 where the model computes. The hard part is understanding what is live at the same time.

2.780Tlogical parameters
512GB200 GPUs
184.31 GiBreported HBM per GPU
60.70 GiBaverage FP32 update-state tally

Default case: full Kimi K3, PP8 / CP1 / TP1 / DP-shard64 / EP64, DistMuon plus AdamW, one 4K row per microbatch, and 64 microbatches in one 1F1B schedule. This is a training memory study, not an inference KV-cache calculator.

First, name the copies

FP32 training does not mean FP32 GEMMs

In this recipe, the sharded resident parameter is the master weight. FSDP makes a BF16 compute view for forward and backward; the optimizer updates the FP32 resident shard. Do not count a separate, full-model BF16 master copy on every GPU.

Resident masterFP32Sharded parameter, updated by the optimizer
FSDP compute viewBF16Cast / gather the weights needed by compute
Gradient historyFP32Reduction and optimizer-visible gradient shards
Muon momentumFP32One persistent tensor, in the gradient's dtype
Object Dtype Lifetime / ownership
Resident / master parameter FP32 Storage shard; persists across updates
Forward/backward parameter view BF16 Unsharded over FSDP, but still local to PP and EP
Gradient reduction / accumulation policy FP32 Unreduced PP gradients can outlive one microbatch
Optimizer-visible param.grad FP32 Matches the FP32 resident parameter in this recipe
Muon momentum FP32 One tensor with the storage gradient's layout
AdamW first and second moments FP32 Two tensors for the small AdamW remainder
Model GEMMs / main activations BF16 Exceptions for selected pointwise arithmetic and statistics
The unavoidable bill

Muon needs one momentum, not two Adam moments

The first study counted 2,779,931,738,208 parameters. In this optimizer assignment, 2,777,072,664,576 use DistMuon and 2,859,073,632 use AdamW: about 99.897% versus 0.103%. Routed expert matrices alone are 97.94% of the model. Selecting 16 of 896 experts reduces compute per token, not the number of trainable weights or optimizer states we must store.

DistMuon parameter4 + 4 + 4 = 12 bytes

FP32 master + FP32 gradient + FP32 momentum

AdamW parameter4 + 4 + 4 + 4 = 16 bytes

FP32 master + gradient + two FP32 moments

Update-state tally = 12 P_muon + 16 P_adam
                   = 33,370,617,153,024 bytes
                   = 30.35 TiB across the logical model

Ideal 512-way average = 60.70 GiB / GPU

This tally assumes all trainable parameters have gradients and optimizer state. It is not a measured peak or an assertion that every gradient exists throughout forward. It excludes BF16 compute views, unsharded accumulation, activations, padding, communication, and optimizer workspaces. The familiar “16 or 17 bytes per parameter” shortcut is not a universal memory law.

256 GPUs121.40 GiB average update-state tally
512 GPUs60.70 GiB average update-state tally

Twice the GPUs halves evenly distributed resident state. It does not automatically halve a gathered compute unit, microbatch activations, or NCCL workspace.

Explore the ownership

A memory lab, with its assumptions exposed

Pick a pipeline rank. The state ledger uses the actual 93-layer structure, including the first dense FFN, last MLA layer, embeddings, vision pathway, and output head. The backward budget adds explicitly modeled working sets. It is a planning model, not a substitute for measuring an implementation.

After reduction / optimizer-state tally63.23 GiB

Planning subtotal + chosen reserve

Backward planning budget

Full deferred gradients replace reduced shards in this phase; they are not added on top of an entire second gradient copy. Actual reduction can briefly overlap both and needs additional buffers.

Allocation category Modeled size What the number means

PP, EP, and FSDP divide different things

PP8

Own a model slice

Ranks 0–6 own 12 layers each; rank 7 owns the remaining nine. Embeddings and vision sit at the front, the output head at the back. Pipeline stages are not perfectly balanced, so a model-wide average hides the worst rank.

EP64

Own 14 experts per MoE layer

896 / 64 = 14. The 64 ranks exchange tokens, rather than all 512 ranks participating in one EP group. Dense attention and shared-expert weights are not divided by EP.

FSDP64 / expert FSDP1

Shard the resident history

512 / PP8 = 64 ranks per pipeline stage. Dense master/gradient/state shards span those 64 ranks. EP already divides the expert bank by 64, leaving expert FSDP = 64 / 64 = 1: no further expert-storage division.

On one pipeline stage, let D = non-routed parameters and E = routed parameters.

Resident parameters / GPU = D / dense_FSDP + E / (EP * expert_FSDP)
BF16 gathered stage view  = 2 * (D + E / EP) bytes

At PP8 / EP64 / FSDP64: expert_FSDP = 1

Increasing EP at fixed PP and GPU count can shrink the expert compute slice while reducing the expert FSDP degree. It does not create additional aggregate HBM. And the 512 GPUs do not form one pooled allocation space: every rank must stay within its own device capacity.

Memory follows lifetime, not global batch

64 microbatches do not mean 64 saved forwards

In ordinary 1F1B, a rank fills its local pipeline, then alternates forward and backward. Backward releases that microbatch's saved activations. With eight physical stages and enough microbatches, rank 0 can hold eight unfinished forwards; rank 7 needs only one. This is a logical schedule bound, excluding implementation-specific send/receive buffers and keepalives.

Peak unfinished forwards by PP rank

Peak unfinished forwards on rank r = min(microbatches, PP - r)

At the default shape, local packed tokens T = rows × context = 4096. One BF16 [T, 7168] stream is 56 MiB. Twelve checkpointed layer inputs across five unfinished forwards on rank 3 give a boundary-input floor of 3.28 GiB. The growing AttnRes bank and kernel workspaces are additional, not hidden inside that number.

Global tokens per update are DP × microbatches × rows × context: 64 × 64 × 1 × 4096 = 16,777,216. Increasing microbatches beyond the 1F1B live-forward bound mostly extends the schedule; increasing rows or context increases each microbatch's activation and routing footprint. Two 2K rows and one 4K row have the same flattened token count, but different document attention boundaries.

KDA's fixed-size inference state does not make its training activations constant-size: token and chunk intermediates still need storage or recomputation. Varlen FlashAttention avoids materializing the full attention-probability matrix for MLA, but still needs Q/K/V, outputs, and backward statistics. Neither attention path has a zero activation-memory bill.

An interactive fitting walkthrough

From a 30-TiB state bill to a local budget

Each step changes one ownership or activation assumption. The same FP32-master / FP32-state / BF16-compute policy is kept throughout. Component lengths below use a logarithmic axis; add the numeric values, not bar lengths.

1 MiB1 GiB64 GiB64 TiB

Model versus implementation

A measured run is the capacity proof

4K / 512-GPU reference146.18 GiBmaximum logged tensor allocation
Device capacity184.31 GiBreported by the training runtime
Arithmetic difference38.13 GiB20.69% — not guaranteed usable slack

The reference completed 12 updates with FP32 resident state, BF16 compute, PP8 / FSDP64 / EP64, full layer checkpointing, varlen attention, compiled pointwise regions, no CUDA graphs, and forced-balanced HybridEP routing. It demonstrates short-run feasibility of this specific configuration; it is not a general capacity guarantee or a convergence result. The fixed reference stays fixed when you change calculator controls.

The calculator deliberately does not label the gap between its subtotal and 146.18 GiB as “activation memory.” That would invent a decomposition. Some important reasons implementations exceed a state-only estimate:

Deferred PP gradients

Gradient accumulation can retain unreduced stage gradients until the schedule finishes. A reduced FP32 shard and an unreduced FP32 dense gradient differ by the FSDP factor. Repeated backward calls do not create 64 independent parameter-gradient histories.

Gather / reduction buffers

A casted input shard, all-gather output, compute view, and reduce-scatter input may briefly overlap. Retaining every in-flight buffer defeats an otherwise good memory budget. Resharding and bounded buffer lifetimes matter as much as dtype.

SiTU-GLU temporaries

Gate/up products cover routed assignments, not just original tokens. Eager FP32 pointwise intermediates occupy HBM. Compiling the pointwise region can fuse intermediates and shorten their lifetimes; it does not compress the FP32 master weights.

Muon working layouts

DistMuon redistributes shards into logical matrices before its update. The storage layout, compute layout, communication buffers, BF16 iteration copy, and Gram matrices have different lifetimes. Transient buffers avoid paying optimizer-only storage during model compute.

Memory outside PyTorch

NCCL can allocate workspace outside PyTorch's caching allocator. Unused cached blocks are not necessarily available to NCCL. Communicator initialization order and runtime connection policy can therefore change whether an otherwise identical run starts.

Graphs and precision shortcuts

CUDA graphs can retain private pools and captured buffers. BF16 reduction alone does not shrink FP32 master, optimizer-visible gradient, or momentum shards. Neither graph capture nor lower reduction precision is a free state-memory reduction.

Tensor allocation, allocator reservation, and total device usage are different measurements. The reported 38.13-GiB difference ignores external allocations and fragmentation. Check every PP rank and the first optimizer update, not only the first forward. Also check later iterations, when momentum and caches are populated.

Sources and accounting notes

  1. Kimi K3 technical report and released configuration: architecture and logical dimensions.
  2. TorchTitan Kimi K3 and DistMuon: parameter shapes, momentum storage, and Newton–Schulz computation. Optimizer assignments and lifecycle settings refer to the recipe analyzed here, not every upstream recipe.
  3. PyTorch FSDP and pipeline parallelism: mixed precision, sharded storage, and schedule concepts.
  4. Presentation inspired by Edward Yang's Hopper memory study. This page uses Kimi K3, GB200, Muon, and the stated FSDP/PP policy; it does not transplant DeepSeek's AdamW or DualPipe assumptions.

GiB = 230 bytes; TiB = 240 bytes. Structural totals match study 01. Shards are modeled by ideal division, ignoring per-tensor padding. Non-default PP splits are contiguous illustrative partitions, not validated launch recipes. The selected-activation model omits kernel-specific state and may include candidates an implementation aliases or recomputes. No internal run links, data paths, or cluster identifiers are included.