[ExecuTorch][WebGPU] Add q8ta_add op (int8 elementwise add)#21191
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/21191
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit ff9b3d7 with merge base 4a26c64 ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Pull Request resolved: #21191 Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established. Solution: Port `et_vk.q8ta_add` (two int8 tensors + per-tensor qparams -> int8): dequantize both, compute `a + alpha*b`, requantize. Reuses the C0 int8 buffer path (`array<u32>` pack/unpack, `is_int8` guard, multiply-by-`inv_scale`). Implementation: `Q8taAdd.cpp` registers `et_vk.q8ta_add.default` (`out = args.back()`), guards all three tensors int8 + equal `numel` + `numel % 4 == 0`, fail-loud; `q8ta_add.wgsl` unpacks 4 int8/word, dequantizes `scale*(q - zero_point)`, forms `a + alpha*b`, and requantizes `clamp(round(v * inv_output_scale) + zero_point, -128, 127)`. Mirrors Vulkan `q8ta_binary.glsl` + `common.glslh`, with one deliberate divergence: the Vulkan glsl buffer kernel drops `alpha` (computes `a + b`), so this port implements the full `a + alpha*b` to match the CPU reference for any `alpha` (surfaced in the handler comment). Constraints: same-shape only (no broadcast — the equal-`numel` guard rejects it, matching the `add` op baseline); `supports_resize=False` (no resize hook), mirroring the partitioner. ghstack-source-id: 406366820 @exported-using-ghexport Differential Revision: [D112257597](https://our.internmc.facebook.com/intern/diff/D112257597/)
Stack from ghstack (oldest at bottom):
Problem: The WebGPU delegate has no quantized elementwise add — the first C1 q8ta op, on the int8 activation path C0 established.
Solution: Port
et_vk.q8ta_add(two int8 tensors + per-tensor qparams -> int8): dequantize both, computea + alpha*b, requantize. Reuses the C0 int8 buffer path (array<u32>pack/unpack,is_int8guard, multiply-by-inv_scale).Implementation:
Q8taAdd.cppregisterset_vk.q8ta_add.default(out = args.back()), guards all three tensors int8 + equalnumel+numel % 4 == 0, fail-loud;q8ta_add.wgslunpacks 4 int8/word, dequantizesscale*(q - zero_point), formsa + alpha*b, and requantizesclamp(round(v * inv_output_scale) + zero_point, -128, 127). Mirrors Vulkanq8ta_binary.glsl+common.glslh, with one deliberate divergence: the Vulkan glsl buffer kernel dropsalpha(computesa + b), so this port implements the fulla + alpha*bto match the CPU reference for anyalpha(surfaced in the handler comment).Constraints: same-shape only (no broadcast — the equal-
numelguard rejects it, matching theaddop baseline);supports_resize=False(no resize hook), mirroring the partitioner.@exported-using-ghexport
Differential Revision: D112257597
Differential Revision: D112257597