Repository navigation
Commit 8928480
authored
[ET-VK] Activation transpose preprocess shaders + dispatch helper (pytorch#20055)
[ET-VK][q4gsw] Add et_vk.q4gsw_linear.default with W_4X8 GEMM + adaptive nc-coop GEMV
Pull Request resolved: pytorch#19996
Adds `et_vk.q4gsw_linear.default` backed by production compute shaders and a single top-level dispatch in `Q4gswLinear.cpp`. The op uses two or three execute nodes per dtype path that share a 6-binding descriptor set layout: a GEMM `DynamicDispatchNode` that self-gates to `{0,0,0}` at M==1, and an adaptive nc-coop GEMV sibling `DynamicDispatchNode` that self-gates to `{0,0,0}` at M!=1. The fp16 path adds a transpose preprocess that also self-gates at M==1. Decode-time `virtual_resize` correctly routes M==1 through the nc-coop GEMV after a prefill M>1 set up the graph. Existing serialized models that reference `et_vk.linear_q4gsw.default` are routed to the same forwarder so the cutover requires no graph-level changes; the old `QuantizedLinear.cpp::linear_q4gsw` body is deleted.
Production shaders under `runtime/graph/ops/glsl/`:
- `q4gsw_linear_gemm__w_4x8_nc` — fp32 GEMM, 4M x 8N per-thread tile, 8x8 LWG, reads the raw `[M, K]` activation directly. The per-k4 weight tile loads as a single `ivec4` covering 2 consecutive 4x4 N-blocks (one 16B aligned LSU read replaces two 8B reads). Aliases the same buffer the prepack writes.
- `q4gsw_linear_gemm__tin__w_4x8_nc` — fp16 GEMM, transposed-input path, 8x4 per-thread tile, 1x128 LWG, reads the pre-transposed vec4 activation produced by the transpose preprocess. Nibble dequant stays in int16 end-to-end before the fp16 FMA, saving one fp32 register and lifting AOC fiber occupancy from 37% to 50% on Adreno 750 (validated at M=256 K=4096 N=4096: 6135.92 us -> 5637.20 us, -8.1% wall-clock).
- `q4gsw_linear_gemv_coop__w_4x8_nc_buffer_{g1w64,g4w16,g8w8}` — cooperative-reduction GEMV reading the same nc-buffer weight payload as the GEMM shaders, with three (NUM_GROUPS, WORKERS_PER_GROUP) decompositions chosen at dispatch time by the production picker based on output N. All keep total threads/WG = 64; each WG produces NUM_GROUPS * 8 outputs, and the K-loop strides by WORKERS_PER_GROUP.
Prepack: `pack_q4_linear_weight__w_4x8_nc_buffer` produces an int SOA nibble buffer; one `ivec4` covers a 4K x 8N block. The fp32 GEMM shader views the buffer as `ivec4`; the fp16 tin GEMM shader reads it as `ivec2`; the nc-coop GEMV shader rebinds the same bytes as scalar int arrays. Scales use a single `prepack_q4_scales` (dtype-matched vec4) for GEMM; GEMV rebinds the same bytes as a gvec2 via `vec_size=2`. The shared nc-buffer payload means prefill and decode both consume one prepack — no dual-format weight memory cost.
Dispatch structure:
- fp32 (`add_q4gsw_linear_w_4x8_node`): two nodes. The GEMM dispatch binds `q4gsw_linear_gemm__w_4x8_nc` unconditionally; its gated global WG gates the dispatch to `{0,0,0}` at M==1. The nc-coop GEMV sibling owns the decode.
- fp16 (`add_q4gsw_linear_tin_w_4x8_node`): three nodes. The transpose preprocess self-gates `{0,0,0}` when M==1 (no-op); the GEMM dispatch binds `q4gsw_linear_gemm__tin__w_4x8_nc` and its gated global WG returns `{0,0,0}` at M==1; the nc-coop GEMV sibling handles M==1.
- nc-coop GEMV picker (`add_q4gsw_linear_nc_coop_gemv_node`): shape-adaptive dispatch that self-gates `{0,0,0}` when M!=1. Heuristic on output N:
* N <= 1024 -> `q4gsw_linear_gemv_coop__w_4x8_nc_buffer_g1w64` LWG (1, 1, 64)
* N <= 4096 -> `q4gsw_linear_gemv_coop__w_4x8_nc_buffer_g4w16` LWG (1, 4, 16)
* N > 4096 -> `q4gsw_linear_gemv_coop__w_4x8_nc_buffer_g8w8` LWG (1, 8, 8)
The adaptive picker replaces sg-GEMV at decode. Cross-device sweep on Galaxy S24 (Adreno 750), S25 (Adreno 830), and Pixel 9 Pro XL (Mali-G715) shows shape-adaptive nc-coop beats sg-GEMV on every LLM-decode shape by 3-56%, with the largest wins at small-N (47-56% at K=2048 N=512 across both Adreno devices). The adaptive picker also unblocks Mali, where sg-GEMV cannot dispatch (subgroupSize=16 != required 64).
The op is registered under both `et_vk.q4gsw_linear.default` and `et_vk.linear_q4gsw.default` for backward compatibility. Also extends `validate_against_reference` in `test/custom_ops/utils.cpp` to handle fp16 tensors.
Demonstration shaders under `test/custom_ops/glsl/` (not linked into the production shader library):
- `q4gsw_linear_gemv__w_4x8_nc{,_nosg}` — sg / nosg GEMV variants from earlier iterations. The sg variant pins subgroupSize to 64 via `VK_EXT_subgroup_size_control` and uses `subgroupBroadcast`; the nosg variant has every thread load its own activation. Both are dispatched by the `test_fpa_q4gsw_linear` benchmark binary's forced-shader selectors `GEMV_W_4X8` and `GEMV_W_4X8_NOSG` (selectors 1 and 2). Retained as a demonstration of the single-thread-per-output GEMV layout the adaptive nc-coop now supersedes at decode.
Buffer-padding fix (latent OOB read on N % 8 != 0): The fp32 GEMM's 16B ivec4 weight load spans two consecutive (k4, n4) ivec2 tiles along N. Pad the SOA weight buffer's row stride to next-even N4 (no-op for the canonical N % 8 == 0 shapes); the prepack shader's existing `(n < N)` branch fills the OOB tiles with the bias-zero nibble pattern (0x88888888u). Adds GEMM accuracy coverage for N=12 and N=20.
ghstack-source-id: 390109017
@exported-using-ghexport
Differential Revision: [D107447239](https://our.internmc.facebook.com/intern/diff/D107447239/)1 parent d66a2a3 commit 8928480
26 files changed
Lines changed: 4274 additions & 39 deletions
File tree
- backends/vulkan
- runtime/graph/ops
- glsl
- impl
- test/custom_ops
- glsl
- impl
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
0 commit comments