Skip to content

Fix Metal small-batch matmul parity for GLM verification - #1078

Merged
i386 merged 7 commits into
mainfrom
jd/fix-glm-dsa-verify-parity
Jul 26, 2026
Merged

Fix Metal small-batch matmul parity for GLM verification#1078
i386 merged 7 commits into
mainfrom
jd/fix-glm-dsa-verify-parity

Conversation

@i386

@i386 i386 commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Fixes #1076.

Summary

This PR fixes GLM-DSA batched verify_tokens parity at the Metal matrix-multiplication boundary while preserving genuine one-call multirow execution.

  • add row-parallel, batch-invariant F32, Q5_0, Q4_K, and Q6_K mul_mv_ext kernels that use canonical one-row arithmetic and reduction order;
  • allocate the canonical Q5_0 threadgroup-memory footprint for the extended kernel;
  • assign each batch row to an independent Metal threadgroup instead of replaying rows serially;
  • cover the affected small-batch dispatch through width 16, including GLM's 192-column Q5_0 projection;
  • expose an independent --sample-width in skippy-bench verify-window-local, require that timed widths are parity-checked, and reject widths above the proven ceiling during CLI parsing;
  • compare typed generation signal windows and retain full target-stream, continuation, native-position, exported-state, token-signal, and top-2-logit diagnostics.

No environment-variable guard or serial verifier fallback is required by this fix.

Root cause

Metal changed matrix multiplication implementation as verification width grew:

  • one-row execution used canonical mul_mv;
  • small batches used mul_mv_ext with a different reduction shape;
  • wider batches could cross into mul_mm;
  • the GLM 192-column Q5_0 projection also missed the ordinary small-batch eligibility rule.

Those paths were within normal backend numerical tolerances, but were not batch-invariant. The drift changed canonical exported state and token signals, and could later change greedy continuation. Direct sparse prefill and FlashAttention were not the root cause.

The repaired kernels keep one batched graph and parallel GPU execution while making every row follow the canonical one-row computation.

Scope

The batch-invariant path is bounded to widths 16 or lower:

  • F32 and Q5_0: widths 2-16;
  • Q4_K and Q6_K: widths 4-16.

Existing dispatch remains unchanged outside those source types and widths. verify-window-local rejects larger widths until equivalent exactness is implemented and proven.

The parity harness deliberately builds an always-accepted greedy target stream so it measures kernel/state parity rather than proposal quality. Native-MTP proposal quality and acceptance remain the responsibility of the dedicated MTP benchmarks.

GenerationSignalWindow is now compared as a typed value. It remains advisory because one batched call and N serial calls necessarily have different call-history window shapes; canonical model state and TokenSignal remain exactness gates.

Physical validation

Validation used Apple M3 Ultra Metal, the public GLM-4.7 Flash MTP Q4_K_M GGUF, greedy sampling, one session, F16 K/V, and FlashAttention auto.

Exactness

Widths 1, 2, 4, 9, and 16 each passed:

  • exact target stream;
  • exact 256-token continuation;
  • exact native position;
  • byte-exact full exported state;
  • exact token signal;
  • exact top-2 tokens and margins.

This is 5/5 parity cells and 1,280 checked continuation decodes. Report SHA-256: bfd74dae283b798cacb961d38ddae8dd187feffc7c1c986620059f2209fa67c4.

The earlier regression matrix also covered 506-token and 20,006-token prompts at widths 1/2/4/9, with 8/8 parity cells and 2,048 continuation decodes.

Before/after performance

Each row below uses 64 measured iterations after 16 warmups. The baseline omits only patch 0043; Rust harness, model, prompt, cache types, FlashAttention mode, and hardware are identical.

Width Baseline batched Patched batched Change Patched vs serial
9 173.19 tok/s, 51.968 ms 256.82 tok/s, 35.044 ms +48.3% 3.63x
16 255.68 tok/s, 62.578 ms 301.42 tok/s, 53.083 ms +17.9% 4.29x

The baseline failed exported-state and token-signal parity at both widths. The patched path passed both, so correctness did not require a performance regression.

Gates

  • clean pinned llama.cpp patch-queue apply;
  • patched static Metal llama.cpp build;
  • cargo fmt --all -- --check;
  • cargo test --locked -p skippy-bench (73 passed);
  • cargo clippy --locked -p skippy-bench --all-targets -- -D warnings;
  • focused Apple Metal backend sweep for modified source types: 274/274 MUL_MAT cases passed.

Summary by CodeRabbit

  • New Features
    • Added CLI options for verification widths, sample width, continuation steps, and flash-attention mode.
    • Expanded the verification JSON report with selected flash-attention mode, sampled token stream, requested widths/steps, and detailed per-width parity check diagnostics.
    • Supports running parity verification across multiple requested widths in one command.
  • Bug Fixes
    • Improved argument validation and parity mismatch/error reporting.
    • Improved consistency of small-batch Metal matrix operations across batch sizes.
  • Tests
    • Updated and added tests covering CLI parsing, planning/sampling behavior, and parity mismatch diagnostics.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Verification parity and backend execution

Layer / File(s) Summary
Verification CLI and report contracts
crates/skippy-bench/src/cli.rs, crates/skippy-bench/src/verify_window_local.rs
Adds verification-width, continuation-step, and flash-attention options; validates them and records expanded verification metadata.
Target planning and parity execution
crates/skippy-bench/src/verify_window_local.rs
Derives width-specific token streams and compares batched and serial verification across predictions, state, tokens, and signals.
Generalized runtime reporting
crates/skippy-bench/src/verify_window_local.rs
Applies selected flash-attention settings to full and split runtimes and computes token rates from the configured verification width.
Batch-invariant Metal matmul dispatch
third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch
Updates Metal dispatch parameters and adds batch-invariant F32 and quantized kernel variants.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant FullModelSampling
  participant VerifyTargetPlan
  participant ParityChecks
  participant StageSession

  CLI->>FullModelSampling: verification widths and continuation steps
  FullModelSampling->>VerifyTargetPlan: choose target plan
  VerifyTargetPlan-->>FullModelSampling: width-specific verify tokens
  FullModelSampling->>ParityChecks: run requested parity checks
  ParityChecks->>StageSession: batched verification and serial continuation
  StageSession-->>ParityChecks: predictions, state, token, and signal results
  ParityChecks-->>FullModelSampling: detailed parity results
Loading

Suggested reviewers: ndizazzo, michaelneale

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address #1076 by adding batch-invariant Metal kernels and verification checks that compare batched vs sequential parity across the required widths and state.
Out of Scope Changes check ✅ Passed No clearly unrelated code changes stand out; the CLI and report updates support the verification and parity work described in the issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: fixing Metal small-batch matmul parity for GLM verification.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jd/fix-glm-dsa-verify-parity

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

This pull request is currently a draft. Reviews will not take place until the PR is marked as ready for review.

@i386 i386 changed the title Fix GLM-DSA verify window parity Fix Metal small-batch matmul parity for GLM verification Jul 26, 2026
@i386
i386 marked this pull request as ready for review July 26, 2026 02:04
@github-actions
github-actions Bot requested a review from ndizazzo July 26, 2026 02:04

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
crates/skippy-bench/src/verify_window_local.rs (2)

287-287: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename max_width to reflect that it receives a token count.

Callers pass target_token_count(args) (max width + continuation steps), and the loop then produces count + 1 targets. The max_width name makes the + 1 slack hard to reason about.

Also applies to: 296-297

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/skippy-bench/src/verify_window_local.rs` at line 287, Rename the
max_width parameter and all related references in the affected function to
indicate it represents a target token count, not a width. Update callers such as
target_token_count(args) and the loop’s count-plus-one logic consistently,
preserving the existing behavior.

469-504: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Continuation parity is decided by an internal bail!, making continuation_matched always true.

Both the serial and batched calls already assert each step equals the plan, so the batched_continuation == serial_continuation comparison at Line 399 can never be false. Consider returning the decoded tokens without the per-step assertion and letting the caller's comparison (plus a plan comparison) be the single gate, so the reported flag carries real information.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/skippy-bench/src/verify_window_local.rs` around lines 469 - 504, The
per-step bail in decode_expected_continuation prevents continuation parity
mismatches from reaching the caller, making continuation_matched uninformative.
Remove the predicted-versus-expected assertion from decode_expected_continuation
while preserving token decoding and collection, and let the caller compare
serial and batched continuations against each other and the target plan as the
sole validation gate.
third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch (1)

76-92: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Nested ternaries for nsg/r0ptg are dense but internally consistent; consider extracting for readability.

The logic checks out (F32's nr0=2 fixed row-count matches the 256B smem sizing in device.cpp; Q4_K/Q6_K's 2*nsg matches per-simdgroup row assignment), but the multi-way nested ternary spanning type checks is hard to scan at a glance. A small named helper (e.g. compute_batch_invariant_row_params(type, ne00)) returning {nsg, r0ptg} would make future changes to this dispatch logic safer to review.

♻️ Illustrative refactor direction
-        const int nsg = op->src[0]->type == GGML_TYPE_F32 ?
-            std::min(4, (ne00 + 127) / 128) : 2;
+        const int nsg = compute_mul_mv_ext_nsg(op->src[0]->type, ne00);
@@
-        const int16_t r0ptg = batch_invariant_ext_type ?
-            (op->src[0]->type == GGML_TYPE_F32 ? 2 :
-             op->src[0]->type == GGML_TYPE_Q5_0 ? N_R0_Q5_0*nsg : 2*nsg) :
-            nypsg*nsg;
+        const int16_t r0ptg = compute_mul_mv_ext_r0ptg(
+            op->src[0]->type, batch_invariant_ext_type, nsg, nypsg);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch`
around lines 76 - 92, Extract the batch-invariant row-parameter selection
currently embedded in the nsg and r0ptg ternaries within ggml_metal_op_mul_mat
into a small named helper, such as compute_batch_invariant_row_params, returning
both values. Preserve the existing type- and ne00-dependent behavior, and keep
the non-batch-invariant nypsg*nsg path unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/skippy-bench/src/verify_window_local.rs`:
- Around line 341-454: Split run_parity_check into semantically named helpers
that keep each function below Clippy’s line-count threshold. Introduce a shared
ParitySide collection helper for serial and batched execution, state export,
token signals, and signal-window formatting, reusing one layer_end conversion;
extract the bail! message construction into format_parity_failure. Preserve the
existing comparisons, diagnostics, and VerifyParityCheck output.
- Around line 403-410: Update the parity result logic around
signal_window_matched so it participates in the matched conjunction and
signal-window divergence cannot pass silently. Also ensure the returned report
preserves the actual aggregate match status, returning matched: false for failed
checks instead of always reporting true after an early bail; retain the existing
failure diagnostics and successful result behavior.
- Around line 1088-1091: Update the throughput reporting around the sample-width
selection and fields such as batched_width2, split_inprocess_width2, and
verified_tokens_per_sec so calculations use the actual selected verify width
from verify_widths rather than assuming 2. Ensure labels and JSON field names
accurately represent configurable widths, preserving or intentionally updating
the report contract consistently.
- Around line 456-467: Update serial_decode_expected to fail immediately when
decode_step_frame_sampled_mtp returns a negative predicted value, matching
choose_target_plan’s behavior; do not skip the sentinel or continue collecting
later predictions, and return an appropriate error using the existing
error-context conventions.

---

Nitpick comments:
In `@crates/skippy-bench/src/verify_window_local.rs`:
- Line 287: Rename the max_width parameter and all related references in the
affected function to indicate it represents a target token count, not a width.
Update callers such as target_token_count(args) and the loop’s count-plus-one
logic consistently, preserving the existing behavior.
- Around line 469-504: The per-step bail in decode_expected_continuation
prevents continuation parity mismatches from reaching the caller, making
continuation_matched uninformative. Remove the predicted-versus-expected
assertion from decode_expected_continuation while preserving token decoding and
collection, and let the caller compare serial and batched continuations against
each other and the target plan as the sole validation gate.

In
`@third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch`:
- Around line 76-92: Extract the batch-invariant row-parameter selection
currently embedded in the nsg and r0ptg ternaries within ggml_metal_op_mul_mat
into a small named helper, such as compute_batch_invariant_row_params, returning
both values. Preserve the existing type- and ne00-dependent behavior, and keep
the non-batch-invariant nypsg*nsg path unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 865562ed-baf7-4823-ac1c-0604d58f97f8

📥 Commits

Reviewing files that changed from the base of the PR and between cdd793b and 104f565.

📒 Files selected for processing (3)
  • crates/skippy-bench/src/cli.rs
  • crates/skippy-bench/src/verify_window_local.rs
  • third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch

Comment thread crates/skippy-bench/src/verify_window_local.rs
Comment thread crates/skippy-bench/src/verify_window_local.rs Outdated
Comment thread crates/skippy-bench/src/verify_window_local.rs
Comment thread crates/skippy-bench/src/verify_window_local.rs
@danielwinterw

Copy link
Copy Markdown
Collaborator

Reviewed the Metal patch against the pinned llama.cpp source rather than taking the dispatch geometry on faith.

Verified

The kernel geometry checks out against the pin:

  • kernel_mul_mv_t_t_4_impl uses r0 = tgpig.x*NR0 (simdgroups split along ne00, not rows), so F32 r0ptg = 2 is correct, and smem = 32*2*sizeof(float) matches both helper_mv_reduce_and_write<NR0=2>'s NW*NR0 floats and the canonical 32*sizeof(float)*nr0.
  • Q4_K/Q6_K use first_row = (r0*NSG + sgitg)*nr0 with N_R0_* = 22*nsg is right; Q5_0's mul_vec_q_n_f32_impl uses (tgpig.x*NSG + sgitg)*NR0 with N_R0_Q5_0 = 4N_R0_Q5_0*nsg is right.
  • ggml_metal_library_get_pipeline_mul_mv_ext already sets the same FC_MUL_MV + {0,2,3,4} function constants the canonical impls read, so NSG/ne12/r2/r3 resolve correctly in the ext pipelines.
  • ggml_metal_kargs_mul_mv_ext lacks nr0, but only the _disp wrappers read args.nr0 — calling _impl directly with explicit template constants sidesteps that.
  • res.smem is zero-initialized in ggml_metal_library_get_pipeline, so the if (pipeline.smem > 0) guard is safe for the quant pipelines, and ggml_metal_op_mul_mat is the only caller of the ext pipeline getter.
  • Patches apply via find … | sort, so 0043 slots in with no manifest change needed.

Issues

1. Hardcoded throughput denominator is now wrong (crates/skippy-bench/src/verify_window_local.rs). build_report still calls verified_tokens_per_sec(batched_avg, 2) / (serial_avg, 2), and the split path does the same, but the sampled width is now sample_width(args) = verify_widths[0]. --verify-widths 9 reports batched_token_per_sec 4.5x too low. The batched_width2 / split_inprocess_width2 fields are misnamed for the same reason. Thread the sample width through both call sites and rename.

2. sample_width = first element of --verify-widths is an invisible coupling: --verify-widths 1,2,4,9 and 9,4,2,1 run the same parity sweep but produce different benchmark numbers. Either add an explicit --sample-width or keep the benchmark pinned at 2.

3. run_parity_check bails on first mismatch, so matched is always true and first_mismatch_position always None in every emitted report — both fields are dead as written, and a width-4 failure hides whether 9/16 also fail. Collecting all checks and failing once at the end with the full table would fix that and make the aggregation unit-testable.

4. signal_window_matched is computed, reported, and included in the bail message, but excluded from matched. Intentional (window formatting expected to differ) or an oversight? Worth a comment either way.

5. Signal-window equality via format!("{:?}", …) compares Debug strings — sensitive to float formatting and any Debug impl change. If the type can't derive PartialEq, a comment on why would help.

6. Silent semantic change. choose_verify_tokens used the native MTP n=1 draft; choose_target_plan now uses the model's own greedy stream. Right input for a parity harness, but it changes what batched_width2 measures (an always-accepted stream) and drops this command's only coverage of the native MTP draft path. Worth a line in the PR body.

Risks worth settling before merge

Blast radius. This isn't verifier-scoped — it changes Metal dispatch policy for every model this fork runs. Batch sizes 9–16 on F32/Q5_0/Q4_K/Q6_K previously reached mul_mm; they now take the row-parallel mul_mv path, which re-reads the weight matrix per row instead of amortizing it across the batch. Q4_K is the most common quant in the wild. The validation table compares one-call vs serial verification — it doesn't show the cost against the pre-patch batched kernels, which is the number that says whether general prefill and multi-token decode regressed. A llama-bench pp/tg run plus a batch-9..16 decode comparison before/after on a Q4_K model would close that. There's no test-backend-ops gate in CI, so nothing else catches it.

Unenforced width ceiling. Parity holds only for ne11 <= 16 and only for these four types; at 17+ the op falls back to mul_mm and batch-invariance silently disappears. Nothing in validate_args or the production verify path enforces that — if a proposer ever emits >16 tokens the guarantee vanishes with no error. Add a guard, or at minimum a documented constant shared with the verifier.

Silent drift against upstream. The patch re-derives nsg = std::min(4, (ne00 + 127) / 128) and smem = 32*2*sizeof(float) from ggml-metal-device.cpp, and hardcodes 2*nsg for Q4_K/Q6_K where N_R0_Q5_0*nsg is used for Q5_0. If upstream bumps N_R0_Q4_K, N_SG_Q6_K, or the F32 nsg heuristic, this still compiles and still runs — it just stops being batch-invariant, i.e. exactly the failure mode this PR exists to fix. llama-upstream-canary catches apply failures, not this. Suggest N_R0_Q4_K*nsg / N_R0_Q6_K*nsg plus a comment on each duplicated constant naming its source of truth.

Minor

  • The four r1ptg template instantiations per type are byte-identical ((void) r1ptg;), multiplying pipeline compilations by 4 for no benefit. Pinning r1ptg = 2 for batch_invariant_ext_type before the pipeline lookup would cut that.
  • serial_decode_expected silently drops negative predictions, surfacing later as a confusing "prediction has N token(s)" error instead of "decode returned no token".
  • Error text "width {width} requires {width}" reads oddly (three sites); verify_tokens_for_width requires targets.len() >= width when it only consumes width - 1.
  • width.saturating_add(1) as u32 vs i32::try_from(layer_end) elsewhere — inconsistent conversion style.
  • choose_target_plan generates one more token than any consumer needs (max_width + continuation_steps + 1); harmless, but the +1 is unexplained.
  • validate_args doesn't reject duplicate widths or widths above the invariance ceiling.

Description mismatch

The body claims the PR "remove[s] the temporary serial verifier fallback and Metal kernel-disable guards", but the diff against main touches only 3 files and removes no such code — and I found no fallback or kernel-disable guard on main. Presumably branch-internal history; worth correcting so it doesn't mislead reviewers or release notes.

Tests

CLI parsing coverage is good, and first_mismatch_position / verify_tokens_for_width are covered including the length-difference case. The parity flow itself isn't testable without a model, which is fair — but fixing (3) would make the aggregation logic unit-testable, which is where a regression is most likely to hide.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch (1)

221-315: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

r1ptg template parameter is vestigial in all four batch-invariant kernels.

Each new kernel ((void) r1ptg; at lines 233, 250, 266, 283) ignores the template parameter and delegates to the same canonical _impl call regardless of its value, so kernel_mul_mv_ext_*_r1_2 through _r1_5 compile to four identical bodies per type. This is harmless (host names are 1:1 replacements of what was removed, and the canonical _impl already indexes rows via tgpig.y), but it's now purely a naming/lookup artifact rather than a real specialization axis — worth a comment or eventual consolidation to avoid confusing future maintainers into thinking r1ptg still affects behavior here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch`
around lines 221 - 315, The r1ptg template parameter is unused in all
batch-invariant kernels and only exists to generate host-name variants. Add a
concise comment near the four kernel templates or their instantiations
documenting that r1ptg is intentionally retained solely for naming/lookup
compatibility and does not affect implementation behavior; do not alter the
canonical _impl calls or generated host names.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch`:
- Around line 221-315: The r1ptg template parameter is unused in all
batch-invariant kernels and only exists to generate host-name variants. Add a
concise comment near the four kernel templates or their instantiations
documenting that r1ptg is intentionally retained solely for naming/lookup
compatibility and does not affect implementation behavior; do not alter the
canonical _impl calls or generated host names.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f65b281c-42e8-4c48-9a9d-d652e7808d21

📥 Commits

Reviewing files that changed from the base of the PR and between 104f565 and 58b281c.

📒 Files selected for processing (2)
  • crates/skippy-bench/src/verify_window_local.rs
  • third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/skippy-bench/src/verify_window_local.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/skippy-bench/src/cli.rs`:
- Around line 247-252: Enforce the documented maximum value of 16 at the CLI
boundary for both VerifyWindowLocalArgs::verify_widths elements and
sample_width. Add clap validation or equivalent argument constraints so invalid
values are rejected before program entry, while preserving the existing defaults
and valid-value behavior.

In
`@third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch`:
- Around line 17-26: Update ggml_metal_library_get_pipeline_mul_mv_ext to add a
Q5_0-specific smem override for the batch-invariant pipeline, matching the
existing Q5_0 kernel path with 32*N_R0_Q5_0*sizeof(float). Ensure the override
applies when the source types select Q5_0 and preserves the existing F32
override.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ce7e6c5a-bc01-495b-9d97-a6f09f4efd22

📥 Commits

Reviewing files that changed from the base of the PR and between 58b281c and a54a61a.

📒 Files selected for processing (3)
  • crates/skippy-bench/src/cli.rs
  • crates/skippy-bench/src/verify_window_local.rs
  • third_party/llama.cpp/patches/0043-ggml-metal-make-small-batch-matmul-batch-invariant.patch
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/skippy-bench/src/verify_window_local.rs

Comment thread crates/skippy-bench/src/cli.rs
@i386

i386 commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for the detailed review. I've addressed the findings in ccf1eb145.

  • Added explicit --sample-width, corrected throughput calculations and report naming, and enforced the shared width-16 ceiling at both CLI parsing and runtime validation.
  • Changed parity execution to collect every requested width before failing, preserved real mismatch diagnostics, and replaced Debug-string signal comparison with the typed signal-window contract. Signal-window shape remains advisory because one batched call and N serial calls have different call histories; exported state and TokenSignal remain exactness gates.
  • Documented that the harness now uses an always-accepted greedy target stream and that native-MTP proposal quality belongs to the dedicated MTP benchmark.
  • Grounded dispatch geometry in the upstream constants, collapsed the redundant r1ptg specializations, and restored Q5_0's required threadgroup-memory allocation.
  • Added matched pre-patch versus patched batched measurements: width 9 improved from 173.19 to 256.82 tok/s (+48.3%), and width 16 improved from 255.68 to 301.42 tok/s (+17.9%).
  • Physical Metal validation passed widths 1/2/4/9/16 with exact target stream, 256-token continuation, native position, full exported state, and token signals. The focused backend sweep passed 274/274 MUL_MAT cases.

The earlier Linux CUDA failure was runner infrastructure (/__e/node24/bin/node missing before checkout). That run was superseded after merging current main; the new CI runs are now in progress.

@i386
i386 merged commit dcfab5b into main Jul 26, 2026
30 checks passed
@i386
i386 deleted the jd/fix-glm-dsa-verify-parity branch July 26, 2026 23:50
michaelneale added a commit that referenced this pull request Jul 27, 2026
* origin/main:
  Fix Metal small-batch matmul parity for GLM verification (#1078)
  Handle K-only transposed KV page import and export (#1084)
  Refresh llama.cpp upstream patch queue (#1085)
  chore: improve embedded native-runtime compatibility guidance (#1043)
  fix(console-ui): chat transcript snapping during live status updates (#1083)
  ci: bump Linux CUDA slim container to gha-convention base runner image
  fix: record activation cache prefix identities (#1041)
  fix: read-only model download caches (#1042)
  ci: disable sccache for Windows ROCm native runtime build (#1087)
  ci: fix v0.74 release GPU builds (sccache disk-only + force_hosted_runners) (#1086)
  Make release sccache failures non-fatal (#1079)
  Keep client-only nodes out of model election (#1074)

# Conflicts:
#	crates/mesh-llm-host-runtime/src/runtime/auto_join.rs
#	crates/mesh-llm-host-runtime/src/runtime/tests/auto_join.rs
#	third_party/llama.cpp/patches/0004-Add-lanes-external-media-and-chat-grammar-support.patch
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.

GLM-DSA batched verify_tokens diverges from sequential decode at width 4

3 participants