Skip to content

perf(gemma4): project only the sampled row at prefill on every path - #1973

Merged
inureyes merged 1 commit into
mainfrom
update/issue-1972-gemma4-last-row-prefill
Sep 24, 2026
Merged

inureyes merged 1 commit into
mainfrom
update/issue-1972-gemma4-last-row-prefill

Conversation

@inureyes

Copy link
Copy Markdown
Member

Gemma 4 prefill still computed full 262k-vocab logits (plus a softcap copy) and kept one row on the paths the shipped checkpoints take:

This PR drops the 4096 gate, overrides all three entry points on the text wrapper through one logits_at helper (head + softcap on the sliced row), and forwards them from both VLM wrappers with the same per-layer-input and vision block-id selection as their forward paths. The gate's premise was byte-identity; 11 families moved to the single-row kernel in #1955, #1969 and #1971 with identical greedy output, and so does Gemma 4 here.

Measurements

M1 Ultra, mlxcel-bench-decode with bench_decode.sh arguments, main 2dfc33e5 against this branch, ABBA:

Model pp512 pp2048
Gemma 4 E4B 4-bit +15.5% +15.3%
Gemma 4 12B 4-bit +8.8% +8.6%

Decode unchanged. Record: docs/benchmark_results/gemma4-last-row-prefill-m1ultra-2026-09-25.md.

Validation

  • Greedy output identical to main on E4B and 12B: short prompt, 512-token prompt, image prompt.
  • New test gemma4_last_logits_match_the_sliced_full_forward checks the three entry points at the last and an interior position for sliding and full attention; shifting the row by one fails it.
  • fmt, workspace clippy and make verify-test pass locally.

Not covered: CUDA/ROCm, the MTP target path (keeps its own full forward).

Closes #1972

Gemma 4 prefill still built the full [1, L, 262144] logits plus a softcap copy on the paths the shipped checkpoints take. The text wrapper kept full logits up to 4096 prompt tokens (#672), had no sequence-id overrides so server prefill used the trait default, and the published checkpoints load as Gemma4VLModel or Gemma4UnifiedModel, which forwarded none of the forward_last_logits entry points.

The text wrapper now overrides all three entry points at every length through a shared logits_at helper, and both VLM wrappers forward them, keeping their per-layer-input and vision block-id selection.

Against main on M1 Ultra (bench_decode.sh arguments, ABBA): E4B prefill +15.5% at pp512 and +15.3% at pp2048, 12B +8.8% and +8.6%. Greedy output identical on both for a short, a 512-token and an image prompt. New unit test covers the three entry points at two positions for both attention families and fails when the row is shifted.

Closes #1972
@inureyes inureyes added status:review Under review type:performance Performance improvements priority:medium Medium priority area:models Model architectures, weights, loading, metadata platform:macos macOS (Apple Silicon) specific labels Sep 24, 2026
@inureyes
inureyes merged commit c61898e into main Sep 24, 2026
20 checks passed
@inureyes inureyes added status:done Completed and removed status:review Under review labels Sep 24, 2026
@inureyes
inureyes deleted the update/issue-1972-gemma4-last-row-prefill branch October 6, 2026 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:models Model architectures, weights, loading, metadata platform:macos macOS (Apple Silicon) specific priority:medium Medium priority status:done Completed type:performance Performance improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf(gemma4): project only the sampled row at prefill on every entry point

1 participant