feat(minimax-m3): add SM100 MSA sparse attention with custom backward - #3809
Open
Butterfingrz wants to merge 11 commits into
Open
feat(minimax-m3): add SM100 MSA sparse attention with custom backward#3809Butterfingrz wants to merge 11 commits into
Butterfingrz wants to merge 11 commits into
Conversation
Signed-off-by: Butterfingrz <13524387014@163.com>
Signed-off-by: Butterfingrz <13524387014@163.com>
Signed-off-by: Butterfingrz <13524387014@163.com>
Signed-off-by: Butterfingrz <13524387014@163.com>
Signed-off-by: Butterfingrz <13524387014@163.com>
Signed-off-by: Butterfingrz <13524387014@163.com>
Contributor
|
/claude review |
Contributor
|
LGTM Reviewed the full diff across all 17 non- Key risk areas all check out:
No critical bugs, security issues, typed-API regressions, or coverage gaps found. |
Signed-off-by: Butterfingrz <13524387014@163.com>
Butterfingrz
requested review from
HuiyingLi,
akoumpa,
athitten and
snowmanwwg
as code owners
September 5, 2026 08:38
Contributor
|
/ok to test 6b17e7a |
Signed-off-by: Butterfingrz <13524387014@163.com>
Signed-off-by: Butterfingrz <13524387014@163.com>
… dQ atomics Port the SM100 MSA backward kernels developed for MiniMax M3 into the model-private kernels package. - msa_task_build_sm100.py (new): one CuTe DSL jit with four launches (work scan, segment keys, bin scan, table scatter) builds the locality-ordered task tables and a device-side CTA-walk descriptor without any host synchronization; the main kernel is launched with a grid bound that covers every task count the capacity admits and surplus CTAs idle. MSA_M3_TASK_BUILD=torch restores the eager Torch chain (bit-identical tables, one host sync) and stays the fallback for ineligible schedules. - msa_backward_sm100.py: dQ accumulates with packed 16-bit atomics (MSA_M3_DQ_ACCUM=fp16|bf16, inline PTX f16x2/bf16x2 red with an L2 hint) into a head-pair-interleaved pool; Q/dO are TMA-loaded per tile; the wrapper owns one internal buffer per call and consumes the task tables through task_build_storage / compile_task_build / build_backward_tasks. - msa_grad_finalize_sm100.py (new): one launch casts the dQ and dK/dV pools to the BF16 gradients. - msa_backward_preprocess_sm100.py: delta accepts an output buffer and the executable is exposed for the plan. - msa_schedule.py: 4 or 32 task rows per CTA (switch at 2400 rows), MSA_M3_ROWS_PER_CTA override, direct shape checks, host mirror of the device CTA interval. - kernels/README.md: module roles and the four MSA_M3_* switches. Validated on one B200: test_msa_sm100.py passes with both the fused and the torch task build (PP=2 skipped, one GPU), test_cp_forward_cp1_matches_eager passes, the CPU minimax_m3_vl unit suite passes (197 passed, 4 skipped), ruff check and format are clean. Signed-off-by: Butterfingrz <13524387014@163.com>
… deterministic-mode error The message still claimed global FP32 atomic accumulation. The SM100 backward now accumulates dK/dV with FP32 atomics and dQ with packed 16-bit atomics (MSA_M3_DQ_ACCUM), so state that instead; the non-determinism and the suggested workarounds are unchanged. Signed-off-by: Butterfingrz <13524387014@163.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds an opt-in SM100 training backend for MiniMax-M3 sparse-attention layers. With
BackendConfig.sparse_attn="msa", the attention operator uses the official MiniMax Sparse Attention (MSA)prefill forward and an AutoModel-owned CuTe DSL backward with device-side task construction and gradient
finalization. This avoids expanding sparse block selection into a dense per-head token mask for the
sparse-SDPA path. The default remains
sparse_attn="generic".MSA applies to sparse layers; dense layers continue to use
backend.attn. The model owns packed-documentlayout and padding, while a private attention Adapter owns kernel dispatch and the state needed by backward.
The example recipe uses SDPA for dense layers and MSA for sparse layers, with 16k text packing and PP4/EP32.
Changelog
BackendConfig.sparse_attnselection and Linuxmsadependency extra.boolean mask representation; MSA consumes compact
q2kindices._msa.pymodule for packed-document layout, tensor/runtime validation, lazy dependencyloading, and forward/backward state. Model and attention layers reuse its typed layout during each forward.
from the saved forward schedule, the main attention backward, and BF16 gradient finalization. The eligible
fused task builder keeps exact counts and CTA scheduling on the device. dQ uses packed 16-bit atomic
accumulation, while dK/dV retain FP32 accumulation.
examples/vlm_finetune/minimax_m3/minimax_m3_vl_sft_tulu3_text_msa_16k.yaml: text-only Tulu-3 SFT,FSDP2 with PP4/EP32, CP1, and activation checkpointing. Its CI metadata requests 32 nodes with four processes
per node on the GB200 cluster. Update the PyTorch container lock for the optional MSA dependency.
Design
MiniMaxM3TextModelresolves document identity and padding once per forward. Each pipeline stage that executesMSA builds one
_MSAPackedLayoutand shares it with its sparse layers. Stages containing only dense layersvalidate the document map without materializing the MSA layout. Callers supply ordinary model inputs and masks;
_msa_layoutis model-owned.Sparse layers compact hidden states and RoPE tables before projection, perform attention on real token rows,
and restore the attention output after
o_proj. Hidden states enter and leave the attention layer as[B, S, hidden]. The external attention format isqkv_format="bshd"; internally, Q/K/V use compact THD tensors,where
Tis the number of real tokens:The flat-attention Interface consists of compact Q/K/V, document-local
q2k[4,T,16], and the packed layout,under the fixed topology and runtime constraints below.
q2kcarries sparse support, with-1in unused slots; the layout carries document offsets and tokencoordinates. CSR, scheduler metadata, and backward task rows are derived execution metadata kept inside the
Adapter and its kernel Implementation. Layers do not construct or retain those execution structures.
_MSASparseAttentionFunctionsaves the compact tensors, forward output/LSE, and forward-derived CSR/schedulefor the corresponding backward pass. Backward creates attention K/V workspaces with each document padded to a
multiple of 128 tokens, computes gradients, and gathers dK/dV back into compact token order. The indexer may
separately align index-K during forward.
Supported scope
attention_dropout=0,rope_fusion=False,te_fp8=None,cp_size=1,num_mtp_modules=0. No sliding windows, CUDA graphs, or deterministic algorithms.backend.attn="sdpa"and a boolean
[B,1,S,S]block-causal mask.MSA_M3_DQ_ACCUM=bf16selects wider-range BF16),FP32 dK/dV. Results are not bitwise deterministic.
Custom kernel
Model-local kernel
MiniMax-M3's custom SM100 backward lives under
nemo_automodel/components/models/minimax_m3_vl/kernels/.Custom backward design
msa_backward_sm100.pyowns the per-call storage and coordinates the kernels below. The autograd Adaptersupplies saved forward state and restores compact gradients after the kernel sequence.
Dependency compatibility
The Linux
msaextra pins official MSA80434d7and CuTe DSL 4.6.2, compatible with Quack 0.6.4. Dependencies load lazily;
kernels/msa_patch.pyfixes upstreamnvvm.fmaxcompatibility.Use
uv runso build tools are onPATH.TEST
Recorded local results; commands below are for reproduction. The logs do not pin kernel source or environment.
CPU unit tests:
Single-B200 SM100 functional tests:
CUDA_VISIBLE_DEVICES=0 PYTHONPATH=. uv run --no-sync python -m pytest -q -ra \ tests/functional_tests/models/minimax_m3_vl/test_msa_sm100.py # 3 passed, 1 skippedThe B200 tests cover packed O/dQ/dK/dV parity, top-16 selection, and checkpointed projection gradients.
PP2 was skipped because it requires two SM100 GPUs.
Additional generic CUDA checks: CP1 passed;
test_eager_sparse_attn_bf16_matches_fp32failed(mean error
1.04e-3, threshold1e-3), also reproduced at6b17e7af.The 128-GPU recipe was not run end to end.
Attention-operator benchmark
One B200, BF16, 64 Q / 4 KV heads, head_dim 128, block 128, top-16, batch 1, one document.
CUDA-event medians: 30 iterations after 5 warmups.
MSAuses fused task construction and FP16 dQ;genericuses dense-mask SDPA.Both consume the same selection. Timing includes per-call preparation and excludes selection and projections.
O/dQ/dK/dV relative L2 error: 1.9e-3–2.9e-3 at 4k–16k. Generic mask expansion takes 39.7 ms at 16k.
Peak allocation includes inputs and temporaries. At 32k, MSA uses 10.5 GB;
generic's 128 GiB bias allocation runs out of memory, preventing parity comparison.
Documentation and pre-checks
The model-local kernel README documents installation and compatibility. The MiniMax-M3 Fern model page still
needs user-facing MSA configuration and installation guidance in a follow-up.