Skip to content

[ExecuTorch][Vulkan] Tests for et_vk.adamw_step#21092

Closed
pytorchbot wants to merge 30 commits into
gh/JCNTH/56/origfrom
gh/JCNTH/77/orig
Closed

[ExecuTorch][Vulkan] Tests for et_vk.adamw_step#21092
pytorchbot wants to merge 30 commits into
gh/JCNTH/56/origfrom
gh/JCNTH/77/orig

Conversation

@pytorchbot

@pytorchbot pytorchbot commented Jul 21, 2026

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: #20938 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/77/base
ghstack PR head: https://github.com/pytorch/executorch/tree/gh/JCNTH/77/head
Merge bot PR base: https://github.com/pytorch/executorch/tree/gh/JCNTH/76/orig
Merge bot PR head: https://github.com/pytorch/executorch/tree/gh/JCNTH/77/orig

@diff-train-skip-merge

cc @SS-JIA @manuelcandales @digantdesai @cbilgin

JCNTH added 21 commits July 21, 2026 00:29
Pull Request resolved: #20918

Export-delegation + fp64 golden tests for the matmul (`mm`, `bmm`, `linear`) ops.

Key changes:
- `test/ops/{test_matmul,test_bmm,test_linear}.py` — fp64 library-reference goldens + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

Differential Revision: [D111755120](https://our.internmc.facebook.com/intern/diff/D111755120/)
…WebGPU backend

Pull Request resolved: #20919

Add `aten._softmax` + `aten._log_softmax` handlers (max-stable online softmax) for the training tail.

Key changes:
- `runtime/ops/{softmax,log_softmax}/` — max-stable softmax + log_softmax WGSL kernels + handlers
- `CMakeLists.txt` `WEBGPU_SRCS` — wire the sources

Reuses the shared Vulkan partitioner (`aten._softmax`/`_log_softmax` already registered); WebGPU kernels only.

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

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

Export-delegation + fp64 golden tests for the softmax (`_softmax`, `_log_softmax`) ops.

Key changes:
- `test/ops/{test_softmax,test_log_softmax}.py` — fp64 goldens + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

Differential Revision: [D111755117](https://our.internmc.facebook.com/intern/diff/D111755117/)
…GPU backend

Pull Request resolved: #20921

Add broadcast-aware `aten.div.Tensor` + `aten.sub.Tensor` elementwise handlers for the training tail.

Key changes:
- `runtime/ops/{div,sub}/` — broadcast elementwise WGSL kernels + handlers
- `CMakeLists.txt` `WEBGPU_SRCS` — wire the sources

Reuses the shared Vulkan partitioner (`aten.div.Tensor`/`sub.Tensor` already registered); WebGPU kernels only.

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

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

Export-delegation + fp64 golden tests for the binary (`div`, `sub`) ops.

Key changes:
- `test/ops/{test_div,test_sub}.py` — fp64 goldens (incl. broadcast) + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

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

Add an `aten.sum.dim_IntList` / `aten.mean.dim` reduction handler for the training tail.

Key changes:
- `runtime/ops/reduce/` — per-row reduction WGSL kernel + handler
- `CMakeLists.txt` `WEBGPU_SRCS` — wire the source

Reuses the shared Vulkan partitioner (`aten.sum.dim_IntList`/`mean.dim` already registered); WebGPU kernel only.

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

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

Export-delegation + fp64 golden tests for the reduce (`sum`/`mean`) ops.

Key changes:
- `test/ops/test_reduce.py` — fp64 goldens (dim variants) + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

Differential Revision: [D111755115](https://our.internmc.facebook.com/intern/diff/D111755115/)
…logical_not) to the WebGPU backend

Pull Request resolved: #20925

Add `aten.where.self`, scalar comparisons (`aten.{eq,ne,le,ge,lt,gt}.Scalar`), and `aten.logical_not.default` handlers for the training tail. The scalar compares and `logical_not` are generated from ONE templated byte-packed-bool shader (`runtime/ops/boolean_op/`) rather than per-op hand-written kernels — mirroring the `binary_op` codegen and Vulkan's grouping of comparison ops as `${OPERATOR}` variants (`backends/vulkan/runtime/graph/ops/glsl/binary_op_buffer.yaml`).

Key changes:
- `runtime/ops/boolean_op/` — one `boolean_op.wgsl` template + `boolean_op.yaml` (variants `compare_{eq,ne,le,ge,lt,gt}` + `logical_not`) expand to the per-variant `*_wgsl.h`; `BooleanOp.cpp` holds one shared `dispatch_bool_op` helper (pack 4 bools per `u32` word, one thread per word) plus the seven `WEBGPU_REGISTER_OP`s.
- `runtime/ops/where/` — ternary select, kept as its own kernel/handler (non-bool-family, as in Vulkan).
- `op_registry.py` — register the net-new `aten.{ne,lt,le,ge,gt}.Scalar` + `aten.logical_not.default` `OpFeatures` (`eq.Scalar` already on master).
- `CMakeLists.txt` `WEBGPU_SRCS` — wire `boolean_op/BooleanOp.cpp`.

`aten.where.self` already had Vulkan `OpFeatures`; the scalar-compare + `logical_not` registrations are additive to the shared Vulkan registry.

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

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

Export-delegation + fp64 golden tests for the select/bool (`where`, scalar compares, `logical_not`) ops.

Key changes:
- `test/ops/{test_where,test_compare,test_logical_not}.py` — fp64 goldens + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

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

Add `aten.gather.default` (row-gather) + `aten.embedding.default` handlers for the training tail.

Key changes:
- `runtime/ops/{gather,embedding}/` — gather / row-gather WGSL kernels + handlers
- `CMakeLists.txt` `WEBGPU_SRCS` — wire the sources

Reuses the shared Vulkan partitioner (`aten.gather`/`embedding` already registered); WebGPU kernels only.

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

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

Export-delegation + fp64 golden tests for the gather (`gather`, `embedding`) ops.

Key changes:
- `test/ops/{test_gather,test_embedding}.py` — fp64 goldens + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

Differential Revision: [D111755129](https://our.internmc.facebook.com/intern/diff/D111755129/)
…) to the WebGPU backend

Pull Request resolved: #20929

Add `_clone_dim_order` (DMA copy), `aten.expand_copy` (broadcast), and `fill` (`aten.full`/`full_like`/`scalar_tensor`) handlers for the training tail.

Key changes:
- `runtime/ops/{dim_order,expand_copy,fill}/` — WGSL kernels + handlers (dim_order is a native buffer DMA copy)
- `CMakeLists.txt` `WEBGPU_SRCS` — wire the sources

Reuses the shared Vulkan partitioner (`_clone_dim_order`/`expand_copy`/`full`* already registered); WebGPU kernels only.

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

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

Export-delegation + fp64 golden tests for the shape/copy (`dim_order`, `expand_copy`, `fill`) ops.

Key changes:
- `test/ops/{test_dim_order,test_expand_copy,test_fill}.py` — fp64 goldens + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

Differential Revision: [D111755126](https://our.internmc.facebook.com/intern/diff/D111755126/)
…d, requant) to the WebGPU backend

Pull Request resolved: #20931

Add the 4-bit fine-tuning weight-path custom ops — `et_vk.linear_q4gsw_backward` (input grad dX), `et_vk.linear_dW` (weight grad dW — a generic fp32 weight-gradient matmul, not q4gsw-specific), and `et_vk.q4gsw_requant` (STE re-quant of fp32 latents → 4-bit codes) — that close the on-device training loop through a frozen 4-bit base.

Key changes:
- `runtime/ops/quantized_linear/{QuantizedLinearBackward,QuantizedLinearRequant}.cpp` + `LinearDw.cpp` + `q4gsw_{backward,requant}.wgsl` + `linear_dW.wgsl` — the three training kernels
- `custom_ops_lib.py` — 3 custom-op defs (`linear_q4gsw_backward` + `register_autograd` on `linear_q4gsw`, `linear_dW`, `q4gsw_requant`)
- `op_registry.py` — 3 `OpFeatures`
- `CMakeLists.txt` `WEBGPU_SRCS` — wire the sources

Training-only, WebGPU-only custom ops registered under the shared Vulkan partitioner; Vulkan has no kernels for them yet (a separate Vulkan-kernel track covers that). Guards mirror the sibling `Dw`/`Requant` ops (scales-rank + `K==0`).

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

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

Export-delegation + fp64 golden tests for the q4gsw training (`backward`, `dw`, `requant`) ops.

Key changes:
- `test/ops/{test_quantized_linear_backward,test_linear_q4gsw_dw,test_q4gsw_requant}.py` — fp64 dequant-matmul / weight-grad / re-quant goldens + a round-trip + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

Differential Revision: [D111755121](https://our.internmc.facebook.com/intern/diff/D111755121/)
…WebGPU backend

Pull Request resolved: #20933

Add `et_vk.fused_ce` — a fused cross-entropy (loss + dlogits in one op) for the on-device training tail.

Key changes:
- `runtime/ops/fused_ce/` — fused-CE WGSL kernel (+ the `reduce` shader it depends on) + handler
- `custom_ops_lib.py` — `fused_ce` custom-op def + `register_autograd`
- `op_registry.py` — `OpFeatures`
- `CMakeLists.txt` `WEBGPU_SRCS` — wire the source

Training-only, WebGPU-only custom op registered under the shared Vulkan partitioner; no Vulkan kernel yet.

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

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

Export-delegation + fp64 golden tests for the fused_ce ops.

Key changes:
- `test/ops/test_fused_ce.py` — fp64 loss + dlogits goldens (incl. masked-label) + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

Differential Revision: [D111755119](https://our.internmc.facebook.com/intern/diff/D111755119/)
…p) to the WebGPU backend

Pull Request resolved: #20935

Add `et_vk.adamw_step` — an on-GPU AdamW optimizer step (delegated in-place parameter update) for on-device training.

Key changes:
- `runtime/ops/adamw/` — elementwise AdamW-update WGSL kernel + handler
- `custom_ops_lib.py` — `adamw_step` custom-op def (mutating, `Tensor(a!)`)
- `op_registry.py` — `OpFeatures` (string key `et_vk::adamw_step`)
- `CMakeLists.txt` `WEBGPU_SRCS` — wire the source

Delegating the optimizer step to the GPU is new to ExecuTorch — its optimizers are host-side C++ (`extension/training/optimizer/adamw.cpp`). Training-only WebGPU custom op under the shared Vulkan partitioner; no Vulkan kernel yet.

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

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

Export-delegation + fp64 golden tests for the adamw (`adamw_step`) ops.

Key changes:
- `test/ops/test_adamw.py` — fp64 in-place param/m/v goldens (incl. non-zero weight-decay) + delegation checks — fp64 library-reference goldens + delegation checks (≥2 cases/op).

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

Differential Revision: [D111755127](https://our.internmc.facebook.com/intern/diff/D111755127/)
…zer step)

Pull Request resolved: #20937

Vulkan GLSL kernel + handler for the training custom op `et_vk.adamw_step` (elementwise in-place AdamW parameter update). Mirrors `impl/BinaryOp.cpp` elementwise structure + `unary_op.glsl` push-constant scalars; param/m/v are read-modify-write (`kReadWrite`). AOT registration already exists under the shared Vulkan partitioner.
ghstack-source-id: 405026087
@exported-using-ghexport

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

Vulkan op-test golden for `et_vk.adamw_step` (ATen library-computed reference of the CPU-eager update; in-place param/m/v vs the kernel). 3 cases incl. non-zero weight-decay + a large 1-D tail. Wires `adamw_step_test` in `targets.bzl` + `CMakeLists.txt`.
ghstack-source-id: 405030805
@exported-using-ghexport

Differential Revision: [D111761775](https://our.internmc.facebook.com/intern/diff/D111761775/)
@pytorch-bot pytorch-bot Bot added the module: vulkan Issues related to the Vulkan delegate and code under backends/vulkan/ label Jul 21, 2026
@pytorch-bot

pytorch-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

❗ 1 Active SEVs

There are 1 currently active SEVs. If your PR is affected, please view them below:

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

JCNTH added 3 commits July 21, 2026 09:42
…W_4X8)

Pull Request resolved: #20945

**Adds the Vulkan `et_vk.q4gsw_requant` kernel** — straight-through re-quant of fp32 latent weights into the frozen-scale 4-bit codes, for on-device weight training. Writes the codes directly in the forward's W_4X8 layout so no per-step re-pack is needed.

**Problem:** `et_vk.q4gsw_requant` is registered in the shared Vulkan partitioner but Vulkan had no runtime kernel.

**Solution:** a GLSL kernel that quantizes `round(latent / scale)` clamped to `[-8, 7]` and packs the codes in the W_4X8 block layout the forward reads, reusing the exact byte-pair convention of `glsl/pack_q4_linear_weight__w_4x8.glsl` (even-N low nibble, odd-N high; one ivec4 per 4K x 8N block at `(k4, n8)`; OOB upper tile = the bias-zero `0x88888888`). A zero scale yields code 8 (no divide-by-zero), matching the eager reference.

Key changes:
- `glsl/q4gsw_requant.{glsl,yaml}` — buffer x float; 2D dispatch over `(k4, n8)`.
- `impl/QuantizedLinearRequant.cpp` — prepacks the constant scales; output is the W_4X8 int buffer `[K4 * N4_padded * 2]`; `group_size` spec constant; dispatch-grid guard.

**Design note (for review):** per the layout decision, requant writes W_4X8 to match the Vulkan forward. Today the forward and backward each prepack their own flat `[N, K/2]` weight internally, so nothing yet consumes an externally-produced W_4X8 buffer — closing the training loop needs a forward path that reads a mutable pre-packed weight (the weight-lifecycle follow-up). The op's AOT meta in `custom_ops_lib.py` still describes the flat `[N, K/2]` output and should be reconciled with this W_4X8 output.

**Constraints:** buffer storage, fp32 latent/scales; `N % 4 == 0`, `K % 4 == 0`, `group_size % 4 == 0`.
ghstack-source-id: 405059118
@exported-using-ghexport

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

**Correctness tests for the Vulkan `et_vk.q4gsw_requant` kernel** (stacked above the op diff).

**Coverage:** the golden codes are computed with ATen (`round`/`clamp`, zero-scale -> code 8), mirroring `quant_nibble`, then packed into the expected W_4X8 int buffer with a small bit-packing reference (data-reshaping only, no hand-rolled math). The kernel output is compared int-for-int against that buffer, which locks the exact byte layout the forward reads. The latent is built as `code * scale` so `round()` is unambiguous (no `.5` tie-break divergence).

Cases:
- `test_tile_aligned` — single group, tile-aligned N/K.
- `test_grouped` — multiple quantization groups along K.
- `test_odd_n4` — `N % 8 != 0` (odd N4 -> padded stride + bias-zero OOB tile).
- `test_zero_scale` — a zero scale must yield code 8, not a divide-by-zero.

Also wires `q4gsw_requant_test` into `targets.bzl` + `CMakeLists.txt`.
ghstack-source-id: 405059122
@exported-using-ghexport

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

Replace the hand-maintained explicit `WEBGPU_SRCS` op-handler list with `file(GLOB WEBGPU_OP_SRCS CONFIGURE_DEPENDS runtime/ops/*/*.cpp)` so adding a new op no longer requires editing this file (addresses review feedback). The five `runtime/*.cpp` sources and `runtime/ops/OperatorRegistry.cpp` (which sits directly under `ops/`, not a per-op subdir) stay explicit. `CONFIGURE_DEPENDS` re-globs at build time when op sources are added or removed.

The glob resolves to exactly the 40 op handlers the explicit list enumerated (verified set-equal) — no op added or dropped, and static-init registration is order-independent under `--whole-archive`.

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

Differential Revision: [D112482039](https://our.internmc.facebook.com/intern/diff/D112482039/)
Base automatically changed from gh/JCNTH/76/orig to gh/JCNTH/75/orig July 21, 2026 16:43
Base automatically changed from gh/JCNTH/75/orig to gh/JCNTH/74/orig July 21, 2026 16:44
Base automatically changed from gh/JCNTH/74/orig to gh/JCNTH/73/orig July 21, 2026 16:44
Base automatically changed from gh/JCNTH/73/orig to gh/JCNTH/72/orig July 21, 2026 16:44
Base automatically changed from gh/JCNTH/72/orig to gh/JCNTH/71/orig July 21, 2026 16:45
Base automatically changed from gh/JCNTH/71/orig to gh/JCNTH/70/orig July 21, 2026 16:45
Base automatically changed from gh/JCNTH/70/orig to gh/JCNTH/69/orig July 21, 2026 16:46
Base automatically changed from gh/JCNTH/69/orig to gh/JCNTH/68/orig July 21, 2026 16:46
Base automatically changed from gh/JCNTH/68/orig to gh/JCNTH/67/orig July 21, 2026 16:47
Base automatically changed from gh/JCNTH/67/orig to gh/JCNTH/66/orig July 21, 2026 16:47
Base automatically changed from gh/JCNTH/66/orig to gh/JCNTH/65/orig July 21, 2026 16:47
Base automatically changed from gh/JCNTH/65/orig to gh/JCNTH/64/orig July 21, 2026 16:48
Base automatically changed from gh/JCNTH/64/orig to gh/JCNTH/63/orig July 21, 2026 16:48
Base automatically changed from gh/JCNTH/63/orig to gh/JCNTH/62/orig July 21, 2026 16:48
Base automatically changed from gh/JCNTH/62/orig to gh/JCNTH/61/orig July 21, 2026 16:48
Base automatically changed from gh/JCNTH/61/orig to gh/JCNTH/60/orig July 21, 2026 16:49
Base automatically changed from gh/JCNTH/60/orig to gh/JCNTH/59/orig July 21, 2026 16:50
Base automatically changed from gh/JCNTH/59/orig to gh/JCNTH/58/orig July 21, 2026 16:50
Base automatically changed from gh/JCNTH/58/orig to gh/JCNTH/57/orig July 21, 2026 16:51
Base automatically changed from gh/JCNTH/57/orig to gh/JCNTH/56/orig July 21, 2026 16:51
@JCNTH JCNTH closed this Jul 21, 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. module: vulkan Issues related to the Vulkan delegate and code under backends/vulkan/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants