Skip to content

fix(npu): disable shared TP for Async CAM model SP - #432

Merged
jiangkuaixue123 merged 1 commit into
mainfrom
codex/fix-npu-shared-experts-sp
Oct 13, 2026
Merged

jiangkuaixue123 merged 1 commit into
mainfrom
codex/fix-npu-shared-experts-sp

Conversation

@jiaran-king

@jiaran-king jiaran-king commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Observed problem and introduction

NPU Async CAM Attention can run with model TP and SP enabled while its standalone shared MLP still holds TP-sharded weights. SP assigns different token rows to the TP ranks, but the shared MLP's native row-parallel AllReduce assumes those ranks are computing partial results for the same tokens. It therefore sums contributions from different tokens and produces incorrect shared-expert output. This can corrupt generation and accuracy without causing a shape error or process failure.

The introduction chain is:

  • AFD #363 placed the standalone shared MLP on Attention for Async CAM. With the earlier Ascend implementation, its is_sequence_parallel=True / disable_tp setting selected complete shared weights.
  • Ascend #13946, commit 92616f3a, changed shared linear layers to select replication through enable_shared_expert_dp; shared layers no longer honor the generic disable_tp flag.
  • AFD #407 upgraded to Ascend 8d4409d6 without adapting this standalone shared path. #425 subsequently integrated the upgrade into main.

This is an AFD compatibility gap exposed by the Ascend dependency upgrade. Both MRV1 and MRV2 reuse the affected shared branch.

Affected models and configurations

The incorrect layout requires all of the following:

  • NPU CAMAsyncAFDConnector, on the Attention role, with compute_gate_on_attention=true.
  • A model with standalone shared experts using the DeepSeek-V2-family adapter: model types deepseek, deepseek_v2, deepseek_v3, deepseek_v32, or glm_moe_dsa. Existing MRV2 admission remains limited to V2/V3 MLA within this family.
  • Effective model MoE SP, with Attention TP > 1, EP enabled and PP = 1. The fix checks the effective SP decision after native FlashComm derivation; requesting FlashComm alone is insufficient. The hardware test used A DP2/TP2, enable_flashcomm1=true, and allgather_reducescatter.
  • Shared-expert DP unset/false, leaving the shared projections TP-sharded.

TP alone is valid when the shared inputs contain the same tokens on each rank. TP=1 and already-replicated shared weights do not have this mismatch. DeepSeek-V4 uses a separate implementation and is outside this fix.

Fix and behavior scope

For the affected TP + SP path, disable only shared-expert TP by replicating complete shared weights on each Attention rank. Keep the model's other TP/SP behavior.

After native FlashComm/SP derivation and before model weight allocation, select Ascend's existing enable_shared_expert_dp=true mechanism for the affected Attention path. This makes both shared projections use tp_size=1: each rank computes the complete shared MLP for its own SP token rows, without a shared TP AllReduce. Despite the flag's name, this does not change the configured model DP or TP sizes. The existing native placement check is retained.

Configuration Result after this change
Affected Attention path, effective SP on, shared DP unset/false Shared weights become complete on each rank; shared TP becomes 1. Model TP/SP remain enabled.
Effective model SP off, including TP=1 or this family's PP > 1 path No automatic shared setting override; preserve the requested shared layout.
Shared DP already true in a configuration accepted by the existing validator Preserve the replicated shared layout.
FFN role, other connectors, gate-on-FFN, or non-AFD No automatic override from this fix.
DeepSeek-V4 Existing implementation and MRV2 shared-DP restriction remain.

MRV2 configuration admission is unchanged. Its existing rejection of explicit enable_shared_expert_dp=true remains for V2/V3 and V4, together with the finegrained-TP restriction. This PR changes the effective Ascend shared-weight layout only in the affected SP path; the source additional_config mapping is preserved. It does not introduce a new admission rule or expand the accepted parameter set.

The production diff is +26/-1 lines in one file, afd_plugin/compat/patches/npu/ascend_config.py. The validator, its existing runtime tests, the shared MLP constructor and forward helper match main. Existing deployment documentation and focused factory scope coverage are updated. Replication increases shared-weight memory per affected Attention rank; performance and memory equivalence are not claimed.

Validation and evidence limits

Final PR commit: f44bb989cb10eb4217435b575ce2da94d6cfceb2. The shared-layout factory code is identical to the previously tested commit f6bc4961fe2f8f917f9505b9ed2769e21f424d90; the MRV2 admission change has been removed. The retained MRV1 production path is unchanged by that removal.

Current closeout checks:

  • Factory/lifecycle tests: 5 passed, 1 skipped locally. The skipped existing splitting-ops test requires the pinned vLLM source via AFD_TEST_VLLM_SOURCE. The effective-SP scope test covers roles, connectors, gate placement, model family, SP off, PP > 1, explicit shared settings and preservation of the input configuration.
  • Repository pre-commit checks passed, including Ruff, mypy 3.10 and Markdown checks.
  • The validator and its runtime test file are byte-identical to main. Evaluating the restored MRV2 admission block against the recorded MRV2 launch options confirms that its explicit shared-DP=true request is rejected.

Reusable MRV1 hardware evidence from f6bc4961:

  • DeepSeek-V2-Lite, Ascend 910C, CANN 9.1.0, torch 2.10.0, torch-npu 2.10.0.post4, vLLM ced6857a (0.30.0), Ascend 8d4409d6; Async CAM eager, A DP2/TP2 and F DP4/TP1 with EP. MRV1 explicitly requested shared DP=false, exercising the automatic layout correction. Both the Python extension and CAM operator package were compiled for that hardware run; the upstream source trees were clean.
  • During real requests, all four Attention ranks retained model TP=2, SP=true; both shared projections used tp_size=1 with complete shared weights (gate_up_proj shape [5632, 2048]). This confirms SP remained active and the shared branch actually used the intended layout.
  • MRV1 GSM8K: 41/128 (32.03%), compared with the existing native reference's 39/128 (30.47%) on the same 128 questions. The raw samples were rechecked: all prompt and target hashes match. Accuracy uses flexible answer extraction; identical generated text is not required.

MRV2 hardware closeout on f44bb98 (2026-10-13):

  • DeepSeek-V2-Lite on Ascend 910C with the same pinned vLLM/Ascend commits and CANN/torch/torch-npu versions listed above. All 528 tracked source files matched the final PR commit; both upstream source trees were clean. The matching, previously compiled extension and CAM operators were reused, with their loaded hashes verified.
  • Async CAM eager, A DP2/TP2 and F DP4/TP1 with EP. Both roles explicitly requested enable_shared_expert_dp=false, which the unchanged MRV2 validator accepts. Attention enabled FlashComm1 with allgather_reducescatter, exercising the automatic shared-layout correction.
  • During real requests the actual runner was AFDNPUAttentionModelRunnerV2. All four Attention ranks retained model TP=2, SP=true; effective shared DP became true, both shared projections used tp_size=1, and each rank held complete shared weights (gate_up_proj shape [5632, 2048]). All 70 live shared-branch observations had positive token rows, covering every Attention rank within the request window.
  • 4/4 serial and 12/12 concurrent requests returned correct numeric answers, with concurrency 12 and prompt lengths 57/121/186/250 tokens. Four elementary arithmetic questions used independently checked answers 12/27/6/42 and flexible numeric extraction. This is a functional smoke test, not a GSM8K accuracy result.
  • The launcher exited with code 0; all model processes were cleared from the devices and the test task was stopped with storage preserved. No production code or PR commit changed for this verification.

Correction to the earlier smoke-test claim: both historical 25-request accounting runs completed, including concurrency 12 and prompt token counts 305/369/433/497. However, their checker accepted B / 62.50% / 2.17, while the question gives 16/31 = 51.61% and 19/7 = 2.71, with no correct supplied option. These runs provide request-path/concurrency smoke evidence only, not mathematical correctness or accuracy evidence. The independent GSM8K result above is the accuracy evidence.

The historical MRV2 command explicitly requested shared DP=true and remains rejected by the unchanged validator; that run is not used to qualify this PR. The new accepted-configuration smoke run above verifies MRV2 startup and request execution for the tested topology. These V2-Lite eager runs do not qualify other models, graph execution or performance. No GSM8K rerun was performed for the MRV2 closeout.

jiangkuaixue123 added a commit that referenced this pull request Oct 9, 2026
## Purpose and scope

Integrate `update/v0.30.0` with main through `6981ee1`, incorporating
#402,
#405, #407, #411, #412, #413, #417 and #424 while preserving main's
changes,
including #427 and #359. Keep the pinned vLLM
`ced6857afa0ea7b2e3f0846a62e1394e90f15607`
and vLLM-Ascend `8d4409d6256d8a6729140ddcc0d1889e3f96cdd6`.

## Integration changes

- Reconcile main/upgrade interfaces, typing, test configuration and
documentation.
- Keep #430's Legacy DBO stage-padding fix and its required strided CAMP
receive
counts, FFN token counts and graph keys. Removing those counts while
retaining
  the stage-padding fix would make 4A2F transfer lengths disagree.
- Keep #429's single-barrier W4A8 SwiGLU fix without changing operator
tolerances.
- Keep the reviewed ACLNN workspace capture release after successful
submission,
  preserving #412's required pre-submission ownership.
- Keep the EngineCore patch-inventory correction; it is unrelated to SP.
- #411's intentional top-N profiling-control retirement remains
accepted.

## Known issues handled independently

Two fixes are extracted from this integration and are reviewed
separately:

- **#431 — MRV2 CAMP padding and FFN context:** many-to-one NPU
eager/fallback batches
can produce incorrect content; native FFN DP metadata is overwritten
with
  Attention metadata. Branch: `codex/fix-npu-mrv2-padding-context`.
- **#432 — DSV2 shared experts with SP + TP:** model-local token rows
are incompatible
with TP-sharded shared weights. Branch:
`codex/fix-npu-shared-experts-sp`.

These are explicitly accepted known issues for this integration, not
prerequisites
for merging #425. Each fix proceeds independently. No
configuration-disabling
switch, compatibility framework or new runtime guard is added.

Qwen3.6 validation, new NPU MRV2 DBO, #422, performance qualification
and inherited
DCO remediation remain outside scope.

## CI image alignment

Use `vllm/vllm-openai:v0.30.0` as the CI base. After installing
dependencies,
report vLLM/PyTorch/CUDA versions and require vLLM 0.30.0.
Buildkite #151 stopped during image construction because the added `uv
pip check`
rejected the official image's intentional NCCL 2.30.7 override of
PyTorch's
2.29.7 pin. Remove that blanket check while retaining the version
assertion.
Changed-file pre-commit hooks and embedded shell/Python syntax checks
pass.
Image construction passed in #152; GPU configuration validation awaits
the new Buildkite run.

## GPU DBO configuration follow-up

Buildkite [#152](https://buildkite.com/vllm/afd-plugin/builds/152)
passed image
construction, Simple Test and Legacy E2E. MRV2 reported three passes and
three
failures: eager DP2 failed during startup rendezvous; eager/graph DBO
timed out
on the first evaluation step.

`a06d850` restores native MRV2 chunked-prefill and token-budget
defaults, following
#416's configuration approach. Explicit caller choices, request
concurrency,
sample counts, accuracy thresholds and live two-stage assertions are
retained.
The candidate production stream-order change in `04ac606` is withdrawn;
`afd_plugin/` and `csrc/` match `3d30d17` exactly. Large-message P2P
deadlock
investigation (#414) remains separate from this configuration
validation.
Related CPU tests: **228 passed**; applicable pre-commit hooks pass.
Fresh GPU CI is pending. The startup port race remains under
observation.

## Validation of the split

Integration head: `a06d850fd9b5b580e172cafd518cce64d9d06612`.

- The four E2E runner/configuration/process-management unit files pass
**222 tests**.
- Applicable pre-commit hooks pass for changed files, including Ruff,
mypy,
  Markdown and SPDX; `git diff --check` passes.
- A broader local selection reports **236 passed, 78 skipped, 15
failed**.
  All 15 failures are missing-vLLM imports and reproduce on the original
`6941faf` with the same selection. This is not a passing NPU runtime
suite.
- No GPU/NPU experiments were rerun during extraction. The hardware
records below
  remain tied to their original source/configurations.
- Recombining both extracted fixes restores `afd_plugin/` and `csrc/`
exactly to
`6941faf`. Test simplification and documentation are the remaining
differences.

### GPU hardware results

Hardware-tested source: `3ee2e812656a0d88baf6487b02fcf6f15a88ea2e`;
these are historical results; the restored MRV2 test defaults require
fresh CI validation. H20-3e used pinned vLLM 0.30, PyTorch 2.13.0+cu130,
CUDA 13.0 and NCCL 2.29.7. Target-runtime units: **1231 passed, 126
skipped, 165 subtests passed**; skips require unavailable Ascend/NPU
dependencies or devices. All **14** selected DeepSeek functional
scenarios passed. E showed live two-stage eager execution; G showed
eligible live two-stage FULL execution and matching FFN replay layouts.

Fixed first-300 GSM8K results (correct answers):

| Model / path | Strict match | Flexible extract |
| --- | ---: | ---: |
| DeepSeek-V2-Lite native | 113/300 | 113/300 |
| Legacy graph + DBO 2A2F | 108/300 | 110/300 |
| MRV2 B: eager, no DBO | 116/300 | 118/300 |
| MRV2 E: eager DBO | 103/300 | 104/300 |
| MRV2 G: FULL DBO | 104/300 | 105/300 |
| MRV2 B: single repeat | 108/300 | 109/300 |
| MRV2 E: single repeat | 107/300 | 107/300 |
| Qwen3-30B-A3B native | 277/300 | 266/300 |
| Qwen3 AFD graph 2A1F | 282/300 | 273/300 |

All selected configurations meet the unchanged absolute threshold; that
does not establish numerical equivalence. The initial B→E paired strict
losses/gains were 15/2 and flexible 16/2; B→G were 13/1 and 14/1. In the
one bounded B/E repeat, E−B changed from −13/−14 to −1/−2, with paired
losses/gains 8/7 and 9/7. The original large gap did not consistently
reproduce. Both rounds are retained, with no relaxed threshold or
selection of the best run.

The repeat's two pytest/JUnit cases passed, but its controller raised at
the immediate post-E GPU-process check. The E samples remain usable;
verified final cleanup and allocation release were completed. The
overall repeat job is not labelled PASS. Native/AFD topology and
scheduling differences limit causal comparisons.

Existing old-main Legacy evidence is reused: same first256 questions and
generation arguments, old vLLM 0.26 DBO **94/256 strict and flexible**,
integrated Legacy **93/256 strict, 94/256 flexible**. Strict paired
losses/gains were 8/7, flexible 8/8. Runtime/deployment differences
remain; old main was not rerun. Old main does not support GPU MRV2 DBO
E/G.

Qwen3 eager's existing128 result is **122/128 strict, 118/128
flexible**; graph on the same128 is **123/128, 120/128**. The completed
DeepSeek native1319 result, obtained before the sample-scope reduction,
was **495/1319 strict, 497/1319 flexible**; its first300 are reused.
Candidate300 results are representative comparisons, not full-dataset
qualification. No further full-dataset, old-main or model-download
experiments were run after the agreed scope reduction.

### Historical NPU hardware results

The following runs included the CAMP padding/context repair that is now
outside
this integration. They do not certify the split baseline without that
repair,
and do not validate the later DSV2 shared-expert SP fix.

Pinned vLLM/Ascend, CANN 9.1.0, torch 2.10.0+cpu and torch-npu
2.10.0.post4 on Guian A3, using complete V2-Lite and DSV4 Flash W4A8
checkpoints. Five representative AFD configurations each ran the same
first300 GSM8K questions, 8-shot, maximum generation512 and
concurrency12. Flexible-extract results:

| NPU configuration | Correct | Native reference | Difference |
| --- | ---: | ---: | ---: |
| V2-Lite MRV1 2A2F graph | 106/300 | 106/300 | 0.00 pp |
| V2-Lite MRV2 2A2F FULL | 113/300 | 106/300 | +2.33 pp |
| V2-Lite ordinary Async CAM | 106/300 | 106/300 | 0.00 pp |
| DSV4 W4A8 layered off | 287/300 | 286/300 | +0.33 pp |
| DSV4 W4A8 layered on | 286/300 | 286/300 | 0.00 pp |

Historical validation of the combined repairs in `babcbd1` (including
the MRV2 padding/context change now extracted from this PR): MRV2 2A1F
eager/FULL_DECODE_ONLY/FULL each pass **25/25** after CAMP padding
repair. The final common ABI shorts pass **75/75**, all three exits0.
Related target-environment CPU tests: **148 passed, no skips**. Live
traces confirm graph replay, gate/quantization, dispatch/combine and
actual layered kernels; the workspace probe remains steady through896
work items.

**#428 / #430 is fixed and integrated at `563164a`.** That source tree
matches the hardware-tested #430 tip
`2f506eedb4a4bd547368b8e8a9076b980d5c83c8`. Native CAMP **72/72**,
Legacy DBO 2A1F **25/25**, 2A2F **25/25**, related units **24 passed, no
skips**. Live unequal stages were observed. Fixed first128 GSM8K: DBO on
**41/128**, off **40/128**. These bounded repair checks supplement the
five300 runs. The 2A2F model checks passed, but its shell wrapper later
exited2; that orchestration error is disclosed in the [repair
evidence](#430 (comment)).

**#429 is fixed at `2145e82`.** The original per-group operator case
passed in three independent processes, and the full operator suite
passed **16 tests, no skips**, with the rebuilt kernel selected.
Tolerances remain `rtol=0.04`, `atol=0.05`; the earlier
approximately1.7% mismatch concerned output elements, not a fraction of
operators. The five model-accuracy runs used per-channel weights.
[Failure, fix and device
verification](#429).

Shutdown AIV/MTE warnings occurred after scoring/SIGTERM; clean device
exit is not claimed. Historical DeepSeek-V3.2 recipes have not been
revalidated. The synchronous DSV4 A5/A3 profiles inherited from #359
check finished, nonempty concurrent responses, not answer accuracy; A5's
existing content defect remains documented. Existing Qwen DBO exclusions
also remain. These results do not qualify arbitrary topologies or
establish performance equivalence.

## Repository status

The split introduces one ordinary follow-up commit; it does not rewrite
existing
contributors' history. The original fix commits remain in ancestry, but
their
extracted changes are absent from this PR's final source tree.

The PR awaits final review. Current GitHub checks are shown on the PR;
old green checks are not attributed to this head. Historical DCO
identity mismatches were accepted through the authorized DCO override on
`c900c87`; checks on subsequent heads are reported separately. No
temporary report, raw model
output or local review bundle is part of the committed changes.

---------

Signed-off-by: yujuancao07 <yujuancao07@gmail.com>
Signed-off-by: lirx-pd <616517220@qq.com>
Signed-off-by: jiangkuaixue123 <jiangxiaozhou111@163.com>
Signed-off-by: zzh <jiaranran2@gmail.com>
Signed-off-by: Zhou ziheng <jiaranran2@gmail.com>
Co-authored-by: CaoYujuan <76958030+yujuancao07@users.noreply.github.com>
Co-authored-by: jiangkuaixue123 <jiangxiaozhou111@163.com>
Co-authored-by: lirx-pd <616517220@qq.com>
Base automatically changed from codex/v030-main-integration to main October 9, 2026 07:09
@hsliuustc0106 hsliuustc0106 added bug Something isn't working Ascend Ascend NPU platform and related changes labels Oct 12, 2026
@jiaran-king
jiaran-king force-pushed the codex/fix-npu-shared-experts-sp branch 3 times, most recently from 77433fd to 1c253d2 Compare October 12, 2026 07:58
@jiaran-king jiaran-king changed the title fix(npu): align DSV2 shared experts with SP token layout fix(npu): reject DSV2/V3 model sequence parallelism Oct 12, 2026
@jiangkuaixue123
jiangkuaixue123 marked this pull request as ready for review October 12, 2026 09:28
@jiaran-king jiaran-king changed the title fix(npu): reject DSV2/V3 model sequence parallelism fix(npu): disable shared TP for Async CAM model SP Oct 12, 2026
@jiaran-king
jiaran-king force-pushed the codex/fix-npu-shared-experts-sp branch from f6bc496 to 354e9d0 Compare October 12, 2026 13:37
Select Ascend's existing shared-expert DP layout for DeepSeek-V2-family
Async CAM Attention when effective model MoE SP is active. Each rank holds
complete shared weights and computes its local token rows with shared
projection tp_size=1.

Resolve native FlashComm/SP before selecting this layout. Preserve model
TP/SP, routed-expert parallelism, other roles and connectors, and non-SP
behavior. Keep the existing MRV2 explicit shared-DP admission restriction.

Update deployment documentation and cover the factory's scope and input
configuration preservation.

Signed-off-by: jiaran-king <jiaranran2@gmail.com>
@jiaran-king
jiaran-king force-pushed the codex/fix-npu-shared-experts-sp branch from 354e9d0 to f44bb98 Compare October 13, 2026 01:27
@jiangkuaixue123
jiangkuaixue123 merged commit 6589f30 into main Oct 13, 2026
2 checks passed
@jiangkuaixue123
jiangkuaixue123 deleted the codex/fix-npu-shared-experts-sp branch October 15, 2026 06:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ascend Ascend NPU platform and related changes bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants