Skip to content

[ExecuTorch][WebGPU] Test coverage for the packed-word-dequant f16 steel GEMM#20824

Merged
JCNTH merged 3 commits into
gh/JCNTH/13/origfrom
gh/JCNTH/14/orig
Jul 9, 2026
Merged

[ExecuTorch][WebGPU] Test coverage for the packed-word-dequant f16 steel GEMM#20824
JCNTH merged 3 commits into
gh/JCNTH/13/origfrom
gh/JCNTH/14/orig

Conversation

@pytorchbot

Copy link
Copy Markdown
Collaborator

This PR was created by the merge bot to help merge the original PR into the main branch.
ghstack PR number: #20799 by @JCNTH
^ Please use this as the source of truth for the PR details, comments, and reviews
ghstack PR base: https://github.com/pytorch/executorch/tree/gh/JCNTH/14/base
ghstack PR head: https://github.com/pytorch/executorch/tree/gh/JCNTH/14/head
Merge bot PR base: https://github.com/pytorch/executorch/tree/gh/JCNTH/13/orig
Merge bot PR head: https://github.com/pytorch/executorch/tree/gh/JCNTH/14/orig

@diff-train-skip-merge

…eel GEMM

Pull Request resolved: #20799

Locks the `group_size % BK` gate that selects the packed-word-dequant (`pwdq`) f16 steel GEMM. `pwdq` is bit-exact to the `half` kernel, so the existing `steel_f16`/`steel_f16_edge` configs (gs=32) already exercise it; these add the two group sizes the gate keys on but those omit.

Key changes:
- `test_quantized_linear.py` / `test_webgpu_native.cpp` — add `pwdq_gs64` (gs=64, `% BK == 0` → stays on `pwdq`) and `pwdq_gs8` (gs=8 `< BK=16` → falls back to the per-nibble `half` kernel, whose per-K scale read is correct there). Both goldened at the f16 tol (2.3e-4) in the `WGPU_BACKEND_STEEL_F16` build against the fp64 dequant-matmul truth.

Co-authored-with: Claude Code.
ghstack-source-id: 401564881
@exported-using-ghexport

Differential Revision: [D111163551](https://our.internmc.facebook.com/intern/diff/D111163551/)
@pytorch-bot

pytorch-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/20824

Note: Links to docs will display an error until the docs builds have been completed.

This comment was automatically generated by Dr. CI and updates every 15 minutes.

JCNTH added 2 commits July 9, 2026 14:43
…GEMM

Pull Request resolved: #20800

**+46-56% end-to-end prefill tok/s over the shipped f16 `steel` q4gsw GEMM (Apple M4 Pro / Chrome Canary), behind an opt-in runtime spec (default OFF); perplexity held (13.32 -> 13.37, +0.05).**

**Problem:** the f16 `steel` prefill GEMM (and its packed-word-dequant variant `pwdq`) accumulates its 4x4 register tile in f32. WebLLM/MLC accumulate in f16, which halves the accumulator footprint and raises occupancy — the largest remaining prefill gap vs MLC on Apple.

**Solution:** an f16-accumulate variant of the `pwdq` kernel — identical staging (dequant-once + hoisted scale) and 64x64/256-thread/BK=16 geometry, but the 4x4 accumulator is kept in f16 with `fma()` (mirrors MLC's `array<f16,16>` reduction) and cast to f32 in the epilogue for the f32 output/bias.

Before (`pwdq`): f16 multiply, f32 accumulate.
After (`pwdqf16acc`): f16 multiply, f16 accumulate, f32 epilogue.

**Implementation:**
- New `ACC=half` fork in the shared `q4gsw_linear_gemm_steel.wgsl` template (a `shader_variants` entry in `q4gsw_linear_gemm_steel.yaml` generates `q4gsw_linear_gemm_steel_half_pwdq_f16acc_wgsl.h`) — no standalone shader file.
- Opt-in via the `enable_f16_accumulate_gemm` runtime spec (a load-time `BackendOption` read in `WebGPUBackend::init`, threaded through `WebGPUGraph::build(..., f16_accumulate_gemm)` -> `graph.f16_accumulate_gemm()`), default OFF — no CMake option or compile flag.
- When the spec is set, overrides the f32-accumulate steel kernels for M>1 prefill whenever the device negotiated shader-f16 and `group_size % BK == 0`; else the f32-accumulate `pwdq` / `half` / f32 kernels run (fail-closed).

**Constraints:** LOSSY — f16 accumulation over the full K (up to 8192) is not bit-exact, so it ships on a perplexity bar, not a bit-exact gate (as MLC does): measured Llama-3.2-1B int4 perplexity 13.32 -> 13.37 (+0.05) on the real prefill path. Default-OFF keeps upstream builds on the strict f32-accumulate golden; the runtime spec is opt-in for latency-sensitive deployments.

Co-authored-with: Claude Code.
ghstack-source-id: 401564900
@exported-using-ghexport

Differential Revision: [D111163606](https://our.internmc.facebook.com/intern/diff/D111163606/)
Pull Request resolved: #20801

Adds golden coverage for the f16-accumulate (`pwdqf16acc`) steel GEMM, which runs under `WGPU_BACKEND_STEEL_F16ACC` when `group_size % BK == 0`.

Key changes:
- `test_quantized_linear.py` / `test_webgpu_native.cpp` — add `pwdqf16acc` (96x2048x256, K=2048) and `pwdqf16acc_down` (128x8192x2048, deep-K worst case) under `#ifdef WGPU_BACKEND_STEEL_F16ACC`, goldened against the fp64 dequant-matmul truth. f16 accumulation error grows with K, so the tolerances are wider than the f16-multiply `steel_f16` (2.3e-4) and the deep-K shape gets the loosest gate; perplexity (the kernel diff) is the primary quality bar and this catches gross bit/index bugs.

Co-authored-with: Claude Code.
ghstack-source-id: 401515200
@exported-using-ghexport

Differential Revision: [D111163651](https://our.internmc.facebook.com/intern/diff/D111163651/)
@JCNTH JCNTH merged commit b93758e into gh/JCNTH/13/orig Jul 9, 2026
20 of 21 checks passed
@JCNTH JCNTH deleted the gh/JCNTH/14/orig branch July 9, 2026 21:44
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants