Skip to content

perf(ds4): default mixed ROCmFP MMQ prefill on gfx1151 - #683

Merged
davide221 merged 16 commits into
mainfrom
codex/ds4-prefill-gfx1151
Sep 9, 2026
Merged

davide221 merged 16 commits into
mainfrom
codex/ds4-prefill-gfx1151

Conversation

@davide221

@davide221 davide221 commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Builds on the now-merged #667 and targets main. This makes its registry-aware mixed ROCmFP MMQ prefill path the default on gfx1151 when DS4 uses dense or sparse approximate prefill.

The old path dequantized mixed expert weights and then called BLAS. The direct MMQ path removes that round trip and reduces the 8K trace from 325,841 to 73,165 GPU dispatches.

Exact prefill and non-gfx1151 devices keep their existing behavior. An explicit DFLASH_DS4_MIX_MMQ_PREFILL=0 remains the kill switch.

Historical Strix Halo results

DeepSeek-V4-Flash-0731 ROCmFPX MIX, six routed experts, chunk 3072, sparse prefill, DSpark enabled, cold cache:

Prompt Before After Gain
8,192 147.9 tok/s (55.4s) 209.0 tok/s (39.2s) +41.3%
32,768 139.5 tok/s (234.9s) 185.8 tok/s (176.4s) +33.2%
122,879 105.7 tok/s (1162.7s) 129.35 tok/s (950.0s) +22.4%

The historical 8K result was a matched same-code kill-switch A/B. The longer comparisons used the same model, service flags, tokenizer-built prompt, and HTTP workload from the pre-change #667 captures. All measured contexts in that sweep produced the same response SHA-256: 16fbd7d1f18d2fedb247d73edc3bc6aa040f5ab99bd3b48c35b79e543d22179b. These are not fresh results for the current head.

The gain narrows with context length because sparse attention becomes the remaining dominant cost. This does not claim Vulkan parity yet.

Reuse and safety

  • The optimized loaders remain generic mixed-ROCmFP qtype MMQ code; this PR only adds a qualified DS4/gfx1151 default policy.
  • Future model backends can select the same path after model/device qualification.
  • Exact mode is not enabled automatically because MMQ changes reduction and codebook-quantization topology.
  • Explicit environment policy is preserved, including the value 0 kill switch.

Historical verification

  • HIP dflash_server and test_deepseek4_unit build
  • test_deepseek4_unit on gfx1151
  • test_inference_profile
  • test_observability
  • test_qwen35_roctx
  • test_seq_engine_contract
  • test_deepseek4_roctx
  • test_server_unit: 431 passed, 0 failed
  • Clean full API context sweep at 8K, 32K, and 122,879 tokens

September 8 fix verification

The fixes through ed09c8682 make automatic mixed-MMQ selection model/graph-local, remove the Windows HIP environment mutation, reconcile this PR with current main, and propagate the policy through cached/hash-routed and single-token fallback graphs. The streaming-attention tests now verify actual kernel launches. The optimized kernels and explicit disable switch are retained.

Fresh lucebox8 gfx1151 validation: 494/494 CTest entries passed (489 server-unit entries plus affected DS4/MMQ/grouped-MMID/fused-combine and negative-option tests). HIP server and test builds passed.

Matched 8K prose-task regression check, old PR head 710315f44 versus final head ed09c8682: two cold requests per build/mode, identical input token IDs, six routed experts, 256 output tokens, sparse approximate prefill, chunk 3072, caches disabled. Throughput is total tokens divided by total API-reported stage time.

Mode / stage Before (tok/s) Fixed head (tok/s) Change
AR prefill 208.99 219.38 +5.0%
AR decode 20.10 20.83 +3.6%
Adaptive DSpark prefill 208.27 218.98 +5.1%
Adaptive DSpark decode 17.57 19.05 +8.4%

Adaptive runs use confidence-driven width (cap 4), fused verification and F16 KV in both builds. These results show no slowdown in this small regression sample; they do not isolate the policy fix from other changes brought in from main. Outputs are not byte-identical between builds, and adaptive decode remains slower than AR on this task. No fresh 128K or Vulkan comparison was performed.

Still draft pending fresh CI/Cubic review, broader output-quality and long-duration stability qualification.

Review in cubic

@davide221

Copy link
Copy Markdown
Contributor Author

Experimental long-context follow-up (still draft/opt-in): added a reusable D512 K==V streaming top-k HIP attention path behind DFLASH_DS4_DIRECT_INDEXER_TOPK=1 and GGML_CUDA_MLA_STREAM_TOPK=1. On gfx1151, three matched isolated graph runs improved 2627.3→2236.8 us (1.17x), 2645.5→2293.5 us (1.15x), and 2649.7→2363.3 us (1.12x). Matched ROCprof kernel time improved 2619.5→2126.6 us (-18.8%). test_deepseek4_unit and all 16 DS4 benchmark-tool tests pass. No full-model tok/s or output-parity claim yet; Lucebox8 is currently unreachable and the fallback host is booted with only ~61 GiB system RAM.

@davide221

Copy link
Copy Markdown
Contributor Author

Pushed 8e49d7b as another opt-in burn-in candidate; the PR remains draft.

Measured on gfx1151:

  • Grouped MoE combine, DS4 shape 4096 x 6 x 3072: old 4-op chain 12.16 ms, fused scalar 1.66 ms, aligned vec4 1.43 ms. CPU-reference NMSE 3.94e-15.
  • Sparse grouped MMQ, K=4096, rows=2048, 256 experts, top-k 6, width 48, 20 iterations:
    • ROCmFP2: 6.078 -> 4.904 ms (-19.3%)
    • ROCmFP3: 6.325 -> 6.291 ms (neutral)
    • grouped ROCmFP4: 9.097 -> 4.058 ms (-55.4%)

The MMQ selector is format-aware and only activates for sparse grouped MoE on gfx1151 via GGML_CUDA_MMQ_MOE_ADAPTIVE_X=1; ordinary matmuls, other formats, and other devices are unchanged. Combine remains behind DFLASH_MOE_FUSED_COMBINE=1 and DFLASH_MOE_COMBINE_VEC4=1.

Validation: 76 grouped-MMID parity cases pass, masked routes remain +0, the ROCmFPX numerical suite passes, and dflash_server builds. Full DS4 throughput and response-hash A/B is still required before enabling either path by default; LB8 is currently unreachable and the fallback host cannot load the full model with its present memory split.

@davide221

Copy link
Copy Markdown
Contributor Author

Pushed b0d5b1b: vectorized FP32 staging for the reusable D512 streaming indexed-attention candidate.

Qualification on gfx1151:

  • Five alternating clean runs: F16 staging 2.603 ms mean, vectorized FP32 staging 2.363 ms mean (-9.3%).
  • Same-run ROCprof: 2.382 ms -> 2.117 ms across 93 calls each (-11.1%).
  • FP32-staged output is byte-identical to the F16-staged streaming output; the full DeepSeek4 unit suite passes and dflash_server builds.
  • Geometry sweep rejected 8-head, 32-head, and 8-key stages; 16 heads x 16 keys remains fastest.

Enable with GGML_CUDA_MLA_STREAM_F32_STAGE=1 alongside the existing direct-indexer and streaming-attention flags. It remains opt-in because LB8 is still unreachable and the full 8K/32K/128K model-backed throughput/output A/B is pending.

@davide221

Copy link
Copy Markdown
Contributor Author

Pushed 1b6cd67: coalesced ROCmFP3 MMQ weight loads.

For each eight FP3 values, one wave lane now reads the exact three packed bytes once and expands both adjacent int8 groups. On HIP, the three bytes come from one safe four-byte memcpy load within the 14-byte quant block.

Matched DS4 sparse grouped shape (K=4096, rows=2048, 256 experts, top-k 6, width 48): q3 mean 6.268 ms -> 6.114 ms (-2.46%); final 20-iteration run 6.111 ms. Q2/Q4 controls were unchanged. Grouped-output parity passed all 76 cases, the complete ROCmFP numerical suite passed, and dflash_server builds.

I also tested folding scale staging into the weight pass; it regressed Q2/Q3 by more than 2x and was discarded.

@davide221

Copy link
Copy Markdown
Contributor Author

Pushed f140639: paired ROCmFP2 MMQ loads.

Adjacent FP2 four-value groups now share one aligned 16-bit HIP load per lane. On the matched sparse grouped shape, two 20-iteration runs averaged 4.894 ms before and 4.835 ms after (-1.20%). Q3/Q4 controls were unchanged. All 76 grouped cases passed, the complete ROCmFP numerical suite passed, and dflash_server builds.

@davide221

Copy link
Copy Markdown
Contributor Author

Pushed f1039da: compact device-side sparse-MoE work queue for prefill-sized gfx1151 grouped ROCmFP MMQ (opt-in with GGML_CUDA_MMQ_MOE_PERSISTENT=1). It removes empty expert tiles without a host readback or synchronization and is model-neutral within the grouped ROCmFP path. The ordinary grid remains selected below 256 tokens.

Three alternating matched runs at the DS4 prefill shape (K=4096, rows=2048, 256 experts, top-k 6, width 3072) averaged:

  • ROCmFP2: 34.834 -> 30.944 ms (-11.2%)
  • ROCmFP3: 36.926 -> 32.147 ms (-12.9%)
  • ROCmFP4: 25.154 -> 22.852 ms (-9.2%)

All baseline/candidate outputs across three runs had the same SHA-256. Additional outputs were byte-identical at widths 128/256/512/1024; all 76 grouped-MMID cases and the complete ROCmFP numerical suite pass, and dflash_server builds. Full-model 8K/32K/128K throughput qualification remains pending because LB8 is still not passing Tailscale data traffic; the PR remains draft.

@davide221

Copy link
Copy Markdown
Contributor Author

Pushed 2d09e65: optional HIP hardware exponential for the reusable FP32-staged D512 streaming-MLA softmax (GGML_CUDA_MLA_STREAM_FAST_EXP=1). Five alternating runs averaged 2.359 ms for the existing FP32-staged kernel and 2.154 ms with the intrinsic (-8.7%). The stronger numerical fixture uses realistic ~unit-scale Q/K values; versus the precise FP32-staged output, NMSE was 1.97e-14 and max absolute error 4.1e-8. The complete DeepSeek4 unit suite passes and dflash_server builds. It remains opt-in and the PR remains draft pending the LB8 full-model A/B.

@davide221

Copy link
Copy Markdown
Contributor Author

First review fix: 710315f44 restores the complete automatic MMQ tile search.

The previous loop stopped after the first eligible tile because selecting it changed the loop's continuation condition. Default dispatch and rejected overrides now examine wider candidates; valid explicit/adaptive recommendations still return immediately. Hardware/shared-memory eligibility, automatic-only exclusions, and smallest-width tie breaking are preserved.

Added six regression cases using the same host selector as production dispatch, registered them in test_server_unit, and included them in the ROCm CI filter.

Validation on lucebox8, Radeon 8060S / gfx1151, ROCm 7.2.4, native ROCmFP wire-format build:

  • Clean HIP build of test_server_unit, test_rocmfpx_mmq, and test_deepseek4_mmid_grouped_cuda: passed.
  • Full server unit suite: 437 passed, 0 failed, 0 skipped.
  • ROCmFP2/3/4 numerical and actual MMVQ/MMQ dispatch checks: all 32 shape/type cases passed with default selection, then separately with GGML_CUDA_MMQ_X=16, 32, and rejected width 24.
  • Grouped verification: 76 comparisons passed (18 exact, 58 within the existing numerical tolerances); masked fused-zero check passed. This is not a claim of universal byte identity.
  • Host regression proof: 5 of 6 tests failed with the old termination condition; all 6 passed after the fix, including AddressSanitizer/UndefinedBehaviorSanitizer.
  • Final diff whitespace and workflow YAML parsing checks passed.

This is a focused first fix, not merge approval. The Windows HIP environment helper, process-global approximate-mode policy leak, and reconciliation with current main remain outstanding. No end-to-end throughput or new Vulkan comparison was measured in this patch.

Reproducible test build and logs remain in /data/pr683-mmq-fix-20260908.75dE55 on lucebox8. GPU runs used ROCR_VISIBLE_DEVICES=1 with HIP_VISIBLE_DEVICES unset, selecting the Strix GPU rather than the R9700.

@davide221
davide221 changed the base branch from codex/ds4-rocm-moe-wave32 to main September 8, 2026 17:51
@davide221

Copy link
Copy Markdown
Contributor Author

Pushed 64ed6f97a (code) and 6f454dac2 (documentation), and retargeted this draft to main after merging fe0744ec2.

This addresses the three outstanding blockers from the previous review:

  • Mixed-MMQ automatic selection is now owned by the model and copied into its matmul operation metadata. It no longer writes DFLASH_DS4_MIX_MMQ_PREFILL into the process environment or caches that automatic choice in function-static dispatch state. Exact/unqualified models preserve the existing backend defaults, including perf(ds4): accelerate ROCm decode and long-context selection #667's specialized paired FP2 path; explicit model-load overrides remain supported.
  • HIP dispatch, graph-capture admission, scheduler admission, fused gate/up selection, hybrid graph caches and the sorted-expert fallback use the same policy. Other models can reuse the operation-level interface after qualification.
  • The Windows HIP ::setenv call introduced by this PR is gone. Windows execution has not been tested locally.
  • Conflicts with current main are resolved. This retains the merged perf(ds4): fuse expert-major MoE route combine #658 fused-combine contract and perf(ds4): accelerate long context and add PFlash #664 sparse-verification correctness/defaults; it does not resurrect the old sparse-verifier automatic enablement.

Validation on lucebox8, Radeon 8060S / gfx1151, ROCm 7.2.4:

  • Release HIP server and affected test targets build successfully.
  • All 488 server unit tests passed; the full DS4 unit and grouped-MMID GPU suites passed.
  • Separate final runs of the ROCmFP MMVQ/MMQ numerical/dispatch suite and DS4 fused-combine test passed.
  • New regressions cover independent per-operation policy, actual FP2/FP3 MMQ dispatch with interleaved backends, explicit override changes, graph replay and policy changes, storage-cache identity, and failed approximate/exact model initialization without environment leakage.
  • The GPU regression caught a missing metadata copy in the sorted fallback during development; that is fixed and the regression now passes.
  • Workflow YAML parsing and diff whitespace checks passed.

The optimization kernels are retained. Fresh matched client throughput checks are in progress; this comment is not a throughput claim or merge approval. A numeric-tokenization fix on main changed the old counting benchmark's input tokens, so the new comparison uses a number-free prose task and asserts identical raw input token IDs between the old/new tokenizers. Six experts, sparse prefill, cold caches; AR and adaptive DSpark are checked separately.

Reproduction source/build/logs: /data/pr683-ready-20260908.J8fiUT on lucebox8. Baseline is the previous PR head 710315f44 in /data/pr683-mmq-fix-20260908.75dE55.

@cubic-dev-ai please review the model-local policy, fallback/capture consistency and main reconciliation at 6f454dac2. Keep this PR draft while review and performance qualification finish.

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Pushed 64ed6f97a (code) and 6f454dac2 (documentation), and retargeted this draft to main after merging fe0744ec2.

This addresses the three outstanding blockers from the previous review:

  • Mixed-MMQ automatic selection is now owned by the model and copied into its matmul operation metadata. It no longer writes DFLASH_DS4_MIX_MMQ_PREFILL into the process environment or caches that automatic choice in function-static dispatch state. Exact/unqualified models preserve the existing backend defaults, including perf(ds4): accelerate ROCm decode and long-context selection #667's specialized paired FP2 path; explicit model-load overrides remain supported.
    ...

@davide221 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

3 issues found across 27 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="server/docs/DS4.md">

<violation number="1" location="server/docs/DS4.md:609">
P3: The new DS4.md section documents DFLASH_DS4_DIRECT_INDEXER_TOPK and GGML_CUDA_MLA_STREAM_TOPK/GGML_DS4_FA_STREAM_TOPK, but these are absent from the full control inventory in server/docs/ENVIRONMENT.md while the sibling streaming variables (GGML_CUDA_MLA_STREAM_F32_STAGE/FAST_EXP) are listed there. Add each newly surfaced control to the ENVIRONMENT.md inventory with its defining file so the registry stays the single source of truth.</violation>
</file>

<file name="server/src/deepseek4/deepseek4_backend.cpp">

<violation number="1" location="server/src/deepseek4/deepseek4_backend.cpp:924">
P1: On gfx1151 approximate prefill, this model-wide policy automatically admits qtype-106 MMQ for down projections, although the qualified default is only the matched routed gate/up fusion. Restrict automatic qtype-106 admission to the gate/up path with its ids and gfx1151 checks, keep down projections on their generic/default predicate, and preserve the explicit override including `=0`.

(Based on your team's feedback about qtype-106 MMQ admission.)</violation>
</file>

<file name="server/deps/llama.cpp/ggml/src/ggml-cuda/fattn.cu">

<violation number="1" location="server/deps/llama.cpp/ggml/src/ggml-cuda/fattn.cu:2665">
P3: This change adds new backend control surfaces GGML_CUDA_MLA_STREAM_TOPK, GGML_DS4_FA_STREAM_TOPK, GGML_CUDA_MLA_STREAM_F32_STAGE, GGML_CUDA_MLA_STREAM_FAST_EXP (and DFLASH_MOE_COMBINE_VEC4 in moe-fused.cu). Per the repo convention, new GGML/DFLASH env names should be added to the generated environment inventory in server/docs/ENVIRONMENT.md with their defining file and regeneration guidance. Confirm the docs portion of this PR inventories all of them; if not, add them.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

}
w_.routed_expert_top_k = cfg_.expert_top_k;
if (!moe_hybrid_) {
w_.mixed_mmq_policy = gfx1151_mix_mmq_prefill_policy(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1: On gfx1151 approximate prefill, this model-wide policy automatically admits qtype-106 MMQ for down projections, although the qualified default is only the matched routed gate/up fusion. Restrict automatic qtype-106 admission to the gate/up path with its ids and gfx1151 checks, keep down projections on their generic/default predicate, and preserve the explicit override including =0.

(Based on your team's feedback about qtype-106 MMQ admission.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At server/src/deepseek4/deepseek4_backend.cpp, line 924:

<comment>On gfx1151 approximate prefill, this model-wide policy automatically admits qtype-106 MMQ for down projections, although the qualified default is only the matched routed gate/up fusion. Restrict automatic qtype-106 admission to the gate/up path with its ids and gfx1151 checks, keep down projections on their generic/default predicate, and preserve the explicit override including `=0`.

(Based on your team's feedback about qtype-106 MMQ admission.) </comment>

<file context>
@@ -883,6 +920,14 @@ bool DeepSeek4Backend::load_model() {
     }
     w_.routed_expert_top_k = cfg_.expert_top_k;
+    if (!moe_hybrid_) {
+        w_.mixed_mmq_policy = gfx1151_mix_mmq_prefill_policy(
+            cfg_.device.gpu, cfg_.prefill_mode);
+    }
</file context>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This appears to conflate the existing default in #667 with this PR’s explicitly approximate prefill mode. #683 already enabled registry-aware MMQ for both mixed qtypes and all routed projections through its gfx1151 dense/sparse automatic environment setting (cd8abb8); this fix replaces that process-global state with the same model-local decision. Monolithic Exact and other devices still resolve to DEFAULT, preserving #667’s restricted paired path; explicit =0 resolves to DISABLED. Restricting the approximate path to gate/up here would undo part of #683 rather than preserve its behavior. The new FP2/FP3 dispatch and fallback tests pass, and the matched six-expert 8K model checks preserve throughput. Broader quality qualification remains a draft gate. Please distinguish any reproducible admission outside that approximate mode from the intended #683 policy.

Comment thread server/test/test_deepseek4_mmid_grouped_cuda.cpp
Comment thread server/src/deepseek4/deepseek4_graph.cpp
Comment thread server/docs/ENVIRONMENT.md Outdated
Comment thread server/docs/ENVIRONMENT.md
Comment thread server/tests/test_deepseek4_unit.cpp
Comment thread server/deps/llama.cpp/ggml/src/ggml-cuda/fattn.cu
Comment thread server/docs/DS4.md
Comment thread server/deps/llama.cpp/ggml/src/ggml-cuda/fattn.cu
Comment thread server/test/test_deepseek4_mmid_grouped_cuda.cpp Outdated
@davide221

Copy link
Copy Markdown
Contributor Author

Pushed ed09c8682 to address the actionable follow-up findings:

  • Tag the cached hash-routed gate/up/down operations, completing the model-local policy propagation missed in the first fix.
  • Carry the same policy through single-token hybrid fallback and cached hot/cold graphs before allocation/admission. A new test inspects all three routed operations in both cached graph variants for DEFAULT, ENABLED and DISABLED.
  • The streaming-attention regression now checks a calling-thread launch counter for the reference and each of the three streaming variants. Unsupported wave64 devices explicitly skip; silent grouped fallback can no longer pass this qualification.
  • Factor the identical streaming launch arguments into one compile-time-specialized helper, retaining the same kernel implementations and template values.
  • Reject the child-only DFLASH_MMID_TEST_WIDTH option in the full-matrix parent, with a negative CTest case. Add --mmid-only for independent grouped-MMID diagnostics; the normal CI invocation still runs both checks.
  • Remove the nonexistent DFLASH_GFX1151_HC_MMVF_Q4 documentation, document the actual DFLASH_CUDA_MMVF_NARROW_F16 switch, and inventory the newly surfaced controls.

Fresh lucebox8 gfx1151 qualification: 494/494 CTest entries passed, comprising all 489 server-unit entries and the affected DS4/grouped-MMID/MMQ/fused-combine checks plus the parent-width rejection test. Release HIP server and test builds pass. The new streaming launch assertions passed, not merely the numerical fallback checks.

The proposed P1 restriction is answered in-thread: #667's restricted default and #683's explicitly approximate-prefill policy are different scopes. This patch retains #683's prior approximate-mode admission and gains; it does not enable that general mixed-MMQ path for monolithic Exact mode. Please re-evaluate against that original scope rather than narrowing the approximate path by assumption.

The six-expert, exact-input-token 8K checks on the preceding reconciliation head preserved both AR and fused/adaptive throughput. The final cached-policy follow-up is being rerun before recording the final numbers. The unoptimized/unfused old-head diagnostic also exposed an existing second-request crash; those results are kept separate and are not a matched optimized comparison.

@cubic-dev-ai please re-review ed09c8682. This remains a draft, not a merge approval; full long-context, broader quality and stability qualification are not implied by the 8K check.

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Pushed ed09c8682 to address the actionable follow-up findings:

  • Tag the cached hash-routed gate/up/down operations, completing the model-local policy propagation missed in the first fix.
  • Carry the same policy through single-token hybrid fallback and cached hot/cold graphs before allocation/admission. A new test inspects all three routed operations in both cached graph variants for DEFAULT, ENABLED and DISABLED.
  • The streaming-attention regression now checks a calling-thread launch counter for the reference and each of the three streaming variants. Unsupported wave64 devices explicitly skip; silent grouped fallback can no longer pass this qualification.
    ...

@davide221 I have started the AI code review. It will take a few minutes to complete.

@davide221

Copy link
Copy Markdown
Contributor Author

Final before/after check is complete on lucebox8, Strix Halo gfx1151, using pushed head ed09c868234b8b4bc459682730fb4708da82d5c9.

Baseline: previous PR head 710315f44555eb783edb157d1c6e590dca6070d0. Candidate includes reconciliation with main fe0744ec2 and the policy/test fixes; this is a regression comparison, not attribution of all improvement to one fix.

8,192-token workload Before (tok/s) Fixed head (tok/s) Change
AR prefill 208.99 219.38 +5.0%
AR decode 20.10 20.83 +3.6%
Adaptive DSpark prefill 208.27 218.98 +5.1%
Adaptive DSpark decode 17.57 19.05 +8.4%

Conditions:

  • Two cold requests per build/mode, one at a time; 8,192 actual input tokens and 256 output tokens each. Metrics are total tokens / total API-reported stage time, not client burst timing or averages of rounded rates.
  • Same number-free prose performance-review task and reference padding. Verified complete raw input-token ID equality between old and new tokenizer binaries; both API requests report 8,192 prompt tokens. This avoids the digit-tokenizer change on main confounding the comparison.
  • Existing DeepSeek-V4-Flash-0731-ROCMFPX-MIX-STRIX.gguf, all six routed experts; target hip:0 after selecting physical Strix with ROCR_VISIBLE_DEVICES=1. No model transfer.
  • --max-ctx 131072 --chunk 3072 --ds4-prefill sparse --ds4-fused-decode --prefix-cache-slots 0 --prefill-cache-slots 0. Every request reports cache_hit=false.
  • DFLASH_DS4_MIX_MMQ_PREFILL unset in both builds, exercising their automatic policy. DFLASH_DS4_SPARSE_DECODE_FLASH=0 in both to match main's safe attention default. No extra experimental streaming/persistent overrides.
  • Adaptive uses DSpark Q4RMFP4/denseF16, confidence-driven adaptive width with cap 4, DFLASH_DS4_FUSED_VERIFY=1 and --ds4-fused-verify-f16-kv in both builds. It is not fixed-width or a counting/high-acceptance benchmark. Final acceptance: 64.3% on both repeats.

Final correctness/build checks: 494/494 CTest entries passed on gfx1151, including actual streaming-launch assertions, interleaved model-policy isolation, cached hot/cold graph policy, mixed FP2/FP3 numerical/dispatch tests, grouped MMID and fused combine. Independent --mmid-only also passed its 76 comparisons and telemetry checks. The temporary benchmark servers have exited; no service was changed.

Limitations: this small 8K sample shows no throughput regression, but 128K and Vulkan were not remeasured. Approximate-mode outputs differ between builds, so this is not a byte-identity or broad quality claim. Adaptive remains slower than AR on this prose task. The separate old-head unfused-verification diagnostic crash reported earlier is excluded from this matched fused comparison, not silently treated as a passing test.

Artifacts remain on LB8 at /data/pr683-ready-20260908.J8fiUT/: baseline-prose8k-ar.json, baseline-fused8k-adaptive.json, final-prose8k-ar.json, final-fused8k-adaptive.json, check_throughput.py, cubic-tests.log, and mmid-only.log; local copies are under /private/tmp/pr683-ready-20260908.WAEyfs/.

The historical longer-context gains remain separately labeled in the PR description. Still draft: fresh CI/Cubic, broader quality, long-context and stability qualification remain open. The qtype-106 P1 scope question is answered with evidence in its thread, not counted as an approval.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

3 issues found across 29 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="server/docs/ENVIRONMENT.md">

<violation number="1" location="server/docs/ENVIRONMENT.md:222">
P3: `DFLASH_MOE_COMBINE_VEC4` appears twice in the generated full inventory: once here (line 222, with a plain-text description instead of the defining file) and again immediately after `DFLASH_MOE_FUSED_COMBINE` (line 240, `- ggml-cuda/moe-fused.cu`). The grep-based `getenv` inventory format is `- VAR - file`, and `DFLASH_MOE_COMBINE_VEC4` is only defined in `ggml-cuda/moe-fused.cu`. Remove this line and keep the single correct `- ggml-cuda/moe-fused.cu` entry.</violation>
</file>

<file name="server/src/common/moe_hybrid_ffn_eval.cpp">

<violation number="1" location="server/src/common/moe_hybrid_ffn_eval.cpp:24">
P2: set_graph_mixed_mmq_policy stamps the mixed-MMQ policy on every MUL_MAT/MUL_MAT_ID/MUL_MAT_GROUPED_SRC in the whole graph, including non-routed nodes such as the shared expert's plain ggml_mul_mat. Those are not mixed-expert matmuls, so the ENABLED policy is applied outside the routed gate/up/down scope that the per-op ggml_mul_mat_set_mixed_mmq calls target elsewhere. Restrict the traversal to routed ops (or rely on the per-op calls) to avoid over-applying the policy.</violation>
</file>

<file name="server/test/test_deepseek4_mmid_grouped_cuda.cpp">

<violation number="1" location="server/test/test_deepseek4_mmid_grouped_cuda.cpp:166">
P3: When a graph compute fails mid-benchmark, the printed average divides the elapsed time by the full requested iteration count even though fewer iterations ran, understating the reported per-iteration cost. Track the count of successfully executed iterations and divide by that instead. This affects the benchmark printout in both run_case() and run_combine_graph().</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread server/src/common/moe_hybrid_ffn_eval.cpp
Comment thread server/docs/ENVIRONMENT.md Outdated
Comment thread server/test/test_deepseek4_mmid_grouped_cuda.cpp Outdated
@davide221

Copy link
Copy Markdown
Contributor Author

Pushed fc31768528dbbd213415382edc833d15453974b1, containing the review fixes in 0dd931647 and a clean merge of current main 5fb1329a6 / #704. The newly merged verifier-cache improvement is preserved; no adaptive-controller refactor is included.

Review fixes

  • Restrict the whole-graph fallback policy traversal to routed MUL_MAT_ID operations. The four affected builders express their routed projections this way; the shared expert's ordinary matmuls now retain DEFAULT. The separate per-operation policy setters for batched/grouped/per-expert paths are unchanged. The expanded hot/cold regression failed six shared-policy assertions before the fix and passes afterward while still checking all three routed projections under DEFAULT/ENABLED/DISABLED.
  • Keep one defining-file entry for DFLASH_MOE_COMBINE_VEC4 in the environment inventory. The direct-indexer and all streaming controls requested in the older P3 threads are already inventoried.
  • Count successfully completed benchmark iterations. A failed run emits an explicit aborted diagnostic, not a misleading average including a failed dispatch. Both test loops share the accounting helper; five deterministic self-test cases cover success, first/mid/last failure and zero iterations without faulting a GPU context. The combine path continues to return failure without publishing a speed result.

Verification

Final #704-integrated head on lucebox8/gfx1151, ROCm 7.2.4, HIP graphs ON: Release server/test build passes and 495/495 CTest entries pass (37.14 seconds), including all 489 server-unit entries and the affected DS4, mixed-MMQ, grouped-MMID, fused-combine and negative/self-test checks. No test tolerance was weakened. Pre-integration checks also passed. The policy-scope fail-before receipt and all build/test logs are retained under /data/pr683-ready-20260908.J8fiUT/review2-*.

No GPU kernel source changed in this follow-up. Before integrating #704, the HIP shared library was byte-identical to the measured ed09c8682 build (07d237f6f67ce8e1eef7cfdc241b203b8bc5c275d97329dee033506521551c9a). This is not a fresh throughput claim for the new integrated head.

For clarity, the September 9 matched retrieval recheck of the preceding ed09c8682 head versus the retained #667 qualification build reproduced the decode gain:

Server tok/s, two cold 7,680-token retrieval requests per arm #667 baseline ed09c86
AR prefill 123.025 154.139
AR decode 20.326 20.307
Adaptive prefill 123.768 154.129
Adaptive decode 35.342 35.396

Six experts, sparse F16 fused verification, identical full input token IDs, all eight measured responses strict 5/5 and the same expected response hash. Adaptive was enabled but stayed q4 on this high-acceptance retrieval task. This does not resolve the slower variable-acceptance prose case or qualify 128K/Vulkan parity. Complete provenance and limitations are in /data/ds4-matched-20260909.Vb45YU/RESULTS.md.

The qtype-106 scope discussion remains explicit: #683 intentionally qualifies approximate gfx1151 routed prefill, including down projections; #667's narrower Exact/default paired admission remains unchanged. This follow-up fixes the separate shared-expert metadata issue without silently undoing #683's intended approximate policy. Please review that distinction against the existing mode-qualification and FP2/FP3 dispatch/numerical tests.

@cubic-dev-ai please re-review the current head. The preceding head passed Linux, Windows, Strix, R9700, DGX and workspace CI; RTX3090 was cancelled, not passed. Fresh CI/review on this new head is still required. Still draft; no merge or auto-merge enabled.

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Pushed fc31768528dbbd213415382edc833d15453974b1, containing the review fixes in 0dd931647 and a clean merge of current main 5fb1329a6 / #704. The newly merged verifier-cache improvement is preserved; no adaptive-controller refactor is included.

Review fixes

  • Restrict the whole-graph fallback policy traversal to routed MUL_MAT_ID operations. The four affected builders express their routed projections this way; the shared expert's ordinary matmuls now retain DEFAULT. The separate per-operation policy setters for batched/grouped/per-expert paths are unchanged. The expanded hot/cold regression failed six shared-policy assertions before the fix and passes afterward while still checking all three routed projections under DEFAULT/ENABLED/DISABLED.
    ...

@davide221 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 29 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread server/test/test_deepseek4_mmid_grouped_cuda.cpp Outdated
Comment thread server/test/test_deepseek4_mmid_grouped_cuda.cpp Outdated
@davide221

Copy link
Copy Markdown
Contributor Author

Fixed both latest review findings in be02d6f45.

  • Parse DFLASH_MMID_BENCH_ITERS once. Only a positive value enables benchmark shapes, zero-filled benchmark weights and the timed loop. Unset, zero, negative and nonnumeric values retain randomized correctness inputs. A new end-to-end CTest compares actual output hashes against the unset reference, checks a nonzero reference, rejects accidental benchmark dimensions/timing, and includes a positive timing/shape control.
  • Include ROCmFP4_FAST in the default child and parent matrix, using one shared type/width list and its real quantizer. There are now 89 compared cases, including 13 FAST cases, rather than 76. FAST is not admitted by the existing grouped-type mask, so its numerical fallback is checked and unexpected grouped admission is rejected; the 105 expected grouped launches for the other types are unchanged. No kernel admission was widened.
  • Exercising the previously skipped fused FAST cases exposed a fixture lifetime problem: graph allocation could recycle model-weight storage after the unfused last use while the fused operation still reads it. Keep fixture weights live for the entire graph/repeated benchmark computations. This fixes the mismatch without dropping fused cases, disabling fusion or changing tolerances. The unpinned mismatch also reproduced with GPU graphs disabled.

Verification on lucebox8 / gfx1151 / ROCm 7.2.4:

  • Previous head's three MMID CTests passed.
  • New checks failed before fixes: explicit zero enabled the benchmark shape, and the parent expected FAST outputs that the child skipped.
  • Final Release build and 496/496 DS4/server CTest entries passed (41.24 s), including the new five-mode configuration regression and complete 89-case matrix. Existing HIP compatibility-header macro-redefinition warning remains; no build error.
  • git diff --check passed. Only the test harness, its CMake registration and new regression script changed. Inference kernel code is untouched; this is not a new throughput measurement.

Build/fail-before/final receipts are retained in /data/pr683-ready-20260908.J8fiUT/review3-* on Lucebox8.

@cubic-dev-ai please re-review the current head, especially these two findings. The earlier approximate-MMQ policy-scope discussion and fresh cross-platform CI remain separate merge gates. Still draft; no merge or auto-merge enabled.

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Fixed both latest review findings in be02d6f45.

  • Parse DFLASH_MMID_BENCH_ITERS once. Only a positive value enables benchmark shapes, zero-filled benchmark weights and the timed loop. Unset, zero, negative and nonnumeric values retain randomized correctness inputs. A new end-to-end CTest compares actual output hashes against the unset reference, checks a nonzero reference, rejects accidental benchmark dimensions/timing, and includes a positive timing/shape control.
  • Include ROCmFP4_FAST in the default child and parent matrix, using one shared type/width list and its real quantizer. There are now 89 compared cases, including 13 FAST cases, rather than 76. FAST is not admitted by the existing grouped-type mask, so its numerical fallback is checked and unexpected grouped admission is rejected; the 105 expected grouped launches for the other types are unchanged. No kernel admission was widened.
  • Exercising the previously skipped fused FAST cases exposed a fixture lifetime problem: graph allocation could recycle model-weight storage after the unfused last use while the fused operation still reads it. Keep fixture weights live for the entire graph/repeated benchmark computations. This fixes the mismatch without dropping fused cases, disabling fusion or changing tolerances. The unpinned mismatch also reproduced with GPU graphs disabled.
    ...

@davide221 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 30 files

You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.

Re-trigger cubic

Comment thread server/test/test_deepseek4_mmid_grouped_cuda.cpp
Comment thread server/test/test_deepseek4_mmid_grouped_cuda.cpp Outdated
Comment thread server/CMakeLists.txt
@davide221

Copy link
Copy Markdown
Contributor Author

Fixed the three latest test-harness findings in 28dc03c45.

  • Parent benchmark settings: positive DFLASH_MMID_BENCH_ITERS is now rejected with exit 2 before GPU initialization in both normal and --mmid-only parent runs. Benchmarks remain supported through --child; zero/negative/nonnumeric values retain correctness mode. Parent and child share the same positive-value parser. The CLI regression checks both exit status and the intended diagnostic with nondefault benchmark dimensions.
  • Inherited vector-combine disable: the test explicitly sets DFLASH_MOE_COMBINE_VEC4=1 before backend initialization on Windows and POSIX, checks setting failures, and asserts the configuration before combine validation. A new CTest starts with =0 and verifies the combine test still succeeds with vector coverage enabled. No serving-time flag behavior changed.
  • No GPU: child modes use the same supported-device admission as the parent and return 77 before backend initialization when unavailable/unsupported. Actual initialization/computation errors on an admitted device still fail. The CMake wrapper maps the initial child's 77 to an explicit CTest skip marker because CMake 3.21 script mode has no portable exit(77). Other errors, including a device disappearing later in a run, remain failures. The no-GPU regression hides devices only in subprocesses and checks all three child modes and wrapper skip propagation.

Lucebox8 / gfx1151 / ROCm 7.2.4 validation:

  • All three new regressions fail before the fixes for the reported reasons.
  • All seven grouped-MMID CTests pass after the fixes, retaining the full 89-case numerical matrix and existing tolerances.
  • Release build and 499/499 DS4/server CTest entries pass (42.45 seconds).
  • A separate device-hidden CTest run reports 4 passed, 3 skipped, 0 failed; the benchmark-config test is visibly skipped rather than counted as successful GPU coverage.
  • git diff --check passes. Only test/CTest files changed; inference kernels, expert count and production dispatch policy are untouched. No new throughput claim.

Receipts are retained on LB8 under /data/pr683-ready-20260908.J8fiUT/review4-* and locally under /private/tmp/pr683-ready-20260908.WAEyfs/.

Fresh CI and automatic Cubic review apply to this new commit. No additional manual re-review request is being sent. The older approximate-MMQ default-policy discussion remains separate and open. Still draft; no merge or auto-merge enabled.

@davide221
davide221 marked this pull request as ready for review September 9, 2026 16:58
@davide221
davide221 merged commit 2f0eff0 into main Sep 9, 2026
6 checks passed
@davide221
davide221 deleted the codex/ds4-prefill-gfx1151 branch September 18, 2026 15:50
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