[ExecuTorch][WebGPU] Add opt-in native f16 KV cache (−280 MiB, default-OFF)#20770
[ExecuTorch][WebGPU] Add opt-in native f16 KV cache (−280 MiB, default-OFF)#20770JCNTH wants to merge 1 commit into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/20770
Note: Links to docs will display an error until the docs builds have been completed. ❌ 1 New Failure, 1 Unrelated FailureAs of commit 3649dd4 with merge base f8c8334 ( NEW FAILURE - The following job has failed:
BROKEN TRUNK - The following job failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
Stack from ghstack (oldest at bottom):
Add an opt-in native f16 KV cache for WebGPU SDPA — −280 MiB device memory, decode-neutral, default-OFF (byte-identical when off).
Problem: The SDPA K/V cache is stored fp32, so at long context it dominates WebGPU device memory. On a device that negotiated the shader-f16 feature the cache can be stored as native f16 (half the bytes) while attention still accumulates in f32, at no measured decode-speed cost.
Solution: Behind a new opt-in build flag
EXECUTORCH_WEBGPU_KV_F16(definesWGPU_BACKEND_KV_F16, default OFF), and only when the device supports shader-f16 (fail-closed to f32 otherwise):numel*4bytes) and read by the f32 SDPA kernels.numel*2bytes, zero-init); SDPA and FlashDecoding select_f16kernel variants that bind the cache as f16 and widen to f32 on read — compute and accumulation are unchanged.Implementation:
sdpa_compute_attn_weights_f16/sdpa_compute_out_f16bindarray<vec4<f16>>and widen withvec4<f32>(...);sdpa_fd_split_f16binds scalararray<f16>and widens withf32(...);update_cache_f16writesf16(...).WebGPUGraph::build: collect the sdpa K/V cache value ids (args[3],args[4]), allocate them as a dedicated half-size f16 buffer at the constant-allocation site, plus a defensive guard that throws if a non-sdpa op would misread an f16 cache.Sdpa.cpp/SdpaFdDecode.cpp: select the_f16shader whenkv_f16()via a localconst char*(mirrors the steel-f16 gate — no function-signature/ABI change).force_fp16fp32→fp16 storage downcast (backends/vulkan/serialization/vulkan_graph_builder.pyget_effective_dtype); here scoped to the K/V cache and gated on the negotiated shader-f16 feature rather than applied graph-wide.Constraints: the default build (flag OFF) is byte-identical — all f16 code is
#ifdef WGPU_BACKEND_KV_F16-gated with no ABI change and no KV-cache-layout migration on the default path; the opt-in build fail-closes to f32 on a non-shader-f16 device; f16 storage requireshead_dim % 4 == 0(already required and guarded).Co-authored-with: Claude Code.
Differential Revision: D110919974