Kimi-K3-W4A16-RTN

Kimi K3 on a single NVIDIA A100 80GB.

A weight-only quantisation of Moonshot AI's Kimi K3 (2.8T total / 104B activated parameters) that loads and generates on one A100 80GB GPU, with the routed experts held in host RAM. No Ampere-targeted K3 build existed for vLLM, so this was made to fix that gap.

On one A100 80GB GPU this model gets 1 token/second for a single request and a ~100-minute model load. Useful if you have one A100 in a machine with well over 1.3 TB of RAM and want to run K3 at all. This also works with more than one GPU, but ~1tok/s is the base speed on one GPU.

What was changed

Routed experts and attention re-encoded from MXFP4/BF16 into compressed-tensors pack-quantized, served by vLLM's Marlin kernels. Activations stay BF16 (W4A16 / W8A16). Round-to-nearest only — no calibration data, so no dataset is baked into these weights.

component scheme size added RMS error
routed experts (896 × 92 MoE layers) int4, channelwise, symmetric, RTN + clip search 1,267.88 GiB 8.07% vs the released MXFP4 values
attention (every self_attn.*proj) int4, group size 128, symmetric, RTN 16.85 GiB 10.32% vs BF16
shared experts int8, channelwise, symmetric, RTN + clip search 11.32 GiB 0.95% vs BF16
embeddings, lm_head, router gates, norms, vision tower unchanged BF16 ~16.5 GiB —
total ~1,314.6 GiB

Errors were measured by round-tripping each tensor through compressed-tensors' compress()/decompress(). Weight error is a proxy, not a quality measurement — see Evaluation for the real numbers.

Why channelwise: during post-load preparation vLLM's Marlin MoE path materialises the quantisation scales on the GPU, where the CPU offloader cannot reach them, so the scale set must fit in whatever VRAM is left. For K3's experts that is around 158 GB for MXFP4 as published, around 39.6 GB for int4 g128, and around 1.5 GB channelwise. Marlin supports only group sizes {-1, 32, 64, 128}, so channelwise was the only scheme that fits. It costs ~1.1 points of added weight error versus g128. Shared experts run on every token and are GPU-resident, so int8 there cuts their error from 10.15% to 0.95% for +5.4 GiB and no measurable slowdown.

Requirements

GPU 1 × A100-SXM4-80GB (compute capability 8.0), PCIe gen4 x16
host RAM ~1.3 TB consumed by the offloaded experts (tested on a 2 TB machine)
disk ~1.3 TiB
software vLLM 0.28.0, compressed-tensors 0.17.0, PyTorch 2.13.0

Other configurations are untested.

Usage

# Required. Without it vLLM pins the offloaded weights twice and the load fails partway.
export VLLM_WEIGHT_OFFLOADING_DISABLE_PIN_MEMORY=1

# Do NOT set PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True — incompatible with UVA
# offload; fails with "cudaHostAlloc failed".
from vllm import LLM, SamplingParams

llm = LLM(
    model="Fluffy/Kimi-K3-W4A16-RTN",
    tensor_parallel_size=1,
    max_model_len=8192,
    gpu_memory_utilization=0.90,
    kv_cache_dtype="bfloat16",       # fp8 KV is refused on Ampere for MLA
    cpu_offload_gb=1400,
    cpu_offload_params=["experts"],  # routed experts live in host RAM
    linear_backend="marlin",
    trust_remote_code=True,          # K3's tokenizer is custom code
    enforce_eager=True,
)

out = llm.generate(["The three branches of government are"],
                   SamplingParams(max_tokens=32, temperature=0))
print(out[0].outputs[0].text)

K3's chat template lives in tokenization_kimi.py, not a Jinja chat_template, and defaults to thinking on at thinking_effort="max". Moonshot's published evaluation sampling is temperature=1.0, top_p=0.95. Image input is verified through LLM.chat() with chat_template_kwargs={"thinking": True, "thinking_effort": "low"}.

Performance

Measured on one A100 80GB:

value
model load 98–114 min from network storage
GPU memory 46.15 GiB of weights; 69.1 of 79.3 GB used at gpu_memory_utilization=0.90
KV cache 108,544 tokens (BF16) at max_model_len=8192
decode, single request 0.91–0.96 tok/s
decode, 32 concurrent ~1.6 tok/s aggregate — only ~1.7× single
prefill ~49 s per forward pass + ~11 ms/token (512–4,096 tokens)

Decode is bandwidth-bound: ~28 GiB of expert weights cross PCIe per generated token, at 28.7 GB/s (91% of gen4 x16). That is also why batching buys so little — concurrent requests share the expert transfer. Prefill behaves differently: from 512 tokens up, a forward pass costs a roughly fixed ~49 s (one full sweep of the expert set) plus ~11 ms/token, so a 4,096-token prompt takes ~94 s — about 44 tok/s.

Evaluation

Everything below is at thinking_effort="low". Moonshot's official scores are at max effort, and no low-effort reference is published. We ran low effort because generation here is ~1 tok/s. So these are not like-for-like: each gap mixes quantisation loss with the effect of reduced reasoning, and we cannot separate the two. They are shown side by side so you can judge for yourself.

benchmark this build (int4, low effort) Kimi K3 official (full precision, max effort)
OCRBench (1,000 samples) 0.879 ± 0.010 0.89
GPQA Diamond (198 questions, 1 epoch) 0.843 ± 0.026 0.935

Both were run through Moonshot's own Kimi-Vendor-Verifier (commit 3dad65a), which Moonshot uses to check that third-party deployments serve an undegraded model, with its published K3 parameters (temperature 1.0, top_p 0.95).

OCRBench: all 1,000 samples, max_tokens 16384, no truncation, no errors. Per category from 98% (regular text) to 53% (handwritten mathematical expressions). The verifier's list of correctly-serving max-effort deployments spans 0.878–0.897, so this build at low effort lands inside that band.

GPQA Diamond: inspect_evals/gpqa_diamond (the port of OpenAI simple-evals) driven through the verifier's opensource provider, all 198 questions, 0-shot chain-of-thought, max_tokens 16384, 1 epoch — the harness averages 4 by default, so the ±0.026 is wider than a standard run's. 198/198 completed, 0 errors, nothing truncated. By domain: physics 93.0%, biology 78.9%, chemistry 77.4%. For reference, the benchmark's authors measured 65% for PhD experts answering within their own field.

BEAM (1M-token context) cannot run on this hardware: the KV cache holds ~108K tokens.

Known limitations

  • Long context is limited in practice by the KV cache (~108K tokens at BF16) and by prefill cost. An fp8 KV cache would extend it, but vLLM refuses one on Ampere for K3's MLA layers: the check is written as kv_cache_dtype.startswith("fp8"), so it gates e5m2 as collateral even though Triton supports e5m2 on every NVIDIA GPU. This is a software limit, not a hardware one — a patched vLLM should lift it.
  • Needs ~1.3 TB of host RAM, and loading it will fill your page cache — on a busy machine, host memory fragmentation can make the final cudaHostAlloc pin fail.

License

Kimi K3 is released by Moonshot AI under the Kimi K3 License. This quantised derivative is distributed under the same license, with the original LICENSE and copyright notice included unchanged. Note its conditions: a Model-as-a-Service business exceeding $20M in revenue over any consecutive 12 months requires a separate agreement with Moonshot AI, and products with more than 100M monthly active users or more than $20M in monthly revenue must prominently display "Kimi K3". See LICENSE.

Acknowledgements

All model capability is Moonshot AI's; this build only changes how the weights are stored.

Quantised and evaluated on the MLCore cluster at Beth Israel Deaconess Medical Center, whose compute made this possible. This is an independent side project and is not a BIDMC product or an endorsement by BIDMC.

Thanks to the vLLM and compressed-tensors projects, whose UVA offloader and Marlin kernels this build depends on.

Downloads last month
32
Safetensors
Model size
2.7T params
Tensor type
F32
·
I32
·
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for Fluffy/Kimi-K3-W4A16-RTN

Quantized
(50)
this model