Skip to content

Support official vLLM 0.29.0 - #23

Merged
XbzOnGit merged 3 commits into
ProjectDMX:mainfrom
zhaoyboo:vllm-0.29-support
Sep 19, 2026
Merged

XbzOnGit merged 3 commits into
ProjectDMX:mainfrom
zhaoyboo:vllm-0.29-support

Conversation

@zhaoyboo

@zhaoyboo zhaoyboo commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Port the out-of-tree DMI integration from official vLLM 0.27.1 to 0.29.0, keeping separate V1 and V2 workers. This PR changes DMI-vLLM-Integration only; it does not change the DMI root/gitlink, patch upstream vLLM, or publish a release tag.

2026-09-18 review update: reverted the nonessential residual-hook rewrite, Qwen3 V-view cleanup, added Llama compute_logits_local, and optional weight-tying alignment. The corrected head preserves the pre-port observation and constructor behavior. GPU requalification of this correction is pending; historical GPU receipts are not results for the corrected head.

Required adaptations retained

  • Forward V2's new prepare_inputs(..., batch_req_state, ...) argument and graph dispatch's optional max_query_len; preserve packed ordering and capacity safeguards.
  • Reject final-logit capture with batch-sharded sampling; inspect V2's actual in-progress prompt-logprobs state.
  • Remove retired AutoWeightsLoader keyword arguments and adapt GPT2's weight mapper. Preserve existing LM-head construction and weight aliases.
  • Adapt MoE runner-owned gates, Kimi K3 SP/auxiliary-state handling, and Granite's RoPE/NoPE branch.
  • Remove OLMo3 implementation, registration and stale oracle because upstream removed its native target.
  • Update package/CI pins and retain bounded differential/storage tests, independent eager residual-value checks, and the API audit: 865 occurrences / 555 mapped boundary groups.

Exact basis and dependencies

  • Previous upstream: v0.27.1 / 6e448d0ea9bf3d88d898b65449ca6dc2aec170ac
  • Target: official v0.29.0 wheel / source tag 98dff2a81d747d1dba01a47f939f48c3526d4206
  • Integration base: 420bafba42580291f1551ed129b5c55d5ac5799e
  • DMI core: c222f18c4db55f6f2d7136b1d6608c0b540b273a (1.2.0 / API v1)
  • Qualification environment: Python 3.12.8, PyTorch 2.13.0 / CUDA 13.0, Transformers 5.17.0, RTX 4090, ClickHouse 25.12.2.54.
  • Rebuild DMI native against the target PyTorch/CUDA; use a fresh version-specific compilation cache.

Corrected-head validation

  • Portable CPU gate: 689 passed, 4 skipped, 11 deselected.
  • Focused model/loader/source/V2 checks: 107 passed, 1 skipped.
  • Three router-state skips pass in separate fresh processes. The optional layer-range module needs a newer DMI API than the pinned core.
  • AST comparison against 420bafb: in the seven affected production model files, only necessary Qwen3/Llama loader, Qwen3-MoE routing and Granite RoPE method changes remain. Restored constructors, residual forwards and Qwen3 attention views match the base. Llama's already-post-norm resid_mid is unchanged.
  • Static inventory has zero unmapped groups; only the expected empty native-scope warning. git diff --check and smoke-wrapper shell syntax pass.
  • No GPU rerun: all three local GPUs were occupied. No existing process was stopped.

Historical GPU evidence and pending checks

The earlier implementation (through 5ce33c9) passed the six bounded Qwen3-0.6B TP1 cells and the eager residual-value diagnostic: 744 storage rows per ordinary cell, 1,416 total / 1,368 residual rows in the diagnostic. Earlier wheel/import evidence and exact cell definitions are retained in docs/v029-port.md.

The reviewer reported a compiled TP2 token divergence on that implementation. The same-version old-placement control was still pending in that review. Reverting the rewrite is not proof that this divergence is fixed.

Before claiming corrected-head GPU transparency, rerun the bounded V1/V2 workload and the same-version compiled TP2 control. Existing exact token/logit thresholds and the compiled release gate are unchanged; no tolerance was widened and no eager substitution hides this failure. No optimization follow-up PR is introduced.

Reproduce bounded TP1 cells with matching runtime/native, cached Qwen3-0.6B weights and ClickHouse:

CUDA_VISIBLE_DEVICES=0 DMI_V029_PYTHON=.venv/bin/python \
  bash tests/run_v029_smoke.sh

Import/CPU success does not qualify other models or topologies. See docs/v029-port.md, docs/v029-boundaries.tsv, and docs/vllm_contract.md for historical evidence, limitations and outstanding GPU checks. This PR is not a blanket support or release qualification claim.

@XbzOnGit XbzOnGit left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

Minor changes requested.

I checked every runtime-interface change in this PR against the upstream v0.29.0 source (98dff2a) and they all hold: V2 prepare_inputs / dispatch signatures and call conventions, enable_batch_sharded_sampling + compute_logits_local, prompt_logprobs_worker.in_progress_prompt_logprobs, ParallelLMHead.tie_weights, the AutoWeightsLoader signature change (tied aliases are now auto-skipped), WeightsMapper None drop semantics, MoERunner.gate replacing is_internal_router, the FusedMoERouter.select_experts patch boundary, GraniteAttention.use_rope, the Kimi K3 SP/aux rewrite (a faithful mirror of vllm/models/kimi_k3/nvidia/model.py, including the shape[0] == M heuristic), the OLMo3 removal, and the engine APIs used by the smoke harness. The V1 wrapper signatures are unchanged in 0.29. compileall, bash -n, and git diff --check pass on the head.

On the residual-hook rewrite: the observed values are bit-identical to the old hidden_states + residual (single fp32 to BF16 rounding in both the CUDA kernel and the native path), and DMI's ring producer launches on the current CUDA stream, so the in-place aliasing of the returned residual cannot race the capture.

Findings (details inline):

  1. Medium - the GPU cells do not value-check the hooks whose semantics changed; resid_mid is not in the tested selection.
  2. Medium - the # Adapted from ... in official vLLM 0.27.1. headers are now stale in all copied files, and test_models_source_contract.py enforces the stale string.
  3. Medium - the leftover OLMo3 module cannot import on 0.29 and is still lazily registered as an oracle target.
  4. Low - the two new V2 guards fail open via getattr defaults; a real-class attribute contract test would harden them.
  5. Low - the smoke harness relies on EngineCoreProc-only pause_scheduler('wait'), the private LLM.request_counter, a log-string grep, and a host-specific env -u LD_LIBRARY_PATH baked into the release gate.
  6. Low - README points at the feature branch and adds enforce_eager to the quickstart although graph mode is qualified; the release gate pins DMI by raw commit.
  7. Note (pre-existing) - the MoERunner._fse_fuse_gate combined-logits path is not guarded; no DMI model triggers it in 0.29.
  8. Nits - tests/test_request_order.py:488 still sets is_internal_router on a fake runner; the Kimi PP assertion lacks upstream's message.

Not run on my side: the portable pytest suite (no vLLM 0.29 environment here), the GPU cells, and the wheel build. The reported 668/4/11 and the six bitwise-equal cells are taken as stated.

hidden_states = self.input_layernorm(hidden_states)
else:
hidden_states, residual = self.input_layernorm(hidden_states, residual)
self.hook_resid_pre(residual)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rewrite to observe the fused-norm residual is sound: both the CUDA fused_add_rms_norm kernel and the native path round the fp32 sum once to BF16, so this equals the old hidden_states + residual, and DMI's ring producer launches on the current stream (native/csrc/ring/ring_torch_op.cpp, getCurrentCUDAStream), so the later in-place update of this buffer by post_attention_layernorm cannot race the copy.

What is missing is value-level evidence. check_storage in tests/v029_smoke.py only asserts torch.isfinite for resid_pre, and resid_mid is not in the tested hook selection at all, so the change most likely to alter what researchers store is verified only by the identity/order stubs in test_v029_port_contract.py. Suggest one GPU run with resid_pre,resid_mid,resid_final selected that compares the stored tensors against the old hidden_states + residual expression (bitwise in eager, tight tolerance under graphs), or an explicit note in docs/v029-port.md that captured residuals have not been numerically compared on 0.29. Same comment applies to qwen2.py and llama.py.

@@ -59,7 +59,6 @@
"minimax_m2.py": "vllm/model_executor/models/minimax_m2.py",
"mistral.py": "vllm/model_executor/models/mistral.py",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These copies have now been re-audited against 0.29.0, and several were rewritten in this PR (Qwen2/Qwen3/Llama residual taps and LM-head tying, Qwen3-MoE/GLM routing, Kimi SP, Granite RoPE, GPT-2 loader), but every model and oracle file still carries # Adapted from ... in official vLLM 0.27.1.. This test asserts that exact 0.27.1 string at lines 131 and 229, so the suite currently enforces the stale provenance in exactly the files that changed. Suggest bumping the header in all copied files and the two constants here to 0.29.0 (and the docstring at tests/test_model_contracts.py:1).

Comment thread tests/test_olmo3_p_contract.py Outdated

from __future__ import annotations
Legacy source remains for reference; it is not a supported registry target.
"""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failing closed on the registry is the right call, but the leftover source is no longer inert: src/dmi_vllm_integration/models/olmo3.py:63 imports vllm.model_executor.models.olmo3, which does not exist in 0.29, so the module raises ImportError. tests/oracles/__init__.py:54 still lazily registers DMIOlmo3CompareForCausalLM, tests/compare_worker.py:35 still remaps Olmo3ForCausalLM to it, and MODEL_CLASSES in test_models_source_contract.py still lists olmo3.py. Lazy registration hides the broken import until a compare run selects it. Suggest deleting the module, oracle, registry entry, and remap (git history keeps them), or moving them under an explicitly excluded legacy/ path.

"speculative decoding"
)
if (
getattr(parallel, "enable_batch_sharded_sampling", False)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attribute name is correct for 0.29 (ParallelConfig.enable_batch_sharded_sampling, typed bool | None), and the guard is necessary because the runner calls compute_logits_local (gpu/model_runner.py:1416) and bypasses the DMI final-logits hook.

Hardening suggestion: this getattr(..., False) and the nested getattr(..., "in_progress_prompt_logprobs", None) near line 2039 both fail open if upstream renames the attribute, and both unit tests use SimpleNamespace fakes so they would not notice. Since the package pins an exact vLLM version, a small contract test asserting hasattr(ParallelConfig, "enable_batch_sharded_sampling") and hasattr(PromptLogprobsWorker, "in_progress_prompt_logprobs") on the real classes would turn a silent no-op into a loud failure.

)
if captures_router_logits and any(
runner.is_monolithic and runner.is_internal_router
runner.is_monolithic and runner.gate is not None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified against 0.29: MoERunner.gate (runner/moe_runner.py:270) is the right replacement for the removed is_internal_router, and MoERunner is still re-exported from fused_moe/layer.py.

Not a regression, just a boundary the audit does not list: when a model hands the runner both gate and shared_expert_gate, MoERunner._fse_fuse_gate is true and the runner passes combined logits (num_experts + 1 columns) to select_experts (moe_runner.py:898-900), so the observer would capture a router-logits tensor with an extra column. This path existed in 0.27.1 as well, and in 0.29 only qwen3_next.py uses it, so no DMI model is exposed today. Worth a one-line rejection on runner._fse_fuse_gate or a documented boundary in docs/vllm_contract.md.

Comment thread tests/run_v029_smoke.sh Outdated
if [[ "$execution" == graph ]]; then graph_args=(--graph); fi
capture_id="dmi-$cell-${run_root##*/}"
for mode in stock monitored; do
env -u LD_LIBRARY_PATH \

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

env -u LD_LIBRARY_PATH is a workaround for one host's inherited path (per docs/v029-port.md), but baked into the shared script and into gpu-release-gate.yml it can break runners that legitimately need LD_LIBRARY_PATH for CUDA. Suggest making it opt-in (for example DMI_V029_CLEAR_LD_LIBRARY_PATH=1). Same thought for the grep -q 'Directly load AOT compilation' check on line 46: correct for 0.29 (compilation/decorators.py:314), but it is a log-string contract and should be recorded as one.

Comment thread README.md Outdated
checkout, including its native-backend build. This port was tested with DMI
`c222f18c4db55f6f2d7136b1d6608c0b540b273a` (API v1). Build the native backend
against the **same PyTorch/CUDA as vLLM 0.29.0**, not a 0.27 environment.
From the `vllm-0.29-support` integration checkout, run:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After merge this should point at main or the release tag rather than the feature branch.

Comment thread README.md Outdated
llm = LLM(
model="Qwen/Qwen3-0.6B",
worker_cls="dmi_vllm_integration.worker.DMXGPUWorker",
enforce_eager=True,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This README and docs/v029-port.md both say default compilation plus CUDA graphs are qualified, but the quickstart here (and --enforce-eager in the serve example below) reads as a requirement. Suggest dropping it, or stating plainly that graph mode is supported and eager is optional.

with:
repository: ProjectDMX/DMI
ref: v1.1.0
ref: c222f18c4db55f6f2d7136b1d6608c0b540b273a

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pinning a raw commit is reproducible but hard to read next to ci.yml's v1.1.0 / main matrix and pyproject's DMI>=1.1.0,<2.0. c222f18 is DMI 1.2.0 (per pyproject.toml in that checkout); tagging it and pinning the tag would make the release gate self-describing.

assert hidden_states is not None
assert residual is not None
if not get_pp_group().is_last_rank:
assert not self.use_sequence_parallel

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: upstream's equivalent assertion carries a message ("Currently, SP is not supported with PP"); worth keeping it here for the same reason.

@zhaoyboo

Copy link
Copy Markdown
Contributor Author

Addressed the review findings in the follow-up commit:

  1. Residual values: added an independent eager norm-input oracle (tests/v029_residual_reference.py, opt-in --residual-reference). It computes the previous hidden_states + residual expression before in-place normalization updates, rather than using a DMI HookPoint output as its reference. Qwen3-0.6B V1 eager, BF16, TP1: all 1,368 residual rows (resid_pre, resid_mid, resid_final, all 28 layers / final norm) match actual ClickHouse tensors exactly; stock and monitored references match too. 1,416 total stored rows, identical public outputs and 8 raw-logit steps. Missing/duplicate keys, changed finite values, dtype/shape and identity mismatches have negative controls. The release wrapper now includes this value gate. Graph residual numerical comparison and Qwen2/Llama checkpoint-level residual validation remain explicitly unqualified; no broader claim is made.
  2. Provenance: retained copied-model/oracle headers and their source-contract expectations now name 0.29.0; updated test_model_contracts.py docstring.
  3. OLMo3: removed the broken model, compare oracle, lazy oracle target, compare remap and source-test entry. Added absence regression and removed its obsolete inventory groups. Updated audit: 866 occurrences / 556 mapped groups, none unmapped.
  4. V2 guards: added real-object contracts for ParallelConfig.enable_batch_sharded_sampling and PromptLogprobsWorker.in_progress_prompt_logprobs. The latter is an instance attribute, so the test constructs its CPU-only state and checks request add/remove transitions rather than using class-level hasattr.
  5. Harness portability: DMI_V029_CLEAR_LD_LIBRARY_PATH=1 is now explicit opt-in, including the workflow input; default preserves the runner's library path. Both wrapper paths have subprocess tests with a fake Python executable. In-process engine mode is rejected with an actionable explanation. pause_scheduler('wait'), private LLM.request_counter, the AOT log-string assertion and residual-reference layout reads are documented boundaries.
  6. README / gate: removed the feature-branch-specific install wording and eager flags from quickstarts. Kept the immutable DMI c222f18 pin, annotated as DMI 1.2.0/API v1: no matching v1.2 release tag exists, so this PR does not create a core release tag.
  7. Documented the existing _fse_fuse_gate combined-logits boundary as outside the routing shape contract; no registered DMI model currently exercises it.
  8. Updated the fake MoERunner to gate=None and retained upstream's Kimi SP/PP assertion message.

Validation: 680 passed, 4 skipped, 11 deselected in the portable gate. The three router-state skips pass in clean isolated test processes; the remaining optional layer-range module requires a newer DMI API than the pinned core. All 21 production lazy targets import without the native stub. Wheel and sdist build from a clean temporary source snapshot (no OLMo3 in the wheel); bash -n and git diff --check pass.

Committed GPU receipt: docs/evidence/v029-residual-review.json. Scope, methodology and raw-evidence location are in docs/v029-port.md. This follow-up reran the one new residual eager cell, not the prior full GPU matrix. No review threads were auto-resolved.

@XbzOnGit XbzOnGit left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes: revert the residual-hook placement, keep this PR to the version bump

I ran this branch on hardware (3x RTX 4090, CUDA 13.0, DMI c222f18, torch 2.13.0+cu130, vLLM 0.29.0 from PyPI) against main at 420bafb on vLLM 0.27.1 in a second environment on the same torch. The forced parts of the port are correct and I verified them: all six smoke cells reproduce your receipts (744 rows each, 1,416 / 1,368 for the residual cell), request order at six topologies, online storage bitwise at TP1/TP2/PP2, DMILLM, Qwen2-MoE routing at TP2 (69,920 / 69,920 rows), compile-cache reload, V2 parity, and the CPU suite at 680 / 4 / 11. Thank you for that work.

One elective change does not hold up under measurement and I am asking for it to be reverted before merge: observing the fused norm's returned residual instead of computing hidden_states + residual for hook_resid_pre, hook_resid_mid, and hook_resid_final in qwen2.py, qwen3.py, llama.py.

1. The old placement perturbs the model's numerics less

Gate step 09 (Qwen3-0.6B, TP2, compiled, greedy) fails on this branch: request 3 flips from ' purple\nThis is the' (198) to ' purple\n\nThis is the' (271). I bisected it with one engine per process, recording top-5 logprobs at every step (4 prompts, 12 steps, 60 records), each monitored run compared against the same version's stock run.

Version Hooks in the compiled TP2 graph Records differing from stock / 60 Max logprob shift Greedy token at the tie
0.27.1 residual only (old placement) 15 0.095 198, tie position untouched
0.27.1 all hooks 60 0.368 198 (exact tie)
0.29 residual only (new placement) 60 0.867 198 (exact tie)
0.29 q,k,v,z 60 0.802 198 (exact tie)
0.29 residual + q,k,v,z 60 0.546 271, flipped
0.29 all hooks (2 shared-cache + 3 fresh-cache compiles + 1 null mode, all bitwise identical) 60 0.546 271, flipped
0.29 final_logits only 0 0 198
0.29 ln1, attn_out, ln2, mlp_in, mlp_out 0 0 198

The effect is deterministic across fresh compiles and identical in null mode, so it is the presence of the hook ops in the compiled graph, not the copies. The FX graphs in the compile cache have identical model ops in every variant; only the ring.producer_prefix nodes differ. The residual hooks are one of the two ingredients of the flip; the other is q/k/v/z, which predates this PR. At TP1 under compilation both placements are bitwise clean, and in eager TP2 tokens match, so the difference is confined to compiled TP>1, which is exactly where the old placement is the safer one: it reads the norm's inputs, which are already materialized buffers, and writes a private temporary, so it cannot change how inductor schedules the fused norm. The new placement adds an opaque reader to the fused region's output.

The 15 records that differ on 0.27.1 with the old placement carry the same values 0.29 stock produces at those positions, i.e. ordinary rounding-order noise of the same size as the upstream version bump itself (stock 0.27.1 vs stock 0.29: max 0.095). The one control still missing is the old placement compiled under 0.29; it is queued and I will attach it here. On everything measured so far the old placement is the less perturbing one.

2. "Authoritative" buys nothing measurable, and the recorded value is from a more perturbed forward

Your own follow-up oracle shows the two placements record bit-identical values: 1,368 / 1,368 residual rows equal to the old hidden_states + residual expression. I reproduced that exactly. Both the CUDA kernel and the native decomposition round the fp32 sum once, so there is no configuration in this PR's matrix where the fused norm's residual differs from the recomputed one. The case where it would matter (a fused all-reduce + norm kernel producing the residual from fp32 partial sums) is not enabled and not tested here.

Meanwhile the recorded tensor is only "authoritative" for the monitored run, and under compiled TP2 that run is now further from the unmonitored model than before. A residual stream that is bit-exact to a forward the user did not ask for is less accurate for research use, not more.

3. The performance gain is not measurable

Interleaved A/B, same GPU, 2 warmup + 5 timed iterations, tests/benchmark.py:

Row Mode 0.27.1 (old placement) 0.29 (new placement)
Qwen3-0.6B, graph, TP1, residual hooks only ring_active 174.6 ms (std 1.3) 176.8 ms (std 2.9)
Qwen3-0.6B, graph, TP1, residual hooks only ring_db 191.4 ms (std 10.6) 177.2 ms (std 1.1)
Qwen3-0.6B, graph, TP1, all hooks ring_active 287.2 ms (std 45.7) 286.9 ms (std 46.1)
Qwen3-0.6B, graph, TP1, 32x128, all hooks ring_active 806.4 ms (std 46.3) 812.6 ms (std 44.4)
Llama-3.1-8B, graph, TP1, all hooks ring_active 1243.7 ms (std 2.6) 1233.8 ms (std 3.1)

The saved add is one BF16 elementwise op per hook site. Under compilation inductor can fuse it into the norm's reduction kernel as an extra store, which is why it costs nothing to keep; under eager it is one extra kernel on a 0.6B model, below the noise floor.

4. A version bump should be a version bump

Diffing upstream v0.27.1 against v0.29.0 at every boundary this PR touches, the forced changes are the V2 prepare_inputs/dispatch signatures, is_internal_router to gate, the AutoWeightsLoader keyword removals, OLMo3, Granite use_rope, the Kimi K3 SP mirror, the pins, and the prompt-logprobs attribute fix. That is on the order of a hundred source lines and all of it is right. The residual-hook rewrite, the hook_v view cleanup, Llama compute_logits_local, and the tie_weights alignment are not needed for 0.29 to work; the loader change stands on its own. Please move them to a follow-up so that the port can be reviewed and bisected as a port, and so that a numerics change to three model copies gets its own TP2 compiled evidence before it lands.

Concretely

  • Restore the explicit-add placement at the six hook sites in qwen2.py, qwen3.py, llama.py; keep every loader and LM-head fix in those files. Adjust tests/test_v029_port_contract.py accordingly; your residual oracle already computes the old expression and continues to apply.
  • Split the other elective items into a separate PR.
  • Independently of placement, gate step 09 compares greedy tokens of two differently compiled TP2 engines and passed on 0.27.1 only because the tie broke toward the lower id. It needs a logprob tolerance or an eager-mode comparison at TP>1, otherwise it will keep flipping.

hidden_states = self.input_layernorm(hidden_states)
else:
hidden_states, residual = self.input_layernorm(hidden_states, residual)
self.hook_resid_pre(residual)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please restore the previous placement here and at hook_resid_mid / hook_resid_final (and the same three sites in qwen2.py and llama.py): compute hidden_states + residual before the norm and pass that temporary to the hook. Values are bit-identical either way (your 1,368-row oracle), the saved add is not measurable, and under compiled TP2 this placement adds an opaque reader on the fused norm's output and perturbs the model's logits (60/60 records, up to 0.87 nats vs stock) where the old placement perturbs 15/60, 0.095. Details and tables in the review body.

@zhaoyboo

Copy link
Copy Markdown
Contributor Author

Addressed the scope correction in 35db444. The optional model rewrites should not have been bundled into this version port.

  • Restored pre-port residual placement in Qwen2/Qwen3/Llama, Qwen3's V views, the previous weight ties (including the Qwen3 oracles), and removed the added Llama compute_logits_local. Llama's resid_mid was already post-norm at 420bafb; I left that existing behavior unchanged rather than introducing another placement change.
  • Kept the required loader/mapper, runner, routing, Kimi SP, Granite RoPE and upstream-removal adaptations. AST comparison confirms the restored forward/constructor bodies match the base.
  • Retained the independent eager residual-value oracle; replaced the rewrite-specific contracts with pre-port value/order/disabled-hook and final-tap regressions.
  • Portable gate: 689 passed, 4 skipped, 11 deselected. The three router-state skips pass in separate fresh processes; the optional layer-range module still needs a newer DMI API. Static mapping: 865 occurrences / 555 groups, zero unmapped. Diff and shell syntax checks pass.

All three local GPUs were occupied, so I did not launch a GPU rerun or stop any process. The PR description and audit now clearly separate the old GPU receipts from corrected-head qualification. The same-version compiled TP2 control and bounded V1/V2 rerun remain pending; I am not claiming the rollback fixes the observed divergence. The compiled release gate and exact comparison thresholds are unchanged, so the outstanding step-09 issue is not hidden by a tolerance increase or an eager substitution. No review threads were auto-resolved and no optimization follow-up PR was opened.

@XbzOnGit XbzOnGit left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@XbzOnGit
XbzOnGit merged commit c17b9f2 into ProjectDMX:main Sep 19, 2026
3 checks passed
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