fix(rocm/gemma4): #838 widen indexed MoE gate to T<=63 + retirement-safe dispatch - #1046
fix(rocm/gemma4): #838 widen indexed MoE gate to T<=63 + retirement-safe dispatch#1046bakon11 wants to merge 13 commits into
Conversation
8343f06 to
9d4a16c
Compare
…ce invariant that survives mudler#1047 Maintainer repairs applied while landing mudler#1046. No product behavior changes. Donor evidence moves from `.agents/evidence/` -- a path `scripts/check-pr-size.py` cannot classify, so the gate refused the change outright -- to `.agents/specs/rocm-gemma4-indexed-max-t-donor.{md,log}`, which match `SPEC` and `SPEC_EVIDENCE` at `check-pr-size.py:188-189`. The bytes are unchanged: both slice sha256s still match the manifest table, which is what that table exists to check. `docs/FEATURES.md` is left as `main` has it. The branch had rewritten the Gemma4 row, dropping the spec link, the `VT_GEMMA4_*`/`VT_ATTN_*` env pointer and the `test_gemma4_rocm_fp8_seams` seam name. Restoring those and adding the mudler#838 sentence does not fit -- `check-public-doc-tables` caps a cell at 220 characters and main's is already 219 -- and `check-doc-checkpoint` does not ask for a FEATURES edit here, because `feature_surface` now keys off a change to the set of `REGISTER_VLLM_MODEL` registrations (mudler#595, mudler#1086) and this branch changes none. The mudler#838 detail stays where the branch already put it in full: `docs/USAGE.md`, `docs/ENVIRONMENT.md` and the spec. The source-invariant case in `test_gemma4_indexed_max_t.cpp` sliced `rocm_gemma4_experts.hip` between `RetireGemma4Fp8TopKIndexedPeer` and the next symbol, then asserted `return true;` was absent from the result. That is a slice of the GAP between two functions, not of the function, so any unrelated definition added after the closing brace lands inside it. Open PR mudler#1047 inserts about 160 lines exactly there and carries its own `return true;`, which would have turned `main` red on `build-test-cpu` after both landed -- this case is registered unconditionally and reads the source from disk. It now brace-matches the function's own body, and gains two assertions that the slice is bounded and that the function does sync the compute stream, so the guarantee is stated more completely than before rather than relaxed. Proved by mutation against the real test binary, built standalone and pointed at a scratch source root: the repaired case reds on a mutant that discards the sync status and returns unconditional success (3 assertions fail), and stays green under the mudler#1047-shaped insertion, where the original case reds. The worktree sources were never mutated; the scratch copy was restored and its sha256 compared against the tree. The remaining review findings need a gfx1201 pair and are recorded under `## Open on gfx1201 hardware` in the row spec instead of being papered over. The `rw_idx` pooled buffer on the T=1 path contradicts Scope item 3's hipGraph-stable invariant, and this branch still records no measurement for a change that flips a product default across T=2..63. The branch was rebuilt by rebase rather than merge, so it carries no untrailered merge commit; all six original commits keep their authorship. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: ClaudeCode:claude-opus-5 [ClaudeCode]
…ce invariant that survives mudler#1047 Maintainer repairs applied while landing mudler#1046. No product behavior changes. Donor evidence moves from `.agents/evidence/` -- a path `scripts/check-pr-size.py` cannot classify, so the gate refused the change outright -- to `.agents/specs/rocm-gemma4-indexed-max-t-donor.{md,log}`, which match `SPEC` and `SPEC_EVIDENCE` at `check-pr-size.py:188-189`. The bytes are unchanged: both slice sha256s still match the manifest table, which is what that table exists to check. `docs/FEATURES.md` is left as `main` has it. The branch had rewritten the Gemma4 row, dropping the spec link, the `VT_GEMMA4_*`/`VT_ATTN_*` env pointer and the `test_gemma4_rocm_fp8_seams` seam name. Restoring those and adding the mudler#838 sentence does not fit -- `check-public-doc-tables` caps a cell at 220 characters and main's is already 219 -- and `check-doc-checkpoint` does not ask for a FEATURES edit here, because `feature_surface` now keys off a change to the set of `REGISTER_VLLM_MODEL` registrations (mudler#595, mudler#1086) and this branch changes none. The mudler#838 detail stays where the branch already put it in full: `docs/USAGE.md`, `docs/ENVIRONMENT.md` and the spec. The source-invariant case in `test_gemma4_indexed_max_t.cpp` sliced `rocm_gemma4_experts.hip` between `RetireGemma4Fp8TopKIndexedPeer` and the next symbol, then asserted `return true;` was absent from the result. That is a slice of the GAP between two functions, not of the function, so any unrelated definition added after the closing brace lands inside it. A `git merge-tree` of this branch with open PR mudler#1047 (`3df512a11`) grows that gap from 16 lines to 176 and puts three `return true;` inside it, which turns `main` red on `build-test-cpu` once both land -- this case is registered unconditionally and reads the source from disk. It now brace-matches the function's own body, and gains two assertions that the slice is bounded and that the function does sync the compute stream, so the guarantee is stated more completely than before rather than relaxed. Proved against the real test binary, built standalone and pointed at a scratch source root. The repaired case reds on a mutant that discards the sync status and returns unconditional success (3 assertions fail), and stays green on the actual merged tree, where the original case reds with 1 failed assertion. The worktree sources were never mutated; the scratch copy was restored and its sha256 compared against the tree. The remaining review findings need a gfx1201 pair and are recorded under `## Open on gfx1201 hardware` in the row spec instead of being papered over. The `rw_idx` pooled buffer on the T=1 path contradicts Scope item 3's hipGraph-stable invariant, and this branch still records no measurement for a change that flips a product default across T=2..63. The branch was rebuilt by rebase rather than merge, so it carries no untrailered merge commit; all six original commits keep their authorship. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: ClaudeCode:claude-opus-5 [ClaudeCode]
9d4a16c to
cff626f
Compare
|
Thanks — the core of this is right, and the double-scale fix inside it is a real bug caught in passing. I rebased the branch onto current What I changed on your branchYour six commits are preserved with their authorship, rebased (not merged, so no untrailered merge commit). One repair commit sits on top.
What I could not verifyI have no RDNA4 hardware and did not build the project (this host is at 95% disk, and a false ENOSPC failure reads as a code verdict). The test above was compiled and run as a standalone TU — real doctest, real binary, real assertions — and the full test file passes What needs youThese are recorded under A. B. No measurement. #838 is filed as C. The per-expert scale costs one kernel launch per token — up to 63 of them. I deliberately did not make this change, for a reason I think is worth stating: collapsing the loop removes the structural guarantee that D. Six test-only helpers ship in a production header. While you are there: the "tensor oracle" computes E. Smaller, all yours:
One heads-up for #1047The same Happy to take A and C myself if you send me a trace, or just confirm the graph-capture behavior — I mainly need someone with the hardware to say which way A should go. Once A and B are answered this is ready; everything else here is either landed or filed. |
|
@bakon11 — I re-verified this against current State as of
Your
Two things still hold this open, and both are yours. 1. Your reason for not mutating in place is good and I am not asking you to undo it — "fallback must still see unscaled weights" is a real correctness fix for T>1. The shape that keeps both is a TLS-stable It is latent today — decode hipGraph is lab-only — but it is silent, which is the part I do not want to leave undocumented. 2. No measurement on a Everything else here is ready. |
|
Both items accepted — the TLS-stable |
|
Both owed items delivered (pushed 1. hipGraph capture-stability — 2. The T=2..63 default-flip measurement (2×R9700, isolated serve, PREFIX_CACHE=0, profile off, 4-process A(idx=63)→B(1)→B(1)→A(63), 5 bursts/leg, 32 tok/request API-usage denominator, independently reviewed raw):
So the flip pays at both ends of the range and the win grows with T; the shape question is answered — it's not a T=63-only artifact. rocprof arm-verification confirmed each arm dispatches the distinct kernel path before timing was accepted. Numbers + protocol are in |
T=1 scaled router weights live in RwIdxTls (compute_dev + T*top_k). T>1 keeps pooled rw_idx_owned. Fresh Copy+scale every call; never mutate caller rw. Host source invariants added. No GPU. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
VT_GEMMA4_PROFILE=1 emits one parseable dispatch line per RunGemma4Moe at successful indexed return (T=1 TLS and T>1 owned) and at legacy host-gather before router D2H. No control-flow/sync/copy/alloc change. Default OFF silent. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
…ler#1046) Set compute device before compute-stream event record; expert device before expert wait/H2D/launch/event; compute device before compute wait and result D2D. Fail retirement syncs each stream under its owning device and restores compute. Replaces the false "no hipSetDevice" claim. No algorithm/alloc/event order/lifetime/overlap/gate/fallback change. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
Set compute before cst sync; set tls.edev before est sync when TLS ownership matches; restore compute on exit. Best-effort ok=false on any set/sync fail. Completes a060/51ed current- device contract. No reinit or event-destroy. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
|
This branch is currently conflicting with |
|
Conflict resolved — merged current |
dd19c8e to
9f0ace5
Compare
…ce invariant that survives mudler#1047 Maintainer repairs applied while landing mudler#1046. No product behavior changes. Donor evidence moves from `.agents/evidence/` -- a path `scripts/check-pr-size.py` cannot classify, so the gate refused the change outright -- to `.agents/specs/rocm-gemma4-indexed-max-t-donor.{md,log}`, which match `SPEC` and `SPEC_EVIDENCE` at `check-pr-size.py:188-189`. The bytes are unchanged: both slice sha256s still match the manifest table, which is what that table exists to check. `docs/FEATURES.md` is left as `main` has it. The branch had rewritten the Gemma4 row, dropping the spec link, the `VT_GEMMA4_*`/`VT_ATTN_*` env pointer and the `test_gemma4_rocm_fp8_seams` seam name. Restoring those and adding the mudler#838 sentence does not fit -- `check-public-doc-tables` caps a cell at 220 characters and main's is already 219 -- and `check-doc-checkpoint` does not ask for a FEATURES edit here, because `feature_surface` now keys off a change to the set of `REGISTER_VLLM_MODEL` registrations (mudler#595, mudler#1086) and this branch changes none. The mudler#838 detail stays where the branch already put it in full: `docs/USAGE.md`, `docs/ENVIRONMENT.md` and the spec. The source-invariant case in `test_gemma4_indexed_max_t.cpp` sliced `rocm_gemma4_experts.hip` between `RetireGemma4Fp8TopKIndexedPeer` and the next symbol, then asserted `return true;` was absent from the result. That is a slice of the GAP between two functions, not of the function, so any unrelated definition added after the closing brace lands inside it. A `git merge-tree` of this branch with open PR mudler#1047 (`3df512a11`) grows that gap from 16 lines to 176 and puts three `return true;` inside it, which turns `main` red on `build-test-cpu` once both land -- this case is registered unconditionally and reads the source from disk. It now brace-matches the function's own body, and gains two assertions that the slice is bounded and that the function does sync the compute stream, so the guarantee is stated more completely than before rather than relaxed. Proved against the real test binary, built standalone and pointed at a scratch source root. The repaired case reds on a mutant that discards the sync status and returns unconditional success (3 assertions fail), and stays green on the actual merged tree, where the original case reds with 1 failed assertion. The worktree sources were never mutated; the scratch copy was restored and its sha256 compared against the tree. The remaining review findings need a gfx1201 pair and are recorded under `## Open on gfx1201 hardware` in the row spec instead of being papered over. The `rw_idx` pooled buffer on the T=1 path contradicts Scope item 3's hipGraph-stable invariant, and this branch still records no measurement for a change that flips a product default across T=2..63. The branch was rebuilt by rebase rather than merge, so it carries no untrailered merge commit; all six original commits keep their authorship. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: ClaudeCode:claude-opus-5 [ClaudeCode]
T=1 scaled router weights live in RwIdxTls (compute_dev + T*top_k). T>1 keeps pooled rw_idx_owned. Fresh Copy+scale every call; never mutate caller rw. Host source invariants added. No GPU. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
VT_GEMMA4_PROFILE=1 emits one parseable dispatch line per RunGemma4Moe at successful indexed return (T=1 TLS and T>1 owned) and at legacy host-gather before router D2H. No control-flow/sync/copy/alloc change. Default OFF silent. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
…ler#1046) Set compute device before compute-stream event record; expert device before expert wait/H2D/launch/event; compute device before compute wait and result D2D. Fail retirement syncs each stream under its owning device and restores compute. Replaces the false "no hipSetDevice" claim. No algorithm/alloc/event order/lifetime/overlap/gate/fallback change. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
Set compute before cst sync; set tls.edev before est sync when TLS ownership matches; restore compute on exit. Best-effort ok=false on any set/sync fail. Completes a060/51ed current- device contract. No reinit or event-destroy. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
|
Rebased as asked — What I did: replayed the 11 feature commits onto current
Verified on the new head: ROCm evidence re-run is on our 2×R9700 queue and I'll post it here; the previously reported numbers (indexed T≤63 vs host-gather: +14.0% @t=2, +24.6% @t=63, T=8 within dispersion) were measured on the same payload. |
9f0ace5 to
1066a1f
Compare
…ce invariant that survives mudler#1047 Maintainer repairs applied while landing mudler#1046. No product behavior changes. Donor evidence moves from `.agents/evidence/` -- a path `scripts/check-pr-size.py` cannot classify, so the gate refused the change outright -- to `.agents/specs/rocm-gemma4-indexed-max-t-donor.{md,log}`, which match `SPEC` and `SPEC_EVIDENCE` at `check-pr-size.py:188-189`. The bytes are unchanged: both slice sha256s still match the manifest table, which is what that table exists to check. `docs/FEATURES.md` is left as `main` has it. The branch had rewritten the Gemma4 row, dropping the spec link, the `VT_GEMMA4_*`/`VT_ATTN_*` env pointer and the `test_gemma4_rocm_fp8_seams` seam name. Restoring those and adding the mudler#838 sentence does not fit -- `check-public-doc-tables` caps a cell at 220 characters and main's is already 219 -- and `check-doc-checkpoint` does not ask for a FEATURES edit here, because `feature_surface` now keys off a change to the set of `REGISTER_VLLM_MODEL` registrations (mudler#595, mudler#1086) and this branch changes none. The mudler#838 detail stays where the branch already put it in full: `docs/USAGE.md`, `docs/ENVIRONMENT.md` and the spec. The source-invariant case in `test_gemma4_indexed_max_t.cpp` sliced `rocm_gemma4_experts.hip` between `RetireGemma4Fp8TopKIndexedPeer` and the next symbol, then asserted `return true;` was absent from the result. That is a slice of the GAP between two functions, not of the function, so any unrelated definition added after the closing brace lands inside it. A `git merge-tree` of this branch with open PR mudler#1047 (`3df512a11`) grows that gap from 16 lines to 176 and puts three `return true;` inside it, which turns `main` red on `build-test-cpu` once both land -- this case is registered unconditionally and reads the source from disk. It now brace-matches the function's own body, and gains two assertions that the slice is bounded and that the function does sync the compute stream, so the guarantee is stated more completely than before rather than relaxed. Proved against the real test binary, built standalone and pointed at a scratch source root. The repaired case reds on a mutant that discards the sync status and returns unconditional success (3 assertions fail), and stays green on the actual merged tree, where the original case reds with 1 failed assertion. The worktree sources were never mutated; the scratch copy was restored and its sha256 compared against the tree. The remaining review findings need a gfx1201 pair and are recorded under `## Open on gfx1201 hardware` in the row spec instead of being papered over. The `rw_idx` pooled buffer on the T=1 path contradicts Scope item 3's hipGraph-stable invariant, and this branch still records no measurement for a change that flips a product default across T=2..63. The branch was rebuilt by rebase rather than merge, so it carries no untrailered merge commit; all six original commits keep their authorship. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: ClaudeCode:claude-opus-5 [ClaudeCode]
T=1 scaled router weights live in RwIdxTls (compute_dev + T*top_k). T>1 keeps pooled rw_idx_owned. Fresh Copy+scale every call; never mutate caller rw. Host source invariants added. No GPU. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
VT_GEMMA4_PROFILE=1 emits one parseable dispatch line per RunGemma4Moe at successful indexed return (T=1 TLS and T>1 owned) and at legacy host-gather before router D2H. No control-flow/sync/copy/alloc change. Default OFF silent. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
…ler#1046) Set compute device before compute-stream event record; expert device before expert wait/H2D/launch/event; compute device before compute wait and result D2D. Fail retirement syncs each stream under its owning device and restores compute. Replaces the false "no hipSetDevice" claim. No algorithm/alloc/event order/lifetime/overlap/gate/fallback change. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
Set compute before cst sync; set tls.edev before est sync when TLS ownership matches; restore compute on exit. Best-effort ok=false on any set/sync fail. Completes a060/51ed current- device contract. No reinit or event-destroy. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
…opped by rebase (mudler#1046) The 11-commit replay onto current main rewrote the Gemma4-FP8-on-ROCm section wholesale, which silently deleted two paragraphs that landed on main after this branch was authored: the contributor KEEP recipe (2014/1099 t/s prefill, 55 t/s decode) and the no-denominator caveat referencing mudler#845. Both restored verbatim; the indexed-max-T text this PR adds is unchanged. Net USAGE.md diff vs main is now additions plus the intentional rewrite of the env sentence only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1066a1f to
38fe058
Compare
…ce invariant that survives mudler#1047 Maintainer repairs applied while landing mudler#1046. No product behavior changes. Donor evidence moves from `.agents/evidence/` -- a path `scripts/check-pr-size.py` cannot classify, so the gate refused the change outright -- to `.agents/specs/rocm-gemma4-indexed-max-t-donor.{md,log}`, which match `SPEC` and `SPEC_EVIDENCE` at `check-pr-size.py:188-189`. The bytes are unchanged: both slice sha256s still match the manifest table, which is what that table exists to check. `docs/FEATURES.md` is left as `main` has it. The branch had rewritten the Gemma4 row, dropping the spec link, the `VT_GEMMA4_*`/`VT_ATTN_*` env pointer and the `test_gemma4_rocm_fp8_seams` seam name. Restoring those and adding the mudler#838 sentence does not fit -- `check-public-doc-tables` caps a cell at 220 characters and main's is already 219 -- and `check-doc-checkpoint` does not ask for a FEATURES edit here, because `feature_surface` now keys off a change to the set of `REGISTER_VLLM_MODEL` registrations (mudler#595, mudler#1086) and this branch changes none. The mudler#838 detail stays where the branch already put it in full: `docs/USAGE.md`, `docs/ENVIRONMENT.md` and the spec. The source-invariant case in `test_gemma4_indexed_max_t.cpp` sliced `rocm_gemma4_experts.hip` between `RetireGemma4Fp8TopKIndexedPeer` and the next symbol, then asserted `return true;` was absent from the result. That is a slice of the GAP between two functions, not of the function, so any unrelated definition added after the closing brace lands inside it. A `git merge-tree` of this branch with open PR mudler#1047 (`3df512a11`) grows that gap from 16 lines to 176 and puts three `return true;` inside it, which turns `main` red on `build-test-cpu` once both land -- this case is registered unconditionally and reads the source from disk. It now brace-matches the function's own body, and gains two assertions that the slice is bounded and that the function does sync the compute stream, so the guarantee is stated more completely than before rather than relaxed. Proved against the real test binary, built standalone and pointed at a scratch source root. The repaired case reds on a mutant that discards the sync status and returns unconditional success (3 assertions fail), and stays green on the actual merged tree, where the original case reds with 1 failed assertion. The worktree sources were never mutated; the scratch copy was restored and its sha256 compared against the tree. The remaining review findings need a gfx1201 pair and are recorded under `## Open on gfx1201 hardware` in the row spec instead of being papered over. The `rw_idx` pooled buffer on the T=1 path contradicts Scope item 3's hipGraph-stable invariant, and this branch still records no measurement for a change that flips a product default across T=2..63. The branch was rebuilt by rebase rather than merge, so it carries no untrailered merge commit; all six original commits keep their authorship. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: ClaudeCode:claude-opus-5 [ClaudeCode]
T=1 scaled router weights live in RwIdxTls (compute_dev + T*top_k). T>1 keeps pooled rw_idx_owned. Fresh Copy+scale every call; never mutate caller rw. Host source invariants added. No GPU. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
VT_GEMMA4_PROFILE=1 emits one parseable dispatch line per RunGemma4Moe at successful indexed return (T=1 TLS and T>1 owned) and at legacy host-gather before router D2H. No control-flow/sync/copy/alloc change. Default OFF silent. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
…ler#1046) Set compute device before compute-stream event record; expert device before expert wait/H2D/launch/event; compute device before compute wait and result D2D. Fail retirement syncs each stream under its owning device and restores compute. Replaces the false "no hipSetDevice" claim. No algorithm/alloc/event order/lifetime/overlap/gate/fallback change. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
Set compute before cst sync; set tls.edev before est sync when TLS ownership matches; restore compute on exit. Best-effort ok=false on any set/sync fail. Completes a060/51ed current- device contract. No reinit or event-destroy. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
…opped by rebase (mudler#1046) The 11-commit replay onto current main rewrote the Gemma4-FP8-on-ROCm section wholesale, which silently deleted two paragraphs that landed on main after this branch was authored: the contributor KEEP recipe (2014/1099 t/s prefill, 55 t/s decode) and the no-denominator caveat referencing mudler#845. Both restored verbatim; the indexed-max-T text this PR adds is unchanged. Net USAGE.md diff vs main is now additions plus the intentional rewrite of the env sentence only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Independent row/ROCM-GEMMA4-INDEXED-MAX-T from origin/main 3ce5a1d. Pins donor gate slices (SHA256 d0d28f3d… / 5509f3f7…). Hypothesis A only; T=19 is observed on serial M1 — cause unconfirmed. Tensor oracle T=2,19,63 same-dev+peer vs serial reference (64cb mudler#4). FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
Default VT_GEMMA4_DECODE_INDEXED_MAX_T=63. T=1 keeps hipGraph TLS acc; T=2..63 uses an owned [T,H] buffer and the existing per-token indexed helpers. T>=64 still misses the gate (prefill-batch). Packed batched / INDEXED_NOSYNC stay out. Host predicate table + host tensor oracle (abs_tol = 2^-7 * max_abs(ref); exact-zero support) vs serial mix. GPU/p42k HOLD. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
b6b7d99e is not a review target (0ee9/5ebb/d2da). - Gemma4IndexedDispatchTokens is the production T-loop; tests inject distinct same-dev/peer helpers and assert witness, offsets, owner canary - Indexed path scales a rw scratch copy; fallback applies host scale once - RunGemma4Fp8TopKIndexedOnExpertDevice restores compute_dev on every return FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
aab2b4a8 is not a review target (7ec2).
- Product-loop helper writes y; independent serial ref; oracle
T={2,19,63} x {same-dev,peer}; stride/ownership REDs corrupt output
- Post-enqueue fail syncs expert+compute streams before rw_idx/acc_idx
return to DevicePool (RetireGemma4Fp8TopKIndexedPeer)
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Hermes:grok-4.6 [Hermes]
d973/0f32 stop-ships on a fresh head (7c416eb6 is not a review target): - retire indexed peer/compute work inside acc_idx lexical scope; quarantine via DBuf::Release when retirement is not observed - RetireGemma4Fp8TopKIndexedPeer fail-closed (no discarded hip errors) - serial ref no longer calls candidate ApplyToken - production selector Gemma4IndexedSelectArm/RunSelectedArm + packed args - T>1 owner is OwnedTH; T=1 TLS rejected for T>1 Host: 10/10 cases, 1099 assertions. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
HIP compile of gemma4_moe.cpp failed: class-template used as a lambda parameter without arguments. Dispatch YT/XT are uint16_t. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
…ce invariant that survives mudler#1047 Maintainer repairs applied while landing mudler#1046. No product behavior changes. Donor evidence moves from `.agents/evidence/` -- a path `scripts/check-pr-size.py` cannot classify, so the gate refused the change outright -- to `.agents/specs/rocm-gemma4-indexed-max-t-donor.{md,log}`, which match `SPEC` and `SPEC_EVIDENCE` at `check-pr-size.py:188-189`. The bytes are unchanged: both slice sha256s still match the manifest table, which is what that table exists to check. `docs/FEATURES.md` is left as `main` has it. The branch had rewritten the Gemma4 row, dropping the spec link, the `VT_GEMMA4_*`/`VT_ATTN_*` env pointer and the `test_gemma4_rocm_fp8_seams` seam name. Restoring those and adding the mudler#838 sentence does not fit -- `check-public-doc-tables` caps a cell at 220 characters and main's is already 219 -- and `check-doc-checkpoint` does not ask for a FEATURES edit here, because `feature_surface` now keys off a change to the set of `REGISTER_VLLM_MODEL` registrations (mudler#595, mudler#1086) and this branch changes none. The mudler#838 detail stays where the branch already put it in full: `docs/USAGE.md`, `docs/ENVIRONMENT.md` and the spec. The source-invariant case in `test_gemma4_indexed_max_t.cpp` sliced `rocm_gemma4_experts.hip` between `RetireGemma4Fp8TopKIndexedPeer` and the next symbol, then asserted `return true;` was absent from the result. That is a slice of the GAP between two functions, not of the function, so any unrelated definition added after the closing brace lands inside it. A `git merge-tree` of this branch with open PR mudler#1047 (`3df512a11`) grows that gap from 16 lines to 176 and puts three `return true;` inside it, which turns `main` red on `build-test-cpu` once both land -- this case is registered unconditionally and reads the source from disk. It now brace-matches the function's own body, and gains two assertions that the slice is bounded and that the function does sync the compute stream, so the guarantee is stated more completely than before rather than relaxed. Proved against the real test binary, built standalone and pointed at a scratch source root. The repaired case reds on a mutant that discards the sync status and returns unconditional success (3 assertions fail), and stays green on the actual merged tree, where the original case reds with 1 failed assertion. The worktree sources were never mutated; the scratch copy was restored and its sha256 compared against the tree. The remaining review findings need a gfx1201 pair and are recorded under `## Open on gfx1201 hardware` in the row spec instead of being papered over. The `rw_idx` pooled buffer on the T=1 path contradicts Scope item 3's hipGraph-stable invariant, and this branch still records no measurement for a change that flips a product default across T=2..63. The branch was rebuilt by rebase rather than merge, so it carries no untrailered merge commit; all six original commits keep their authorship. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: ClaudeCode:claude-opus-5 [ClaudeCode]
T=1 scaled router weights live in RwIdxTls (compute_dev + T*top_k). T>1 keeps pooled rw_idx_owned. Fresh Copy+scale every call; never mutate caller rw. Host source invariants added. No GPU. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
VT_GEMMA4_PROFILE=1 emits one parseable dispatch line per RunGemma4Moe at successful indexed return (T=1 TLS and T>1 owned) and at legacy host-gather before router D2H. No control-flow/sync/copy/alloc change. Default OFF silent. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
…ler#1046) Set compute device before compute-stream event record; expert device before expert wait/H2D/launch/event; compute device before compute wait and result D2D. Fail retirement syncs each stream under its owning device and restores compute. Replaces the false "no hipSetDevice" claim. No algorithm/alloc/event order/lifetime/overlap/gate/fallback change. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
Set compute before cst sync; set tls.edev before est sync when TLS ownership matches; restore compute on exit. Best-effort ok=false on any set/sync fail. Completes a060/51ed current- device contract. No reinit or event-destroy. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Hermes:grok-4.6 [Hermes]
…opped by rebase (mudler#1046) The 11-commit replay onto current main rewrote the Gemma4-FP8-on-ROCm section wholesale, which silently deleted two paragraphs that landed on main after this branch was authored: the contributor KEEP recipe (2014/1099 t/s prefill, 55 t/s decode) and the no-denominator caveat referencing mudler#845. Both restored verbatim; the indexed-max-T text this PR adds is unchanged. Net USAGE.md diff vs main is now additions plus the intentional rewrite of the env sentence only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…on rewrite (mudler#1046) docs/USAGE.md is a high-traffic file; main moved three times in the last hour. Rewriting the whole Gemma4-FP8-on-ROCm paragraph made every replay a silent preference for our older block (it already dropped two of main's paragraphs once). Restore main's env/GetBlas/hipGraph text verbatim and add the VT_GEMMA4_DECODE_INDEXED_MAX_T documentation as its own adjacent paragraph, so future rebases either apply cleanly or raise a real conflict. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
38fe058 to
9bf4370
Compare
fix(rocm/gemma4): #838 widen indexed MoE gate to T<=63 + retirement-safe dispatch
Fixes #838.
Problem
T=2..63 MoE tokens are observed on the serial M1 path, and the Gemma-4 FP8
device-indexed gate admitted only
T == 1. Everything wider fell through to thelegacy host-gather path, which copies the router weights and indices back to the
host every step. Dispatch retirement was also not scope-safe.
What changed
T == 1toT <= 63, behindVT_GEMMA4_DECODE_INDEXED_MAX_T(unset → 63,=1restores the old T=1-onlybehavior, clamped to
[1,63]). The bound is not arbitrary:Gemma4IndexedOkTalso requires
T < kGemma4PrefillBatchMinT, the same constant that admits theprefill-batch path at 64, so the two gates cannot both claim a token count.
per-expert scale to the router weights
rwin place before attempting theindexed arm, so a fall-through to the host-gather path scaled them a second
time and squared the factor. The scale now lands on a copy, and
Gemma4ApplyHostExpertScaleOncetakes analready_scaledargument so thefallback cannot repeat it.
gemma4 indexed-max-t: fallback scale is once, not s^2pins that: it asserts the result isorig * 3and notorig * 9.gemma4_indexed_gate.has injectable host seams, so the retire-before-releaseordering is testable without a GPU. Peer and compute work is retired while the
scratch buffer is still owned; a buffer whose retirement was not observed is
quarantined rather than returned to the pool.
Gemma4IndexedCall's product instantiations are named explicitly(
<uint16_t, uint16_t>) so the product lambdas compile against currentmain.Verification
Built and smoked on gfx1201, shipping ROCm 7.2.4 (clang
f58b06d), as thecombined #837+#838+#839 stack on
d1b0ea3a: gfx1201 buildBUILD_RC=0, all 30layers resident and bound, ready in ~20 s; batched-MoE prefill deadlock-free
(T=2012 done,
PEER_ACTactive, no hang, no HIP error); Paris/63 quality PASS.Stated plainly, because it bounds what this PR alone demonstrates: that smoke
covers the three-PR stack, not this branch in isolation. What is isolated
here is the host-side evidence — the 10 cases above, which run on
build-test-cpuand include real RED mutants for the double-scale, therelease-before-retire ordering, the argument packing and the T-loop striding.
No throughput measurement accompanies this change. #838 is filed as
perfand the change flips a product default for T=2..63, so
docs/BENCHMARKS.mdstill owes a before/after against
VT_GEMMA4_DECODE_INDEXED_MAX_T=1on the samehost. Correctness comes first there: the token-exact result for T=2..63 is owed
before any throughput ratio is accepted. Both need the gfx1201 pair. They are
recorded under
## Open on gfx1201 hardwarein.agents/specs/rocm-gemma4-indexed-max-t.mdrather than left implicit.Maintainer changes on top
Three repairs were applied while landing, none touching product behavior:
.agents/evidence/— a pathscripts/check-pr-size.pycannot classify, so the gate refused the changeoutright — to
.agents/specs/rocm-gemma4-indexed-max-t-donor.{md,log}, whichmatch
SPECandSPEC_EVIDENCEatcheck-pr-size.py:188-189. The bytes areunchanged; both slice sha256s still match the manifest table.
docs/FEATURES.mdis left asmainhas it. The branch had rewritten theGemma4 row, dropping the spec link, the
VT_GEMMA4_*/VT_ATTN_*env pointerand the
test_gemma4_rocm_fp8_seamsseam name. Restoring those and adding theROCm Gemma-4 hyp A: T=2..63 MoE is observed on serial M1; widen indexed gate #838 sentence does not fit —
check-public-doc-tablescaps a cell at 220characters and main's is already 219 — and
check-doc-checkpointdoes not askfor a FEATURES edit here, because
feature_surfacenow keys off a change tothe set of
REGISTER_VLLM_MODELregistrations (doc-checkpoint makes docs/FEATURES.md a LOCK: 2 of 5 concurrent LTX-2.5 PRs conflict there and nowhere else #595, fix(#595): doc-checkpoint asks whether the registry moved, not whether a file did #1086) and this branchchanges none. The ROCm Gemma-4 hyp A: T=2..63 MoE is observed on serial M1; widen indexed gate #838 detail stays where the branch already put it in full:
docs/USAGE.md,docs/ENVIRONMENT.mdand the spec.rocm_gemma4_experts.hipbetweenRetireGemma4Fp8TopKIndexedPeerand the next symbol, then assertedreturn true;was absent. That is a slice of the gap between twofunctions, not of the function, so an unrelated definition added after the
closing brace lands inside it. A
git merge-treeof this branch with open PRfix(rocm/gemma4): #839 retirement-safe prefill peer GeGLU Launch/Finish #1047 (
3df512a11) grows that gap from 16 lines to 176 and adds threereturn true;inside it, which would have turnedmainred onbuild-test-cpuonce both landed — this case is registered unconditionallyand reads the source from disk. It now brace-matches the function's own body
and gains two assertions, that the slice is bounded and that the function does
synchronize the compute stream, so the guarantee is stated more completely
than before rather than relaxed. Proved against the real test binary, built
standalone and pointed at a scratch source root: the repaired case reds on a
mutant that discards the sync status and returns unconditional success (3
assertions fail), and stays green on the actual merged tree, where the
original case reds. The scratch copy was restored and its sha256 compared
against the tree.
The branch was rebuilt by rebase rather than merge, so it carries no untrailered
merge commit; all six original commits keep their authorship. The
docs/USAGE.mdconflict against #837's landed text was resolved as a union — both the GetBlas
dual-slot paragraph and this row's env description survive.
Known-unrelated CI
windows-msvc-cpuandwindows-msvc-vulkanare red on every open PR from abreak predating this branch (#503, #584).
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: ClaudeCode:claude-opus-5 [ClaudeCode]