Repository navigation
GLM-5.2/GLM-5.3 PR 1: engine: MLA attention, fp8 fused MoE, symmetric all-reduce - #386
Merged
Merged
Conversation
This was referenced Oct 9, 2026
vasilevklart
marked this pull request as ready for review
October 9, 2026 21:54
vasilevklart
force-pushed
the
glm/01-engine
branch
from
October 13, 2026 15:16
b00736f to
d958425
Compare
Byte-level BPE models emit each token's raw bytes, which can end inside a character; decoding per chunk turned those into U+FFFD.
As fused_experts_fp8: dynamo traced the launch path inline, which breaks the graph and fails on a symbolic token count under torch 2.9.1.
The runtime's ready order is handle order in Rust, and handles are recycled: a large prefill could be passed over indefinitely. Backlogged rows count too, since the batch builder tops a backlog up with fresh rows.
Its logits kernel holds every token in one tile; past 128 the first launch raised OutOfResources. The models never send more; now it says so.
Chosen per plan, a captured bucket could re-plan into the other kernel while the graph replayed the captured one on stale buffers.
The CUDA op launched a 0-block grid unchecked; the latched error surfaced in the next unrelated kernel.
A rank whose setup failed fell back to NCCL alone, and its peers' first all-reduce waited on it forever. tp_allreduce_max_kb: 0 now turns it off instead of reading as unset (512).
An empty MSTAR_GRAPH_COMPILE_MODE compiled in Inductor's default mode silently; reduce-overhead and max-autotune capture inside the runner's own graph, fail it, and the bucket serves eager.
The decode and prefill kernels index scales, x and shared as dense rows; a strided view was mis-scaled or mis-added silently. The prefill test now covers GLM-5.2's hidden 6144, the fused sum-and-add branch.
The reader sliced NHD's K/V axis first; on an MLA cache that took latent columns, not tokens.
Every deployment JIT-built the fused-MoE align op before spawning its workers: non-MoE models paid the nvcc build, or hung on a stuck build lock. A model now asks with prebuild_fused_moe.
sm_scale on another backend was dropped silently; an MLA cache without num_qo_heads defaulted to the one latent KV head, and the kernel planned 1.
Each new test file with a CPU case, listed in test/cpu-core.txt.
The deployment config's tp_async_sched key (true, false or a node list) turns it on so a shipped yaml can opt in; MSTAR_TP_ASYNC_SCHED still overrides it. Default stays off.
A long prompt for a path only long prompts take, such as a long-context prefill, without pasting it into the yaml.
A quoted yaml true or false arrives as a string and was taken as a node name, so the switch silently did nothing.
This was referenced Oct 21, 2026
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
As the other backends that don't read it do since #386: planned as an ordinary step, the queries would also attend to the tokens the step appends.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
The fusion strategies get set up the way #386's all-reduce backends are: a classmethod factory on the CommGroup, and its every-rank vote (_all_ranks_agree) instead of a copy.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
#386 pins fused_experts' parameters; the per-GPU tuned configs add an optional config kwarg at the end, None by default.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
As the other backends that don't read it do since #386: planned as an ordinary step, the queries would also attend to the tokens the step appends.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
The fusion strategies get set up the way #386's all-reduce backends are: a classmethod factory on the CommGroup, and its every-rank vote (_all_ranks_agree) instead of a copy.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
#386 pins fused_experts' parameters; the per-GPU tuned configs add an optional config kwarg at the end, None by default.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
As the other backends that don't read it do since #386: planned as an ordinary step, the queries would also attend to the tokens the step appends.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
The fusion strategies get set up the way #386's all-reduce backends are: a classmethod factory on the CommGroup, and its every-rank vote (_all_ranks_agree) instead of a copy.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
#386 pins fused_experts' parameters; the per-GPU tuned configs add an optional config kwarg at the end, None by default.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
As the other backends that don't read it do since #386: planned as an ordinary step, the queries would also attend to the tokens the step appends.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
The fusion strategies get set up the way #386's all-reduce backends are: a classmethod factory on the CommGroup, and its every-rank vote (_all_ranks_agree) instead of a copy.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
#386 pins fused_experts' parameters; the per-GPU tuned configs add an optional config kwarg at the end, None by default.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
As the other backends that don't read it do since #386: planned as an ordinary step, the queries would also attend to the tokens the step appends.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
The fusion strategies get set up the way #386's all-reduce backends are: a classmethod factory on the CommGroup, and its every-rank vote (_all_ranks_agree) instead of a copy.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
#386 pins fused_experts' parameters; the per-GPU tuned configs add an optional config kwarg at the end, None by default.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
As the other backends that don't read it do since #386: planned as an ordinary step, the queries would also attend to the tokens the step appends.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
The fusion strategies get set up the way #386's all-reduce backends are: a classmethod factory on the CommGroup, and its every-rank vote (_all_ranks_agree) instead of a copy.
merceod
added a commit
that referenced
this pull request
Oct 21, 2026
#386 pins fused_experts' parameters; the per-GPU tuned configs add an optional config kwarg at the end, None by default.
This was referenced Oct 22, 2026
Merged
NSagan271
added a commit
that referenced
this pull request
Oct 22, 2026
test_scheduler_room's engine fake (#386) needs get_max_batch_tokens too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vasilevklart
added a commit
that referenced
this pull request
Oct 22, 2026
dghosef
added a commit
that referenced
this pull request
Oct 25, 2026
Brings in model/asr's main merge (2c077f7) and its review round. Conflicts: - mstar/model/qwen3_asr/submodules.py: this branch's side. preprocess routes rows through sampler.overwrite_rows, and check_stop_batched reads host_rows.first_values; model/asr carried earlier copies of both. - mstar/model/whisper/submodules.py: check_stop takes model/asr's condition (no positions_left: the conductor's per-request loop cap owns the 448-position budget since 246d285) and keeps this branch's "stopped" mark for the align walk's token record. check_stop_batched drops its own copy of the position budget for the same reason. - mstar/engine/resources/sampler/{config,utils,resource}.py: both sides. SamplerSpec/SamplerBuffers/SamplerResource keep this branch's loopback_state and main's generation-history knobs; commit computes the keep mask once and scatters the loop-back states and the history before the in-graph-scatter return. - mstar/api_server/openai/serving_chat.py: model/asr's (main's #386) version, which already decodes the stream as one byte stream and puts the role on the first delta; it supersedes this branch's 1870aa9. - test/modular/test_openai_router.py: model/asr's; main's test_chat_joins_a_character_split_across_tokens and test_chat_stream_flushes_a_truncated_character cover this branch's test_chat_keeps_a_character_split_across_chunks, which is dropped. - test/modular/test_qwen3_asr_model.py: this branch's step_walk / engine-path tests; model/asr's PREFILL_WALK case is covered by test_engine_stop_check_takes_the_batched_path. - test/modular/test_whisper_model.py: the prefill preprocess test asserts model/asr's staged values and row_lens and this branch's eager context write. The decoder stub has model/asr's _stager/_inactive. - docs/asr.rst: model/asr's thread-cap, arena and long-file capacity paragraphs and the 12-request cap, then this branch's paragraph that both decode loops stream token by token (with model/asr's 20-minute delivery-deadline reason), then the split/MPS paragraph. - docs/adding_models.rst: both sides (decode_tensor_cores and MLA; loopback_state and the history capabilities; KVStep eager_write and AttentionStep context_only). Changed beyond the conflicts: - whisper: the captured prefill template's ts_rules row is built on the host. model/asr's preprocess stages host rule rows through PinnedStager, and a replay pads real (host) rows with template rows, so a device template row made torch.stack mix devices. Pinned in test_decoder_timestamp_rules_ride_along_as_a_staged_row. - test_whisper_model.py: the batched stop test drops its position-table row and the tests drop their prompt_len state, which no code reads now. - test_ingest_unpersist.py: back to main's; its poll_for_messages stub served the early wake that 383eed7 removed. The early wake (f388689, 7002867) stays removed: data_worker.py, entrypoint.py and conductor.py's message loop match model/asr (main's wake behaviour). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 tasks done
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.
What does this PR do?
GLM-5.2/GLM-5.3 PR 1 of 11: the engine pieces both GLM models share. PRs 2–11 (#387–#392, #397, #398, #405, #406) build on it, each based on the one below, so each diff is that layer only. Merge bottom-up; I rebase and retarget the next after each.
AttnBackend.FLASHINFER_MLA). Absorbed MLA over a latent KV layout (KVLayout.MLA:ckv512 plus a rope slot of 64 or 0), on FlashInfer's MLA kernel with one wrapper per graph slot and graph indices per row. The other backends refuse what only this one reads:sm_scaleat build, andAttentionStep(context_only=True)(which Kimi K3 support with DSpark speculative decoding #257's DSpark draft plans) at plan; and MLA attention refuses a cache with no query heads. The SHM KV transfer reads an MLA cache by token. Documented indocs/adding_models.rst._grid_rows), not all E experts.moe_alignretries a lost JIT lock, and the conductor builds the op once at load for models that ask, so a TP worker can't fall back to the uncapturable path.tp_allreduce: symm_oneshotorsymm_multimem,tp_allreduce_max_kb).mstar/distributed/all_reduce.pyholds the backends:AllReduceis NCCL and the fallback,SymmMemAllReducesends the small messages it can take through one persistent buffer per group, andOneShotAllReduceandMultimemAllReduceare its two kernels.AllReduce.newrefuses an unknown mode and stays on NCCL unless every rank of the group set symmetric memory up. Which kernel a call takes depends only on what every rank shares (mode, message size, eager or compiled), never on one rank's pointer alignment.dist_timeout_s, which a 750 GB load needs). It covers the load and warmup; serving collectives get torch's default, so a wedged rank doesn't hang its peers for the whole load timeout.compile_modeper capture config, checked when the config is built: an unknown mode, or one that turns on Inductor's own CUDA graphs, fails warmup instead of serving its buckets eager.tp_async_sched:true,falseor a list of nodes), so a shipped yaml can turn it on; it stays off by default andMSTAR_TP_ASYNC_SCHEDstill overrides it. The GLM yamls in Speed up GLM-5.2 with fp8 kernels and one-graph MTP #388 and Add GLM-5.3-Flash on 8 GPUs, plain and with MTP #390–Extend GLM-5.2 to 256k-token contexts #392 set it.repeat: N), a long prompt for a path only long prompts take; Extend GLM-5.3-Flash to 1M-token contexts #391 and Extend GLM-5.2 to 256k-token contexts #392's yamls use it.The new settings are serving-config keys; this PR adds no environment variables. Everything the stack sends over the control wire is plain data, as #407 requires.
Numbers
Known gaps
fused_experts; its grid bound equals_grid_rows, so the two conflict textually, not in behaviour.prefill_max_step_tokens, from Speed up GLM-5.2 with fp8 kernels and one-graph MTP #388 on) moves toChunkingPolicy.max_batch_tokens([Chunked Prefill #4a] Chunked prefill core #365) once the chunked-prefill stack lands. Until GLM-5.2/GLM-5.3 PR 2: GLM-5.2 with MLA, fp8 MoE and DSA #387–GLM-5.2/GLM-5.3 PR 11: prefix cache and MTP with temperature #406 are rebased onto this head, they still carry the old budget.How was it tested?
CPU tests for every piece are in
test/cpu-core.txt(test_fused_moe_*,test_mla_kv_layout,test_flashinfer_mla_gates,test_context_only_attention,test_symm_allreduce_routing,test_dist_timeout,test_cuda_graph_compile_mode,test_scheduler_room,test_conductor_moe_prebuild, …); GPU tests intest/integration/test_fused_moe_fp8.py,test_quant_fp8_gpu.pyandtest/modular/test_gpu_mla_attention.py.This head (402f3ff, with main 1493521 merged in, 2026-10-18):
ruff check .passes.@test/cpu-core.txtminustest/cpu-mac-exclude.txton macOS (torch 2.12.1, no triton or einops): 1512 passed and 187 skipped, and its 68 failures and 34 errors are the same tests that fail on main 1493521 on that machine.CommGroup.all_reducetraces into one graph undertorch.compile(fullgraph=True), on NCCL and through the symmetric backend's NCCL fallback. GPU gates on this head are pending; the tables below are from earlier heads.Gates for every layer of the stack against main 3c5f0dd on the same machines (Laude, 2026-10-09):
pytest test/modular(CPU)@test/cpu-core.txt)test_kv_prefix_stage) and no othersruff check .(0.16.10)Gates for every layer of the stack on main 4d01740 (coriander, 8×H200, 2026-10-12/13):
pytest test/modular test/ci test/rust(CPU, torch 2.12.1)@test/cpu-core.txton 4 CPUs,ruff check ., dynamo smoke on torch 2.9.1)Again after the rebase onto main 641162a (2026-10-14):
@test/cpu-core.txton 4 CPUs,ruff check .0.16 and 0.17,test/ci)finish_reason: lengthAgain after the rebase onto main 7fa8b8e (#340, 2026-10-14):
Checklist
ruff check .passes