tpu-megakernels README

The project's README from github.com/Inferact/tpu-megakernels. As one markdown file: README.md.

TPU megakernels for Kimi K3 and Qwen3.8-27B

TPU megakernel: 709 tokens per second on Kimi K3, 16x TPU v7 vs 452 on 16x GB200

Companion code for the blog post 700 TPS on Kimi K3: A Case for TPU Megakernels.

This repository contains fused decode implementations for two models:

Both demos support terminal interaction and an OpenAI-compatible HTTP server.

Results

With speculative decoding at an acceptance length of 6, the megakernels reach 709 accepted tokens per second on Kimi K3 (16× TPU v7 vs 16× GB200, 1.57×) and 1,515 on Qwen3.8-27B (4× TPU v7 vs 4× GB200, 2.18×):

Speculative decode throughput at acceptance length 6: Kimi K3 709 vs 452 tokens/s; Qwen3.8-27B 1,515 vs 695 tokens/s

DSpark keeps a large lead at shorter acceptance lengths as well:

Accepted tokens per second with DSpark speculative decoding at acceptance lengths 3 and 6

Without speculative decoding, the megakernels deliver roughly 1.4–2× the decode throughput of the GB200 baseline at batch sizes 1 through 8:

Aggregate decode throughput at batch sizes 1, 2, 4 and 8, TPU megakernel vs GB200 baseline

See the blog post for the full analysis and measurement setup.

Setup

Create the environment from the repository root:

uv sync

The launchers run Hugging Face in offline mode, so the model snapshots must already be present in the cache selected by HF_HOME, or supplied as explicit local paths. All scripts automatically load an optional, untracked .env file from the repository root. A typical configuration is:

HF_HOME=/path/to/huggingface
KIMI_PRESHARDED_WEIGHTS=/path/to/kimi-k3-tp32
KIMI_DRAFT_PRESHARDED_WEIGHTS=/path/to/kimi-k3-tp32/dspark

The Kimi pre-sharded variables are optional. Without them, the demo prepares its kernel layouts from moonshotai/Kimi-K3 and RedHatAI/Kimi-K3-speculator.dspark. The Qwen demo loads Qwen/Qwen3.8-27B and z-lab/Qwen3.8-27B-DFlash2; packed weight containers under checkpoints/qwen38-tp8 (or $QWEN_PACKED_WEIGHTS when set) are used instead when present. The optional KIMI_CHECKPOINT_REVISION, KIMI_DRAFT_REVISION, QWEN_CHECKPOINT_REVISION, and QWEN_DRAFT_REVISION variables pin the commits resolved from the HF_HOME cache for the default repositories. Explicit --checkpoint, --draft, --weights, and --draft-weights arguments override these defaults.

Kimi requires a four-node Slurm allocation with eight TPU devices per host. Qwen uses one host with eight TPU devices and can run on the first node of any allocation containing at least one host.

CPU correctness tests

Run the fast reference and CPU-interpreter tests with:

JAX_PLATFORMS=cpu uv run pytest -m "not cpu32"

Run the complete suite, including 32-device integration tests, with 32 virtual CPU devices:

JAX_PLATFORMS=cpu \
XLA_FLAGS=--xla_force_host_platform_device_count=32 \
uv run pytest

These tests validate numerical behavior, not TPU-specific Mosaic lowering, layouts, VMEM capacity, DMA scheduling, collectives, or performance.

OpenAI-compatible servers

Start the Kimi K3 + DSpark server on a four-node allocation:

JOBID=<four-node-job> bash scripts/demo_kimi_dspark.sh \
  --serve 0.0.0.0:8000 --context 4096 --max-tokens 512

Start the Qwen3.8-27B + DFlash2 server on the first host of an allocation:

JOBID=<slurm-job> bash scripts/demo_qwen_dflash.sh \
  --serve 0.0.0.0:8000 --context 2048 --max-tokens 512

Both servers expose GET /health, GET /v1/models, POST /tokenize, POST /detokenize, POST /v1/completions, and POST /v1/chat/completions. Kimi uses DSpark by default and supports greedy or temperature/top-p generation; --target-only serves the target megakernel without speculation. Qwen uses DFlash2 by default with greedy generation; --no-spec selects its plain single-token decoder. Omit --serve to use either launcher interactively.

Source layout

Generated weights, checkpoints, compilation caches, evaluation output, benchmark output, and Slurm logs are excluded from version control.

Citation

If you use this codebase or build on our results, please cite the companion blog post:

@misc{novack2026tpumegakernels,
  author       = {Novack, George and Liu, Xuting and Ma, Jeff and Kwon, Woosuk},
  title        = {700 TPS on Kimi K3: A Case for TPU Megakernels},
  howpublished = {\url{https://inferact.ai/blog/tpu-megakernels}},
  year         = {2026},
  month        = sep,
  note         = {Inferact blog post, September 23, 2026},
}

tpu-megakernels (Inferact/tpu-megakernels)

Searching Database…

What is this?A companion research repo with fused 'megakernel' decode implementations for two models on Google TPUs: Kimi K3 with DSpark speculative decoding, and Qwen3.8-27B with DFlash2 speculative decoding, written to accompany the blog post '700 TPS on Kimi K3: A Case for TPU Megakernels'.
Is this a general-purpose inference library or a benchmark demo for these two models?It is companion demo code built specifically around two model pipelines rather than a general-purpose serving library: each model gets its own fused TPU kernel plus an interactive terminal mode and an OpenAI-compatible HTTP server.
How do I get this running?Set up the Python/JAX environment from the repository root, make sure Hugging Face model snapshots are cached (launchers run HF in offline mode), then run demokimidspark.py or demoqwendflash.py interactively or with --serve to start the HTTP API.
Do I need real TPU hardware (and a Slurm cluster) to run this?Yes — Kimi K3 needs a four-node Slurm allocation with eight TPU devices per host (32 total), and Qwen3.8-27B needs one host with eight TPU devices; the CPU correctness tests exist but don't exercise real TPU execution.
Do the CPU tests prove the TPU kernels actually work correctly on hardware?No — the CPU/interpreter test suite only checks numerical correctness; it does not validate TPU-specific Mosaic lowering, memory layouts, VMEM capacity, DMA scheduling, collectives, or real performance.
Does this run on GPUs, or only on Google TPUs?It only runs on Google TPU devices; GB200 GPUs appear solely as the performance baseline the megakernels are benchmarked against, not as a supported execution target.
How much faster are these megakernels than GPUs?With speculative decoding, Kimi K3 reaches 709 accepted tokens/sec on 16x TPU v7 vs a 16x GB200 baseline (1.57x), and Qwen3.8-27B reaches 1,515 tokens/sec on 4x TPU v7 vs 4x GB200 (2.18x). Without speculation, the TPU kernels still deliver roughly 1.4-2x GB200 decode throughput at batch sizes 1-8.
What are DSpark and DFlash2?They are the fused speculative-decoding schemes bundled with each model: DSpark pairs Kimi K3 with one anchor and seven draft rows, while DFlash2 gives Qwen3.8-27B's dense BF16 decoder an optional fused draft/speculation loop.
What does the OpenAI-compatible server expose?Each server exposes GET /health, GET /v1/models, POST /tokenize, POST /detokenize, POST /v1/completions, and POST /v1/chat/completions, so it can be queried like a standard OpenAI API endpoint.
Why build custom TPU megakernels instead of using a standard inference framework?Fusing the whole decode step — attention, MoE, normalization, residuals, and collectives — into a single TPU kernel cuts per-op dispatch overhead, letting TPU v7 chips match or beat GB200 GPUs on decode throughput, as detailed in the companion blog post.
Creator
Inferact
Size
1.4 MB
Stars
162
Updated
CommitOct 15
Age
25d
Commits · 90 Days