loopyt dcf00aca7c feat(h20): enable FlagGems end to end, from an allow-list of ops proven equal to PyTorch
`DEEPINFER_ENABLE_FLAGGEMS=1` turns it on. Verified on all 8 DP ranks: exit=0, 8/8 ranks agreeing,
no kernel fallbacks, `hard failures: none`, correct answers. 19 ops actually dispatched, 152 call
sites, 43 registrations from 37 requested names.

The default is `flag_gems.only_enable(include=[...])`, not `enable()`, and that is the whole design:

* allow-list -- every intermediate state is safe (unproven ops stay on PyTorch, which is correct by
  construction); an incomplete list costs throughput, not correctness.
* deny-list -- I tried it first. Five full engine runs, one new defect each: `cat` (e8m0 dtype),
  `mul` (broadcast shape), `topk` (compile blowup), `rms_norm` (signature), `mm` (compile assert).
  The method requires being bitten before it can exclude, and every state along the way is unsafe.

That matches the instruction this was built to: use what works, leave the rest.

Where it is called is not incidental. `import flag_gems` initialises a CUDA context -- measured,
`torch.cuda.is_initialized()` flips on the import alone, before `enable()`. A `sitecustomize`
injector therefore put all 8 ranks on device 0 and NCCL refused with "Multiple Ranks are using the
same GPU". It now runs inside `create_llm`, after `setup_cuda_visible_devices`, which is the same
hazard already documented there for the profiler.

Defects found and documented rather than worked around, because each one is worth knowing:

* `mul` returns the *first operand's shape* when broadcasting expands it: (1,64,8)*(4,1,8) gives
  (1,64,8), and (64,1)*(1,128) gives (64,1). Silent, no error, fewer elements computed. It made
  `engram_hash_ref` disagree with PyTorch during a real run. add/sub/div/maximum/minimum all
  broadcast correctly, so it is mul's own bug.
* `cumsum` drifts by up to 1.0 over a 512-element bf16 row (tolerance ~0.17) -- bf16 accumulation.
* `topk`'s compile time explodes with k: 4.8 s at k=8, 19 s at k=64, >180 s at k=512, and the
  sampler asks for 4096. py-spy put all 8 ranks at 100% CPU inside `make_llir` with every GPU idle.
* `cat` raises `KeyError: 'float8_e8m0fnu'` on the model's UE8M0 scale tensors during weight load.
* `mm` passes every isolated probe yet fails inside the engine at `general_mm`; trigger unknown, so
  GEMMs stay on cuBLAS, which is faster anyway.

Two methodological errors in my own measurements, both fixed and both recorded:

1. After `enable()`, `torch.mul` *is* `flag_gems.mul`, so the first version of the mul A/B compared
   FlagGems with itself and reported a perfect score. All references are now computed before enable.
2. "ok" did not mean FlagGems ran. `torch.bitwise_xor` has no FlagGems registration at all, so that
   "match" was PyTorch against PyTorch. `screen_ops.py` now checks registration first and reports
   such cases as `skip` rather than pass.

Name mismatch is its own trap: FlagGems registers `add` bare but `eq.Scalar`, `where.self`,
`repeat_interleave.self_int`, `_softmax` (not `softmax`), `div.true_divide`. Asking for `softmax`
silently registers nothing. The bootstrap now expands names against `flag_gems._FULL_CONFIG` and
warns on anything unresolved -- which is how `softmax` was found to need `_softmax`.

Output is not token-identical to the no-FlagGems build (diverges at the first token), but two runs of
the same FlagGems config are bit-identical, so the difference is Triton-versus-eager accumulation
order, not nondeterminism. Answers stay correct and coherent.
2026-10-26 12:53:47 +08:00
csrc initial commit 2026-10-20 12:09:42 +08:00
deep_cluster style(sm90): satisfy ruff and add the missing type annotations 2026-10-21 17:09:08 +08:00
deepinfer feat(h20): enable FlagGems end to end, from an allow-list of ops proven equal to PyTorch 2026-10-26 12:53:47 +08:00
doc update Q&A documentation 2026-10-20 17:06:57 +08:00
eval initial commit 2026-10-20 12:09:42 +08:00
examples feat(h20): enable FlagGems end to end, from an allow-list of ops proven equal to PyTorch 2026-10-26 12:53:47 +08:00
scripts feat(h20): enable FlagGems end to end, from an allow-list of ops proven equal to PyTorch 2026-10-26 12:53:47 +08:00
tests initial commit 2026-10-20 12:09:42 +08:00
vendor initial commit 2026-10-20 12:09:42 +08:00
.clang-format initial commit 2026-10-20 12:09:42 +08:00
.gitignore feat(h20): route tile_kernels calls through a compat layer, so the model runs without TileLang 2026-10-22 18:10:14 +08:00
.gitmodules initial commit 2026-10-20 12:09:42 +08:00
build.sh initial commit 2026-10-20 12:09:42 +08:00
CONTRIBUTING.md initial commit 2026-10-20 12:09:42 +08:00
H20-BRANCHES.md feat(h20): enable FlagGems end to end, from an allow-list of ops proven equal to PyTorch 2026-10-26 12:53:47 +08:00
H20-DEBUG-PLAN.md fix(debug): move debug_dump out of h20_ops so other platforms can import it 2026-10-21 22:37:49 +08:00
H20-DRIFT-ANALYSIS.md docs: record that plain-text prompting answers correctly 2026-10-21 22:50:57 +08:00
H20-FLAGGEMS-PLAN.md feat(h20): enable FlagGems end to end, from an allow-list of ops proven equal to PyTorch 2026-10-26 12:53:47 +08:00
H20-PORTING-JOURNAL.md docs: record the two-branch split and the upstream PR link 2026-10-21 17:16:46 +08:00
H20-SM90-FINDINGS.md feat: add SM90 (Hopper) support for DeepSeek-V4.1 inference 2026-10-21 15:18:56 +08:00
H20-TRITON-PLAN.md test(h20): check what the model actually says, in a file rather than on the command line 2026-10-22 10:53:01 +08:00
LICENSE initial commit 2026-10-20 12:09:42 +08:00
Makefile initial commit 2026-10-20 12:09:42 +08:00
pyproject.toml test(h20): compare two hosts' Triton builds, not just two backends on one host 2026-10-22 10:53:36 +08:00
README.md initial commit 2026-10-20 12:09:42 +08:00
requirements-ascend.txt initial commit 2026-10-20 12:09:42 +08:00
requirements-dev.txt initial commit 2026-10-20 12:09:42 +08:00
requirements-nvidia.txt initial commit 2026-10-20 12:09:42 +08:00
requirements.txt initial commit 2026-10-20 12:09:42 +08:00
setup.py initial commit 2026-10-20 12:09:42 +08:00
TODO.md feat(h20): run sparse MLA on FlagGems' Triton kernel, so TileLang is no longer required 2026-10-25 14:02:58 +08:00

DeepInfer

DeepInfer is the high-performance inference framework that powers DeepSeek's large-scale production services. This open-source release provides offline inference with the core features needed for serving at scale.

Supported models:

  • DeepSeek-V4.1-Flash

Supported features:

  • Optimized kernels, model and sampler runtime
  • Parallelism: Attention DP / balanced CP, MoE EP + EPLB
  • DSpark and confidence-scheduled verification
  • SWA bounded replay
  • Asynchronous scheduling (zero-overhead batch scheduler)
  • Batch-invariant inference
  • Deterministic sampling
  • Structured outputs
Feature details and configuration
  • Optimized kernels: FlashMLA, DeepGEMM, DeepEP, TileKernels, DeepSelect, and custom TileLang kernels.
  • DSpark and confidence-scheduled verification: accelerate decoding with draft tokens and use confidence estimates to schedule verification. Set DEEPINFER_ENABLE_MTP_VARLEN=1; DEEPINFER_USE_NEXTN_DECODE controls the maximum draft length (default: 5).
  • Decoder SWA bounded replay: reduce decoder prefill work by replaying only a bounded suffix. Set DEEPINFER_YOCO_PREFILL_TRUNCATION_MODE=compact and DEEPINFER_YOCO_PREFILL_KEEP_TOKENS=140 for the default V4.1 settings; the retained suffix must cover the SWA window plus the maximum backtracking length.
  • Asynchronous scheduling: overlap CPU batch scheduling with device execution. Enabled by default.
  • Batch-invariant inference: keep model results identical across different batch compositions. Enable with DEEPINFER_BATCH_INVARIANT=1 (NVIDIA only).
  • Deterministic sampling: produce identical outputs for identical input tokens and sampling parameters. Set DEEPINFER_BATCH_INVARIANT=1 DEEPINFER_ENABLE_MTP_VARLEN=0 and pass a fixed seq_seed to SamplingParams (NVIDIA only).
  • Structured outputs: constrain generation to a regex, JSON schema, or EBNF grammar. Pass so_args={"schema_type": ..., "schema": ...} to SamplingParams; see examples.

Supported hardware:

  • NVIDIA SM100 GPUs
  • Huawei Ascend 950 NPUs

Required for a complete inference service (not included in this release):

  • A KV cache system
  • VE/Prefill/Decode disaggregation (most required engine functionality is already implemented)
  • Load balancing across data-parallel replicas for both prefill and decode

Getting started

Prerequisites

  • Linux
  • GCC >= 13.0
  • Python 3.12
  • CUDA 13 (NVIDIA only)
  • CANN 9.2 (Ascend only)

Build from source

Before building DeepInfer, please create and activate an empty Python 3.12 environment.

# Use `ascend` instead for the Ascend platform
# Keep it exported in the environment where you run DeepInfer
export DEEPINFER_ACCELERATOR=nvidia
./build.sh

Offline inference

The default checkpoint, deepseek-ai/DeepSeek-V4.1-Flash-1017, is downloaded into the Hugging Face cache on the first run; set DEEPINFER_HF_MODEL_DIR=/path/to/DeepSeek-V4.1-Flash-1017 to run from a local copy instead.

python examples/offline_inference.py

See examples for details.

Performance benchmarks

Prefill Decode
Prefill: non-cached input throughput vs. latency Decode: output throughput vs. per-user speed

Measured on 4 SM100 GPUs for prefill and 64 for decode — each within one scale-up domain. To reproduce the benchmarks, see run_sweep.sh.

Evaluation benchmarks

See eval/README.md.

License

DeepInfer is released under the Apache License 2.0. See LICENSE for details.

Acknowledgments

DeepInfer was originally built primarily on vLLM, with additional inspiration from SGLang and TensorRT-LLM. We thank their developers.

Citation

@misc{deepinfer2026,
  title = {DeepInfer: High-performance, large-scale inference framework for DeepSeek models},
  author = {DeepSeek-AI},
  year = {2026},
  publisher = {GitHub},
  howpublished = {\url{https://github.com/deepseek-ai/DeepInfer}},
}