Skip to content

[Ascend] GLM-5.2 W8A8 ops: fused MC2 MoE, MLAPO decode, on-device NZ conversion - #355

Open
wanfengcxz wants to merge 10 commits into
DeepLink-org:mainfrom
wanfengcxz:wq/optimize_glm52
Open

wanfengcxz wants to merge 10 commits into
DeepLink-org:mainfrom
wanfengcxz:wq/optimize_glm52

Conversation

@wanfengcxz

@wanfengcxz wanfengcxz commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Ascend ops for GLM-5.2 W8A8, paired with the lmdeploy-side PR (engine wiring lives there).

Changes:

  • Fused MC2 W8A8 MoE operator + fused moe_gating_top_k (vendor/ascend/moe.py, torch_npu_ops.py)
  • GLM DSA MLAPO decode path: merged quantized QKV projections, fused split MLA cache
    writes, split queries fed straight to SFA (vendor/ascend/mlapo.py, ops/llm.py)
  • lmdeploy integration patches, incl. on-device (d2d) NZ conversion of W8A8 expert
    weights — replaces the CPU round-trip that stalls 3-4min when 16 TP workers convert
    concurrently (framework/lmdeploy_ext/device/__init__.py)

Verified on 16x Ascend 910B (tp=16, ep=16), graph mode: outputs identical to the
branch state before the lmdeploy-side refactor.

wanfengcxz and others added 5 commits October 26, 2026 07:55
mla_preprocess returns q_nope/q_pe separately; routing them through the fused sparse_attention_fwd forced a torch.cat followed by slice + contiguous. Call sparse_attention_fwd_split with the split tensors directly (verified: 12480/12480 decode calls take this path, greedy batch output byte-identical).

Co-Authored-By: Claude Code <noreply@anthropic.com>
lmdeploy stock convert_weight_to_nz round-trips every expert tensor through the host (D2H + cpu transpose + H2D); with all TP workers converting concurrently that phase takes minutes after weight loading. Patch LinearWeightsW8A8 to nz_weight.copy_(param.transpose(1, 2)) instead, which performs the ND->NZ format cast as a d2d copy with peak device memory growing by one expert tensor only. lmdeploy main w8a8.py has no NZ support at all, so also wrap FusedMoEW8A8.update_weights to trigger the conversion; the _weight_nz flag keeps it idempotent on branch checkouts that still call convert_weight_to_nz themselves.

Verified on GLM-5.2-W8A8 tp16/ep16 against lmdeploy 39907d02 (w8a8.py aligned with main): 16/16 ranks convert on device, post-load conversion ~10s (was ~240s), generation output byte-identical.

Co-Authored-By: Claude Code <noreply@anthropic.com>
patch_linear_w8a8_nz_convert probes dispatch_ffn_combine availability
before converting: whether the expert weights end up NZ is decided once
at weight-load time, and the weight format is that decision.
prepare_fused_w8a8_weights shrinks to pack_w8a8_scales (scale packing
only) - no more operator probing or NZ re-ensuring in the weight-update
path.

Verified on 16x 910B tp16/ep16: 16/16 ranks convert at load, greedy
outputs match the pre-refactor state.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
@wanfengcxz wanfengcxz changed the title optimize glm52 on a3 [Ascend] GLM-5.2 W8A8 ops: fused MC2 MoE, MLAPO decode, on-device NZ conversion Oct 27, 2026
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.

1 participant