Skip to content

Merge upstream public release 26/09/30 (deepseek-ai/DeepGEMM#462) - #30

Merged
zyongye merged 2 commits into
vllm-project:devfrom
zyongye:merge/upstream-0930
Oct 10, 2026
Merged

zyongye merged 2 commits into
vllm-project:devfrom
zyongye:merge/upstream-0930

Conversation

@zyongye

@zyongye zyongye commented Oct 10, 2026

Copy link
Copy Markdown
Member

Merges upstream's public release 26/09/30 (deepseek-ai#462) into dev. It brings in locality-aware Mega MoE, the GEMM epilogue classes with BF16 stochastic rounding, the reworked Lightning and Sparse Indexer kernels, and upstream's MQA API changes.

This changes the MQA API, so vLLM must update its indexer before bumping its DeepGEMM pin to this commit (details below).

Upstream features on the TORCH_LIBRARY bindings

Upstream adds its new APIs through pybind11, which dev no longer links. They are ported as follows:

  • Epilogue classes: deep_gemm.epilogue.{Identity, Alpha, FP8Quantization, BF16StochasticRounding}(...) build a deep_gemm::Epilogue custom class through factory ops. All GEMM and einsum ops take it as epilogue=None. The objects are torch.ScriptObjects, so they don't work with isinstance.
  • Locality domains: the helpers are locality_domain_* ops, exposed as deep_gemm._C.locality_domain, so upstream's deep_gemm/locality_domain.py works unchanged.
  • MLOPart: the C++ side calls deep_gemm.utils.mlopart through the CPython limited API (taking the GIL itself) instead of pybind11. Python errors from it now surface as RuntimeError rather than AssertionError, and test_locality_domain accepts either.
  • shutdown: a config op; deep_gemm/__init__.py registers it with atexit as upstream does.
  • Stub generator: scripts/generate_pyi.py maps custom-class schema types to Any.

MQA: upstream API adopted

  • Removed: fp8_mqa_logits, fp8_paged_mqa_logits, fp8_gemm_nt_skip_head_mid, and the clean_logits and logits_dtype arguments.
  • fp8_fp4_mqa_logits requires max_seqlen_k > 0 and returns compressed logits. Callers mask entries beyond each row's valid KV span.
  • SM100 takes MXFP8 or MXFP4 inputs with BF16 weights and returns BF16 logits. Paged MQA on SM100 is varlen-only (indices, next_n=1).
  • SM120 needs no kernel changes. It keeps FP8 with per-token float KV scales or MXFP4, FP32 weights and FP32 logits. Paged queries can be fixed-length or varlen. The SM120 kernels already had the compressed-logits path.
  • SM90 keeps dev's 32-row pages, next_n=4 (two-CTA cluster), and the zero-context scheduler test.

dev changes kept on top of upstream

  • SM120 GEMMs move to the renamed epilogue::operators. The head-split index remap goes away with fp8_gemm_nt_skip_head_mid, as does test_sm120_skip_head.py.
  • SiTU Mega MoE is regenerated from upstream's new kernel plus dev's SiTU diff, so it also gets the epilogue prefetch and locality-aware scheduling.
  • NVFP4 Mega MoE uses the new scheduler with a single locality domain (no localization).
  • SwiGLU alpha/beta is re-applied on top of upstream's prefetching epilogue.
  • Mega Gate keeps Remove Mega-Gate finite-score device trap #11's removal of the finite-score device trap, which upstream still has.
  • Upstream behaviour now on dev:
    • get_bf16_mega_gate_config is removed, and bf16_mega_gate defaults to scoring_func='sqrtsoftplus'.
    • FP8×FP4 and BF16 Mega MoE assert that the configured SM count equals the device's.

Testing

Run on 4× GB300 (SM103), CUDA 13.4, torch 2.12.1:

Test Result
test_bf16, test_fp8_fp4, test_einsum, test_layout, test_hyperconnection, test_mega_gate, test_mega_mhc, test_legacy pass
test_attention (DG_MQA_NUM_CASES=40: dense, paged, sparse) pass
test_lazy_init --num-processes 2, test_locality_domain (MLOPart available) pass
test_mega_moe EP4: FP8×FP4 SwiGLU with alpha=1.702, beta=1.0, clamp=7 pass
test_mega_moe EP4: FP8×FP4 with --use-localization pass
test_mega_moe EP4: FP8×FP4 SiTU pass
test_mega_moe EP4: BF16 pass
test_nvfp4_mega_moe EP4 pass

Not run (no hardware): SM90 and SM120. Their kernel headers compile with nvcc -arch=sm_90a / sm_120a, and the host code builds. Someone with those GPUs should run test_attention, test_fp8_fp4, test_einsum and test_sm120_* before this merges.

vLLM follow-up

Before vLLM bumps its DeepGEMM pin to this commit, its indexer (sparse_attn_indexer.py) must:

  • drop clean_logits and pass max_seqlen_k;
  • handle compressed logits;
  • on SM100, pass MXFP8 or MXFP4 with BF16 weights and use the varlen paged interface.

🤖 Generated with Claude Code

LyricZhao and others added 2 commits September 30, 2026 09:48
Add locality-aware Mega MoE execution, GEMM epilogue classes with BF16
stochastic rounding, wider sparse MQA head support, and packed SF strides.
Improve Indexer and Mega MoE pipelines, update attention and Mega Gate
interfaces, and include runtime and correctness fixes.

Export the current source through the OSS filter while retaining public
release history and the Mega MoE task-info release-ordering fix.

Co-authored-by: Anyi Xu <41318296+xay5421@users.noreply.github.com>
Co-authored-by: huahuaquq <289927700+huahuaquq@users.noreply.github.com>
Co-authored-by: TwenTy_ <47315699+THUTwenTy@users.noreply.github.com>
Co-authored-by: xyf007 <41227294+xyf007@users.noreply.github.com>
Co-authored-by: Yongqi Zhuo <Yongqi-Zhuo@users.noreply.github.com>
Co-authored-by: yukuai26 <1010238651@qq.com>
Co-authored-by: Zhean Xu <94977922+zheanxu@users.noreply.github.com>
Bring in locality-aware Mega MoE, the GEMM epilogue classes with BF16
stochastic rounding, the reworked Lightning/Sparse Indexer kernels, and
upstream's MQA API changes.

Adapt the new upstream APIs to the TORCH_LIBRARY bindings:
- Epilogue classes are a `deep_gemm::Epilogue` custom class built by
  factory ops; `deep_gemm.epilogue.X(...)` returns one and every GEMM and
  einsum op takes it as `epilogue=None`.
- Locality domain helpers are `locality_domain_*` ops, exposed as
  `deep_gemm._C.locality_domain` for `deep_gemm.locality_domain`.
- MLOPart calls into Python through the CPython limited API instead of
  pybind11, taking the GIL itself.
- `shutdown` is a config op.
- Python errors from MLOPart surface as `RuntimeError` through the
  dispatcher, which `test_locality_domain` now accepts.

Adopt upstream's MQA API: drop `fp8_mqa_logits`, `fp8_paged_mqa_logits`,
`fp8_gemm_nt_skip_head_mid`, `clean_logits` and `logits_dtype`, and
always return compressed logits. SM120 keeps its kernels unchanged:
FP8 inputs with per-token float KV scales or MXFP4, FP32 weights and
FP32 logits, fixed-length or varlen paged queries. SM90 keeps 32-row
pages and next_n=4.

Keep dev's other changes on top of upstream:
- SM120 GEMMs move to `epilogue::operators` and lose the head-split
  index remap along with `fp8_gemm_nt_skip_head_mid`.
- The SiTU Mega MoE variant is re-derived from upstream's kernel, and
  the NVFP4 Mega MoE uses the new scheduler with one locality domain.
- SwiGLU alpha/beta is re-applied on top of upstream's prefetching
  epilogue.
- Mega Gate keeps the removal of the finite-score device trap.
- `get_bf16_mega_gate_config` is removed, following upstream.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zyongye
zyongye force-pushed the merge/upstream-0930 branch from e7478a5 to 63aa62a Compare October 10, 2026 02:56
@zyongye
zyongye merged commit 15c02c8 into vllm-project:dev Oct 10, 2026
1 check failed
@zyongye
zyongye deleted the merge/upstream-0930 branch October 10, 2026 06:32
zyongye added a commit to zyongye/vllm that referenced this pull request Oct 12, 2026
…parse indexer

Pin vllm-project/DeepGEMM dev 00918bc (upstream 26/09/30 release via
vllm-project/DeepGEMM#30, the vendoring import fix vllm-project#31, and the paged
sparse page-stride relaxation vllm-project#33) and vendor the new
deep_gemm/locality_domain.py. vllm-project#33 drops the sparse indexer's page-stride
requirement from 512 to 256 bytes, which is what the indexer's packed
64-token pages (8448 bytes FP8, 4352 bytes MXFP4) satisfy.

The MQA logits API changed: clean_logits/logits_dtype are gone,
max_seqlen_k is required, prefill logits are compressed to each row's
K span, and SM100 takes only MXFP8/MXFP4 with BF16 weights and returns
BF16 logits. On SM100 the FP8 indexer K writers store their existing
power-of-two scale as four packed UE8M0 bytes (a lossless MXFP8
encoding), FP8 Q passes unit MX scales with its scale still folded into
the weights, and BF16 logits are upcast row-aware for the FP32 top-k
kernels. check_wheel_deepgemm.py now imports the vendored package.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Yongye Zhu <zyy1102000@gmail.com>
zyongye added a commit to zyongye/vllm that referenced this pull request Oct 12, 2026
…parse indexer

Pin vllm-project/DeepGEMM dev 00918bc (upstream 26/09/30 release via
vllm-project/DeepGEMM#30, the vendoring import fix vllm-project#31, and the paged
sparse page-stride relaxation vllm-project#33) and vendor the new
deep_gemm/locality_domain.py. vllm-project#33 drops the sparse indexer's page-stride
requirement from 512 to 256 bytes, which is what the indexer's packed
64-token pages (8448 bytes FP8, 4352 bytes MXFP4) satisfy.

The MQA logits API changed: clean_logits/logits_dtype are gone,
max_seqlen_k is required, prefill logits are compressed to each row's
K span, and SM100 takes only MXFP8/MXFP4 with BF16 weights and returns
BF16 logits. On SM100 the FP8 indexer K writers store their existing
power-of-two scale as four packed UE8M0 bytes (a lossless MXFP8
encoding), FP8 Q passes unit MX scales with its scale still folded into
the weights, and BF16 logits are upcast row-aware for the FP32 top-k
kernels. check_wheel_deepgemm.py now imports the vendored package.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Yongye Zhu <zyy1102000@gmail.com>
zyongye added a commit to zyongye/vllm that referenced this pull request Oct 13, 2026
…parse indexer

Pin vllm-project/DeepGEMM dev 6ce1c5e: the upstream 26/09/30 release
(vllm-project/DeepGEMM#30), the vendoring import fixes
vllm-project/DeepGEMM#31 and vllm-project/DeepGEMM#32, and the paged
sparse MQA page-stride relaxation vllm-project/DeepGEMM#33. Vendor the
new deep_gemm/locality_domain.py. DeepGEMM#32 makes the MLOPart bridge
and the epilogue module use the package's own name, so they also work
when vendored as vllm.third_party.deep_gemm. DeepGEMM#33 lowers the
page-stride guard from 512 to 256 bytes; the DeepSeek-V4.1
sparse-logits block stride stays 512-aligned, which still satisfies it.

The MQA logits API changed: clean_logits/logits_dtype are gone,
max_seqlen_k is required, prefill logits are compressed to each row's
K span, and SM100 takes only MXFP8/MXFP4 with BF16 weights and returns
BF16 logits. On SM100 the FP8 indexer K writers store their existing
power-of-two scale as four packed UE8M0 bytes (a lossless MXFP8
encoding), FP8 Q passes unit MX scales with its scale still folded into
the weights, and BF16 logits are upcast row-aware for the FP32 top-k
kernels. check_wheel_deepgemm.py now imports the vendored package.

build_deepgemm_C.py passes --force to setup.py build_ext: DeepGEMM's
setup.py only tracks python_api.cpp, so an incremental build after a
header-only pin change kept a stale extension. CMake already decides
when this step reruns.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Yongye Zhu <zyy1102000@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants