Xenova HF Staff commited on
Commit
adee57e
·
verified ·
1 Parent(s): 8c41d43

sync 91d990483a17

Browse files
README.md CHANGED
@@ -18,17 +18,17 @@ See the [ONNX Runtime `MatMulBnb4` contrib-operator spec](https://github.com/mic
18
 
19
  ## Inputs
20
 
21
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
22
  | --- | --- | --- | --- | --- | --- | --- |
23
- | `A` | `aT` | `T1` | `2` | — | Float input matrix of shape `(M, K)`, not quantized. | required |
24
- | `B` | `bT` | `T2` | `1` | — | The `[N, K]` weight, flattened and quantized to 4 bits, stored as `(N * K + 1) / 2` bytes; the ONNX type is uint8 (this WebGPU implementation reads one widened u32 per stored byte). | required |
25
- | `absmax` | `absmaxT` | `T1` | `1` | — | Per-block absolute-maximum dequantization scales of shape `((N * K + block_size - 1) / block_size)`, same dtype as A. | required |
26
 
27
  ## Outputs
28
 
29
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
30
  | --- | --- | --- | --- | --- | --- | --- |
31
- | `Y` | `yT` | `T1` | `2` | `[A[0], N]` | Result of `A` multiplied by the dequantized, transposed weight matrix, with shape `(M, N)` and the same dtype as `A`. | required |
32
 
33
  ## Attributes
34
 
@@ -36,12 +36,12 @@ Attributes and default values (overridable per request):
36
 
37
  | Attribute | Default | Description |
38
  | --- | --- | --- |
39
- | `training_mode` | `0` | Whether training outputs are requested. This inference-only implementation supports the standard default value 0. |
40
- | `transB` | `1` | Whether the quantized weight is stored transposed. This implementation supports the standard default value 1. |
41
  | `K` | — | Input feature count (the shared dimension). |
42
  | `N` | — | Output feature count. |
43
  | `block_size` | — | Number of weights sharing one absmax scale; a power of two, at least 16. |
44
  | `quant_type` | — | Codebook selector: 0 = FP4, 1 = NF4. |
 
 
45
 
46
  ## Type constraints
47
 
@@ -50,13 +50,22 @@ Attributes and default values (overridable per request):
50
  | `T1` | `float32`, `float16` |
51
  | `T2` | `uint8` |
52
 
 
 
 
 
 
 
 
 
 
53
  ## Device requirements
54
 
55
  Some implementation variants require `subgroup-matrix` and `subgroups`. These are route-specific capabilities, not package-wide requirements; availability also depends on the request shape and dtype.
56
 
57
  ## Files
58
 
59
- - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
60
  - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
61
  - [`test.json`](build/webgpu/test.json) — correctness cases
62
  - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
@@ -68,10 +77,14 @@ Some implementation variants require `subgroup-matrix` and `subgroups`. These ar
68
 
69
  ## Use with `@huggingface/kernels`
70
 
71
- The loader derives every required output's shape and logical dtype from the manifest contract and this call.
72
- It then allocates the result tensors automatically.
 
 
 
73
 
74
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
 
75
 
76
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
77
 
 
18
 
19
  ## Inputs
20
 
21
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
22
  | --- | --- | --- | --- | --- | --- | --- |
23
+ | `aT` | `A` | `T1` | `2` | — | Float input matrix of shape `(M, K)`, not quantized. | required |
24
+ | `bT` | `B` | `T2` | `1` | — | The `[N, K]` weight, flattened and quantized to 4 bits, stored as `(N * K + 1) / 2` bytes; the ONNX type is uint8 (this WebGPU implementation reads one widened u32 per stored byte). | required |
25
+ | `absmaxT` | `absmax` | `T1` | `1` | — | Per-block absolute-maximum dequantization scales of shape `((N * K + block_size - 1) / block_size)`, same dtype as A. | required |
26
 
27
  ## Outputs
28
 
29
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
30
  | --- | --- | --- | --- | --- | --- | --- |
31
+ | `yT` | `Y` | `T1` | `2` | `[aT[0], N]` | Result of `A` multiplied by the dequantized, transposed weight matrix, with shape `(M, N)` and the same dtype as `A`. | required |
32
 
33
  ## Attributes
34
 
 
36
 
37
  | Attribute | Default | Description |
38
  | --- | --- | --- |
 
 
39
  | `K` | — | Input feature count (the shared dimension). |
40
  | `N` | — | Output feature count. |
41
  | `block_size` | — | Number of weights sharing one absmax scale; a power of two, at least 16. |
42
  | `quant_type` | — | Codebook selector: 0 = FP4, 1 = NF4. |
43
+ | `training_mode` | `0` | Whether training outputs are requested. This inference-only implementation supports the standard default value 0. |
44
+ | `transB` | `1` | Whether the quantized weight is stored transposed. This implementation supports the standard default value 1. |
45
 
46
  ## Type constraints
47
 
 
50
  | `T1` | `float32`, `float16` |
51
  | `T2` | `uint8` |
52
 
53
+ ## Implementation variants
54
+
55
+ One implementation is selected per call from the device capabilities, the request shapes and the dtypes; these notes say what each one covers.
56
+
57
+ - `sgmat_hybrid_rows` — Combines full and partial row tiles in one matrix dispatch. Complete tiles read activations directly; partial tiles stage bounded rows in f32 and reuse weight staging for output. Float16 requests widen before the multiply and narrow once afterward.
58
+ - `sgmat_hybrid_rows_widened` — Combines full and partial row tiles in one matrix dispatch. Complete tiles read activations directly; partial tiles stage bounded rows in f32 and reuse weight staging for output. Float16 requests widen before the multiply and narrow once afterward.
59
+ - `sgmat_staged_rows` — Stages partial activation rows in f32, dequantizes the shared weight tile, and reuses dead weight staging for masked output stores.
60
+ - `sgmat_widened` — Runs the subgroup-matrix tier for a float16 request by widening the activations to float32 either side of the multiply. The matrix units this operator uses accumulate in float32 from float32 operands; the device's float16 configuration returns a float16 result, so feeding them float16 directly would drop the accumulator's precision.
61
+
62
  ## Device requirements
63
 
64
  Some implementation variants require `subgroup-matrix` and `subgroups`. These are route-specific capabilities, not package-wide requirements; availability also depends on the request shape and dtype.
65
 
66
  ## Files
67
 
68
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, provenance)
69
  - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
70
  - [`test.json`](build/webgpu/test.json) — correctness cases
71
  - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
 
77
 
78
  ## Use with `@huggingface/kernels`
79
 
80
+ ```sh
81
+ npm install --save-exact @huggingface/kernels@0.0.1-preview.2
82
+ ```
83
+
84
+ Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
85
 
86
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
87
+ It follows the `v1` branch as fixes land. To pin exact artifact bytes, pass a 40-character commit `revision` instead of `version`.
88
 
89
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
90
 
build/webgpu/bench.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "com.microsoft.MatMulBnb4",
3
  "cases": [
4
  {
5
  "name": "bnb4-nf4-decode-m1-k2048-n2048-b64",
@@ -119,6 +118,288 @@
119
  "outputs": { "yT": { "shape": [512, 4096], "dtype": "float16" } },
120
  "bench": { "metrics": [{ "type": "gflops", "value": "2 * dim(shapes.aT, 0) * args.K * args.N" }] },
121
  "tunableSpace": { "PORTABLE_TILE_K": [16, 32, 64] }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  }
123
  ]
124
  }
 
1
  {
 
2
  "cases": [
3
  {
4
  "name": "bnb4-nf4-decode-m1-k2048-n2048-b64",
 
118
  "outputs": { "yT": { "shape": [512, 4096], "dtype": "float16" } },
119
  "bench": { "metrics": [{ "type": "gflops", "value": "2 * dim(shapes.aT, 0) * args.K * args.N" }] },
120
  "tunableSpace": { "PORTABLE_TILE_K": [16, 32, 64] }
121
+ },
122
+ {
123
+ "name": "bnb4-nf4-speculative-m15-k4096-n4096-b64-band",
124
+ "provenance": {
125
+ "notes": "Fifteen rows represent a speculative decoder's verification width and exercise the tiled route immediately below M=16. `nf4-tiled-speculative-band-m16-control` brackets that boundary."
126
+ },
127
+ "preset": "model",
128
+ "vars": { "M": 15, "K": 4096, "N": 4096, "blockSize": 64 },
129
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
130
+ "inputs": {
131
+ "aT": { "shape": [15, 4096], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
132
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
133
+ "absmaxT": {
134
+ "shape": [262144],
135
+ "dtype": "float32",
136
+ "dist": "uniform",
137
+ "seed": 427,
138
+ "offset": 0.04,
139
+ "scale": 0.01,
140
+ "signed": false
141
+ }
142
+ },
143
+ "outputs": { "yT": { "shape": [15, 4096], "dtype": "float32" } },
144
+ "bench": { "metrics": [{ "type": "gflops", "value": "2 * dim(shapes.aT, 0) * args.K * args.N" }] }
145
+ },
146
+ {
147
+ "name": "bnb4-nf4-speculative-m16-k4096-n4096-b64-tile-floor-control",
148
+ "preset": "model",
149
+ "vars": { "M": 16, "K": 4096, "N": 4096, "blockSize": 64 },
150
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
151
+ "inputs": {
152
+ "aT": { "shape": [16, 4096], "dtype": "float32", "dist": "normal", "seed": 428, "scale": 0.2 },
153
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
154
+ "absmaxT": {
155
+ "shape": [262144],
156
+ "dtype": "float32",
157
+ "dist": "uniform",
158
+ "seed": 429,
159
+ "offset": 0.04,
160
+ "scale": 0.01,
161
+ "signed": false
162
+ }
163
+ },
164
+ "outputs": { "yT": { "shape": [16, 4096], "dtype": "float32" } },
165
+ "bench": { "metrics": [{ "type": "gflops", "value": "2 * dim(shapes.aT, 0) * args.K * args.N" }] }
166
+ },
167
+ {
168
+ "name": "bnb4-nf4-prefill-m64-k4096-n4096-b64-control",
169
+ "preset": "model",
170
+ "vars": { "M": 64, "K": 4096, "N": 4096, "blockSize": 64 },
171
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
172
+ "inputs": {
173
+ "aT": { "shape": [64, 4096], "dtype": "float32", "dist": "normal", "seed": 430, "scale": 0.2 },
174
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
175
+ "absmaxT": {
176
+ "shape": [262144],
177
+ "dtype": "float32",
178
+ "dist": "uniform",
179
+ "seed": 431,
180
+ "offset": 0.04,
181
+ "scale": 0.01,
182
+ "signed": false
183
+ }
184
+ },
185
+ "outputs": { "yT": { "shape": [64, 4096], "dtype": "float32" } },
186
+ "bench": { "metrics": [{ "type": "gflops", "value": "2 * dim(shapes.aT, 0) * args.K * args.N" }] }
187
+ },
188
+ {
189
+ "name": "bnb4-probe-float32-q1-m8-k4096-n4096-b64",
190
+ "preset": "stress",
191
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
192
+ "inputs": {
193
+ "aT": { "shape": [8, 4096], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
194
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
195
+ "absmaxT": { "shape": [262144], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
196
+ },
197
+ "outputs": { "yT": { "shape": [8, 4096], "dtype": "float32" } },
198
+ "bench": { "metrics": [{ "type": "gflops", "value": 268435456 }] }
199
+ },
200
+ {
201
+ "name": "bnb4-probe-float32-q1-m32-k4096-n4096-b64",
202
+ "preset": "stress",
203
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
204
+ "inputs": {
205
+ "aT": { "shape": [32, 4096], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
206
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
207
+ "absmaxT": { "shape": [262144], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
208
+ },
209
+ "outputs": { "yT": { "shape": [32, 4096], "dtype": "float32" } },
210
+ "bench": { "metrics": [{ "type": "gflops", "value": 1073741824 }] }
211
+ },
212
+ {
213
+ "name": "bnb4-probe-float32-q1-m33-k4096-n4096-b64",
214
+ "preset": "stress",
215
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
216
+ "inputs": {
217
+ "aT": { "shape": [33, 4096], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
218
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
219
+ "absmaxT": { "shape": [262144], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
220
+ },
221
+ "outputs": { "yT": { "shape": [33, 4096], "dtype": "float32" } },
222
+ "bench": { "metrics": [{ "type": "gflops", "value": 1107296256 }] }
223
+ },
224
+ {
225
+ "name": "bnb4-probe-float32-q1-m65-k4096-n4096-b64",
226
+ "preset": "stress",
227
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
228
+ "inputs": {
229
+ "aT": { "shape": [65, 4096], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
230
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
231
+ "absmaxT": { "shape": [262144], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
232
+ },
233
+ "outputs": { "yT": { "shape": [65, 4096], "dtype": "float32" } },
234
+ "bench": { "metrics": [{ "type": "gflops", "value": 2181038080 }] }
235
+ },
236
+ {
237
+ "name": "bnb4-probe-float16-q1-m15-k4096-n4096-b64",
238
+ "preset": "stress",
239
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
240
+ "inputs": {
241
+ "aT": { "shape": [15, 4096], "dtype": "float16", "dist": "normal", "seed": 426, "scale": 0.2 },
242
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
243
+ "absmaxT": { "shape": [262144], "dtype": "float16", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
244
+ },
245
+ "outputs": { "yT": { "shape": [15, 4096], "dtype": "float16" } },
246
+ "bench": { "metrics": [{ "type": "gflops", "value": 503316480 }] }
247
+ },
248
+ {
249
+ "name": "bnb4-probe-float16-q1-m16-k4096-n4096-b64",
250
+ "preset": "stress",
251
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
252
+ "inputs": {
253
+ "aT": { "shape": [16, 4096], "dtype": "float16", "dist": "normal", "seed": 426, "scale": 0.2 },
254
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
255
+ "absmaxT": { "shape": [262144], "dtype": "float16", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
256
+ },
257
+ "outputs": { "yT": { "shape": [16, 4096], "dtype": "float16" } },
258
+ "bench": { "metrics": [{ "type": "gflops", "value": 536870912 }] }
259
+ },
260
+ {
261
+ "name": "bnb4-probe-float16-q1-m33-k4096-n4096-b64",
262
+ "preset": "stress",
263
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
264
+ "inputs": {
265
+ "aT": { "shape": [33, 4096], "dtype": "float16", "dist": "normal", "seed": 426, "scale": 0.2 },
266
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
267
+ "absmaxT": { "shape": [262144], "dtype": "float16", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
268
+ },
269
+ "outputs": { "yT": { "shape": [33, 4096], "dtype": "float16" } },
270
+ "bench": { "metrics": [{ "type": "gflops", "value": 1107296256 }] }
271
+ },
272
+ {
273
+ "name": "bnb4-probe-float32-q0-m16-k4096-n4096-b64",
274
+ "preset": "stress",
275
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 0 },
276
+ "inputs": {
277
+ "aT": { "shape": [16, 4096], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
278
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
279
+ "absmaxT": { "shape": [262144], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
280
+ },
281
+ "outputs": { "yT": { "shape": [16, 4096], "dtype": "float32" } },
282
+ "bench": { "metrics": [{ "type": "gflops", "value": 536870912 }] }
283
+ },
284
+ {
285
+ "name": "bnb4-probe-float32-q1-m15-k1024-n128-b64",
286
+ "preset": "stress",
287
+ "attrs": { "K": 1024, "N": 128, "block_size": 64, "quant_type": 1 },
288
+ "inputs": {
289
+ "aT": { "shape": [15, 1024], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
290
+ "bT": { "shape": [65536], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
291
+ "absmaxT": { "shape": [2048], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
292
+ },
293
+ "outputs": { "yT": { "shape": [15, 128], "dtype": "float32" } },
294
+ "bench": { "metrics": [{ "type": "gflops", "value": 3932160 }] }
295
+ },
296
+ {
297
+ "name": "bnb4-probe-float16-q1-m16-k1024-n128-b64",
298
+ "preset": "stress",
299
+ "attrs": { "K": 1024, "N": 128, "block_size": 64, "quant_type": 1 },
300
+ "inputs": {
301
+ "aT": { "shape": [16, 1024], "dtype": "float16", "dist": "normal", "seed": 426, "scale": 0.2 },
302
+ "bT": { "shape": [65536], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
303
+ "absmaxT": { "shape": [2048], "dtype": "float16", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
304
+ },
305
+ "outputs": { "yT": { "shape": [16, 128], "dtype": "float16" } },
306
+ "bench": { "metrics": [{ "type": "gflops", "value": 4194304 }] }
307
+ },
308
+ {
309
+ "name": "bnb4-probe-float32-q1-m15-k1023-n257-b64",
310
+ "preset": "stress",
311
+ "attrs": { "K": 1023, "N": 257, "block_size": 64, "quant_type": 1 },
312
+ "inputs": {
313
+ "aT": { "shape": [15, 1023], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
314
+ "bT": { "shape": [131456], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
315
+ "absmaxT": { "shape": [4108], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
316
+ },
317
+ "outputs": { "yT": { "shape": [15, 257], "dtype": "float32" } },
318
+ "bench": { "metrics": [{ "type": "gflops", "value": 7887330 }] }
319
+ },
320
+ {
321
+ "name": "bnb4-probe-float16-q1-m16-k1023-n257-b64",
322
+ "preset": "stress",
323
+ "attrs": { "K": 1023, "N": 257, "block_size": 64, "quant_type": 1 },
324
+ "inputs": {
325
+ "aT": { "shape": [16, 1023], "dtype": "float16", "dist": "normal", "seed": 426, "scale": 0.2 },
326
+ "bT": { "shape": [131456], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
327
+ "absmaxT": { "shape": [4108], "dtype": "float16", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
328
+ },
329
+ "outputs": { "yT": { "shape": [16, 257], "dtype": "float16" } },
330
+ "bench": { "metrics": [{ "type": "gflops", "value": 8413152 }] }
331
+ },
332
+ {
333
+ "name": "bnb4-probe-float32-q1-m3-k4096-n4096-b64",
334
+ "preset": "stress",
335
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
336
+ "inputs": {
337
+ "aT": { "shape": [3, 4096], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
338
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
339
+ "absmaxT": { "shape": [262144], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
340
+ },
341
+ "outputs": { "yT": { "shape": [3, 4096], "dtype": "float32" } },
342
+ "bench": { "metrics": [{ "type": "gflops", "value": 100663296 }] }
343
+ },
344
+ {
345
+ "name": "bnb4-probe-float32-q1-m129-k1024-n1024-b64",
346
+ "preset": "stress",
347
+ "attrs": { "K": 1024, "N": 1024, "block_size": 64, "quant_type": 1 },
348
+ "inputs": {
349
+ "aT": { "shape": [129, 1024], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
350
+ "bT": { "shape": [524288], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
351
+ "absmaxT": { "shape": [16384], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
352
+ },
353
+ "outputs": { "yT": { "shape": [129, 1024], "dtype": "float32" } },
354
+ "bench": { "metrics": [{ "type": "gflops", "value": 270532608 }] }
355
+ },
356
+ {
357
+ "name": "bnb4-probe-float16-q1-m191-k1024-n1024-b64",
358
+ "preset": "stress",
359
+ "attrs": { "K": 1024, "N": 1024, "block_size": 64, "quant_type": 1 },
360
+ "inputs": {
361
+ "aT": { "shape": [191, 1024], "dtype": "float16", "dist": "normal", "seed": 426, "scale": 0.2 },
362
+ "bT": { "shape": [524288], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
363
+ "absmaxT": { "shape": [16384], "dtype": "float16", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
364
+ },
365
+ "outputs": { "yT": { "shape": [191, 1024], "dtype": "float16" } },
366
+ "bench": { "metrics": [{ "type": "gflops", "value": 400556032 }] }
367
+ },
368
+ {
369
+ "name": "bnb4-probe-float16-q1-m255-k1024-n1024-b64",
370
+ "preset": "stress",
371
+ "attrs": { "K": 1024, "N": 1024, "block_size": 64, "quant_type": 1 },
372
+ "inputs": {
373
+ "aT": { "shape": [255, 1024], "dtype": "float16", "dist": "normal", "seed": 426, "scale": 0.2 },
374
+ "bT": { "shape": [524288], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
375
+ "absmaxT": { "shape": [16384], "dtype": "float16", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
376
+ },
377
+ "outputs": { "yT": { "shape": [255, 1024], "dtype": "float16" } },
378
+ "bench": { "metrics": [{ "type": "gflops", "value": 534773760 }] }
379
+ },
380
+ {
381
+ "name": "bnb4-probe-float32-q1-m255-k4096-n4096-b64",
382
+ "preset": "stress",
383
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
384
+ "inputs": {
385
+ "aT": { "shape": [255, 4096], "dtype": "float32", "dist": "normal", "seed": 426, "scale": 0.2 },
386
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
387
+ "absmaxT": { "shape": [262144], "dtype": "float32", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
388
+ },
389
+ "outputs": { "yT": { "shape": [255, 4096], "dtype": "float32" } },
390
+ "bench": { "metrics": [{ "type": "gflops", "value": 8556380160 }] }
391
+ },
392
+ {
393
+ "name": "bnb4-probe-float16-q1-m511-k4096-n4096-b64",
394
+ "preset": "stress",
395
+ "attrs": { "K": 4096, "N": 4096, "block_size": 64, "quant_type": 1 },
396
+ "inputs": {
397
+ "aT": { "shape": [511, 4096], "dtype": "float16", "dist": "normal", "seed": 426, "scale": 0.2 },
398
+ "bT": { "shape": [8388608], "dtype": "uint8", "dist": "linearMod", "mod": 256, "step": 7 },
399
+ "absmaxT": { "shape": [262144], "dtype": "float16", "dist": "uniform", "seed": 427, "min": 0.04, "max": 0.05 }
400
+ },
401
+ "outputs": { "yT": { "shape": [511, 4096], "dtype": "float16" } },
402
+ "bench": { "metrics": [{ "type": "gflops", "value": 17146314752 }] }
403
  }
404
  ]
405
  }
build/webgpu/cast-scalar-x4.wgsl.jinja CHANGED
@@ -1,27 +1,14 @@
1
- {% if usesF16 %}
2
- enable f16;
3
- {% endif %}
4
  {{ env.wgsl.resourceDeclarations }}
5
- {% if wrapNarrowInt %}
6
-
7
- // ONNX float-to-int8/uint8 narrowing wraps modulo 256 rather than saturating.
8
- // Preserve the low byte after truncation; the signed path then sign-extends it.
9
- fn cast_wrap(v: f32) -> {{ outScalar }} {
10
- let low = i32(v) & 0xFF;
11
- return {{ outScalar }}({% if wrapSigned %}select(low, low - 256, low > 127){% else %}low{% endif %});
12
- }
13
-
14
- {% endif %}
15
  @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
16
- fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
17
  // Four scalar conversions per invocation retain vector-like dispatch density even when the
18
  // logical element count is not vec4 aligned. For a vec4 bulk + scalar tail plan, only lane zero
19
  // of the tail dispatch runs and starts at the first element not covered by the packed pass.
20
- let invocation = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
21
  let base = invocation * 4u;
22
  {% for lane in range(4) %}
23
  if (base + {{ lane }}u < params.count) {
24
- y[base + {{ lane }}u] = {% if wrapNarrowInt %}cast_wrap(f32(x[base + {{ lane }}u])){% else %}{{ outScalar }}(x[base + {{ lane }}u]){% endif %};
25
  }
26
  {% endfor %}
27
  }
 
 
 
 
1
  {{ env.wgsl.resourceDeclarations }}
 
 
 
 
 
 
 
 
 
 
2
  @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
3
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4
  // Four scalar conversions per invocation retain vector-like dispatch density even when the
5
  // logical element count is not vec4 aligned. For a vec4 bulk + scalar tail plan, only lane zero
6
  // of the tail dispatch runs and starts at the first element not covered by the packed pass.
7
+ let invocation = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ tunables.WORKGROUP_SIZE }}u;
8
  let base = invocation * 4u;
9
  {% for lane in range(4) %}
10
  if (base + {{ lane }}u < params.count) {
11
+ y[base + {{ lane }}u] = {{ outScalar }}(x[base + {{ lane }}u]);
12
  }
13
  {% endfor %}
14
  }
build/webgpu/manifest.json CHANGED
@@ -2,32 +2,20 @@
2
  "domain": "com.microsoft",
3
  "name": "MatMulBnb4",
4
  "sinceVersion": 1,
5
- "description": "Computes `A @ dequant(B)^T` where `B` uses bitsandbytes 4-bit quantization: `quant_type = 0` selects FP4 and `quant_type = 1` selects NF4. Supports rank-2 float16/float32 `A`, `transB = 1`, and `training_mode = 0`; rank-1 and rank-3-or-higher `A`, bfloat16, `transB = 0`, and training are not implemented. `B` is the flattened `[N, K]` weight, two codes per byte with the even flat index in the high nibble. Each code indexes a fixed 16-entry codebook, and the value is `codebook[code] * absmax[flat_index / block_size]`.",
6
- "inputs": [
7
- { "role": "A", "dtype": "T1", "rank": 2, "description": "Float input matrix of shape `(M, K)`, not quantized." },
8
- {
9
- "role": "B",
10
- "dtype": "T2",
11
- "rank": 1,
12
- "description": "The `[N, K]` weight, flattened and quantized to 4 bits, stored as `(N * K + 1) / 2` bytes; the ONNX type is uint8 (this WebGPU implementation reads one widened u32 per stored byte)."
13
- },
14
- {
15
- "role": "absmax",
16
- "dtype": "T1",
17
- "rank": 1,
18
- "description": "Per-block absolute-maximum dequantization scales of shape `((N * K + block_size - 1) / block_size)`, same dtype as A."
19
- }
20
- ],
21
- "outputs": [
22
- {
23
- "role": "Y",
24
- "dtype": "T1",
25
- "rank": 2,
26
- "shape": "[dim(shapes.A, 0), attrs.N]",
27
- "description": "Result of `A` multiplied by the dequantized, transposed weight matrix, with shape `(M, N)` and the same dtype as `A`."
28
- }
29
- ],
30
- "attributes": { "training_mode": 0, "transB": 1 },
31
  "attributeConstraints": {
32
  "K": { "required": true },
33
  "N": { "required": true },
@@ -36,158 +24,16 @@
36
  "training_mode": { "values": [0] },
37
  "transB": { "values": [1] }
38
  },
39
- "attributeDescriptions": {
40
- "K": "Input feature count (the shared dimension).",
41
- "N": "Output feature count.",
42
- "block_size": "Number of weights sharing one absmax scale; a power of two, at least 16.",
43
- "quant_type": "Codebook selector: 0 = FP4, 1 = NF4.",
44
- "training_mode": "Whether training outputs are requested. This inference-only implementation supports the standard default value 0.",
45
- "transB": "Whether the quantized weight is stored transposed. This implementation supports the standard default value 1."
46
- },
47
  "typeConstraints": { "T1": ["float32", "float16"], "T2": ["uint8"] },
48
- "args": {
49
- "aT": { "kind": "tensor", "semantic": "A", "role": "input" },
50
- "bT": { "kind": "tensor", "semantic": "B", "role": "input" },
51
- "absmaxT": { "kind": "tensor", "semantic": "absmax", "role": "input" },
52
- "yT": { "kind": "tensor", "semantic": "Y", "role": "output" }
53
- },
54
  "tunables": {
55
- "WORKGROUP_SIZE": 64,
56
- "TILE_MIN_M": 16,
57
- "PORTABLE_TILE_K": 16,
58
- "SGMAT_TILE_ROWS": 64,
59
- "SGMAT_TALL_TILE_ROWS": 128,
60
- "SGMAT_TALL_MIN_M": 128,
61
- "SGMAT_TILE_COLS": 64,
62
- "SGMAT_TILE_K": 32
63
- },
64
- "bindingSets": {
65
- "main": [
66
- {
67
- "name": "a",
68
- "arg": "aT",
69
- "semantic": "A",
70
- "buffer": { "type": "read-only-storage" },
71
- "elementType": "$aScalar"
72
- },
73
- { "name": "b", "arg": "bT", "semantic": "B", "buffer": { "type": "read-only-storage" }, "elementType": "u32" },
74
- {
75
- "name": "absmax",
76
- "arg": "absmaxT",
77
- "semantic": "absmax",
78
- "buffer": { "type": "read-only-storage" },
79
- "elementType": "$absmaxScalar",
80
- "length": "$ABSMAX_LEN"
81
- },
82
- { "name": "y", "arg": "yT", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$aScalar" },
83
- {
84
- "name": "params",
85
- "semantic": "kernel.params",
86
- "buffer": { "type": "uniform" },
87
- "struct": {
88
- "name": "Params",
89
- "fields": [
90
- { "name": "rows", "type": "u32", "value": "dim(shapes.A, 0)" },
91
- { "name": "K", "type": "u32", "value": "attrs.K" },
92
- { "name": "N", "type": "u32", "value": "attrs.N" },
93
- { "name": "blockSize", "type": "u32", "value": "attrs.block_size" }
94
- ]
95
- }
96
- }
97
- ],
98
- "gemv": [
99
- {
100
- "name": "a",
101
- "arg": "aT",
102
- "semantic": "A",
103
- "buffer": { "type": "read-only-storage" },
104
- "elementType": "$aScalar"
105
- },
106
- { "name": "b", "arg": "bT", "semantic": "B", "buffer": { "type": "read-only-storage" }, "elementType": "u32" },
107
- {
108
- "name": "absmax",
109
- "arg": "absmaxT",
110
- "semantic": "absmax",
111
- "buffer": { "type": "read-only-storage" },
112
- "elementType": "$absmaxScalar",
113
- "length": "$ABSMAX_LEN"
114
- },
115
- { "name": "y", "arg": "yT", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$aScalar" },
116
- {
117
- "name": "params",
118
- "semantic": "kernel.params",
119
- "buffer": { "type": "uniform" },
120
- "struct": {
121
- "name": "Params",
122
- "fields": [
123
- { "name": "K", "type": "u32", "value": "attrs.K" },
124
- { "name": "N", "type": "u32", "value": "attrs.N" },
125
- { "name": "blockSize", "type": "u32", "value": "attrs.block_size" }
126
- ]
127
- }
128
- }
129
- ],
130
- "sgmat": [
131
- {
132
- "name": "a",
133
- "arg": "aT",
134
- "semantic": "A",
135
- "buffer": { "type": "read-only-storage" },
136
- "elementType": "$aScalar"
137
- },
138
- { "name": "b", "arg": "bT", "semantic": "B", "buffer": { "type": "read-only-storage" }, "elementType": "u32" },
139
- {
140
- "name": "absmax",
141
- "arg": "absmaxT",
142
- "semantic": "absmax",
143
- "buffer": { "type": "read-only-storage" },
144
- "elementType": "$absmaxScalar",
145
- "length": "$ABSMAX_LEN"
146
- },
147
- { "name": "y", "arg": "yT", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$aScalar" }
148
- ],
149
- "castA": [
150
- {
151
- "name": "x",
152
- "arg": "aT",
153
- "semantic": "A",
154
- "buffer": { "type": "read-only-storage" },
155
- "elementType": "$srcScalar"
156
- },
157
- { "name": "y", "semantic": "aF32", "buffer": { "type": "storage" }, "elementType": "f32" },
158
- {
159
- "name": "params",
160
- "semantic": "kernel.params",
161
- "buffer": { "type": "uniform" },
162
- "struct": { "name": "Params", "fields": [{ "name": "count", "type": "u32", "value": "numel(shapes.A)" }] }
163
- }
164
- ],
165
- "sgmatWiden": [
166
- { "name": "a", "semantic": "aF32", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
167
- { "name": "b", "arg": "bT", "semantic": "B", "buffer": { "type": "read-only-storage" }, "elementType": "u32" },
168
- {
169
- "name": "absmax",
170
- "arg": "absmaxT",
171
- "semantic": "absmax",
172
- "buffer": { "type": "read-only-storage" },
173
- "elementType": "$absmaxScalar",
174
- "length": "$ABSMAX_LEN"
175
- },
176
- { "name": "y", "semantic": "yF32", "buffer": { "type": "storage" }, "elementType": "f32" }
177
- ],
178
- "castY": [
179
- { "name": "x", "semantic": "yF32", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
180
- { "name": "y", "arg": "yT", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$srcScalar" },
181
- {
182
- "name": "params",
183
- "semantic": "kernel.params",
184
- "buffer": { "type": "uniform" },
185
- "struct": {
186
- "name": "Params",
187
- "fields": [{ "name": "count", "type": "u32", "value": "dim(shapes.A, 0) * attrs.N" }]
188
- }
189
- }
190
- ]
191
  },
192
  "derive": {
193
  "deviceWorkgroupCap": "min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)",
@@ -195,67 +41,293 @@
195
  "canPinSubgroupSize32": "device.features.has(\"subgroups\") and device.features.has(\"subgroup-size-control\") and has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize <= 32 and device.adapterInfo.subgroupMaxSize >= 32",
196
  "pinSubgroupSize32": "canPinSubgroupSize32 and not wave32Adapter",
197
  "wave32Effective": "wave32Adapter or pinSubgroupSize32",
 
198
  "packedBytesExpected": "ceilDiv(attrs.N * attrs.K, 2)",
199
  "absmaxCountExpected": "ceilDiv(attrs.N * attrs.K, attrs.block_size)",
200
- "aFloatOk": "(tensorDtypes.A == \"float32\" or tensorDtypes.A == \"float16\") and f16Ok(tensorDtypes.A)",
201
  "portableWorkgroupSize": "min(tunables.WORKGROUP_SIZE, deviceWorkgroupCap)",
202
- "commonShapeValid": "ranks.A == 2 and ranks.B == 1 and ranks.absmax == 1 and ranks.Y == 2 and aFloatOk and tensorDtypes.B == \"uint8\" and tensorDtypes.absmax == tensorDtypes.A and tensorDtypes.Y == tensorDtypes.A and attrs.K > 0 and attrs.N > 0 and attrs.block_size >= 16 and pow2ceil(attrs.block_size) == attrs.block_size and dim(shapes.A, 1) == attrs.K and dim(shapes.B, 0) == packedBytesExpected and dim(shapes.absmax, 0) == absmaxCountExpected and dim(shapes.Y, 0) == dim(shapes.A, 0) and dim(shapes.Y, 1) == attrs.N",
203
- "gemvShapeValid": "commonShapeValid and dim(shapes.A, 0) == 1",
204
  "portableWorkgroupFits": "portableWorkgroupSize > 0 and portableWorkgroupSize * 16 <= device.limits.maxComputeWorkgroupStorageSize",
205
  "portableTileKValid": "tunables.PORTABLE_TILE_K >= 8 and tunables.PORTABLE_TILE_K % 8 == 0",
206
- "tileEligible": "commonShapeValid and dim(shapes.A, 0) >= tunables.TILE_MIN_M and portableTileKValid",
207
- "tileWorkgroupStorageBytes": "8 * 64 * tunables.PORTABLE_TILE_K",
208
- "tileWorkgroupFits": "16 <= device.limits.maxComputeWorkgroupSizeX and 8 <= device.limits.maxComputeWorkgroupSizeY and 128 <= device.limits.maxComputeInvocationsPerWorkgroup and tileWorkgroupStorageBytes <= device.limits.maxComputeWorkgroupStorageSize and ceilDiv(attrs.N, 64) <= device.limits.maxComputeWorkgroupsPerDimension and ceilDiv(dim(shapes.A, 0), 64) <= device.limits.maxComputeWorkgroupsPerDimension",
209
  "sgmatMatrixSize": "8",
210
- "sgmatTileRows": "tunables.SGMAT_TALL_TILE_ROWS if dim(shapes.A, 0) >= tunables.SGMAT_TALL_MIN_M else tunables.SGMAT_TILE_ROWS",
211
  "sgmatRowSubtiles": "4",
212
  "sgmatSubRows": "sgmatTileRows / sgmatRowSubtiles",
213
  "sgmatSubCols": "4 * sgmatMatrixSize",
214
  "sgmatLoadWidth": "sgmatMatrixSize",
215
  "sgmatColSubtiles": "tunables.SGMAT_TILE_COLS / sgmatSubCols",
216
  "sgmatNumSubgroups": "sgmatRowSubtiles * sgmatColSubtiles",
217
- "sgmatSubgroupSize": "device.adapterInfo.subgroupMinSize if has(device.adapterInfo, \"subgroupMinSize\") else 1",
218
  "sgmatWorkgroupSize": "sgmatNumSubgroups * sgmatSubgroupSize",
219
  "sgmatBLoadsPerRow": "tunables.SGMAT_TILE_K / sgmatLoadWidth",
220
  "sgmatWorkgroupStorageBytes": "4 * tunables.SGMAT_TILE_COLS * tunables.SGMAT_TILE_K",
221
  "sgmatDispatchN": "ceilDiv(attrs.N, tunables.SGMAT_TILE_COLS)",
222
- "sgmatDispatchM": "ceilDiv(dim(shapes.A, 0), sgmatTileRows)",
223
- "sgmatWorkgroupFits": "sgmatWorkgroupSize <= deviceWorkgroupCap and sgmatWorkgroupStorageBytes <= device.limits.maxComputeWorkgroupStorageSize and sgmatDispatchN <= device.limits.maxComputeWorkgroupsPerDimension and sgmatDispatchM <= device.limits.maxComputeWorkgroupsPerDimension",
224
- "sgmatWidenBytes": "numel(shapes.A) * 4",
225
- "sgmatWidenOutBytes": "dim(shapes.A, 0) * attrs.N * 4",
226
- "sgmatWidenFits": "sgmatWidenBytes <= device.limits.maxStorageBufferBindingSize and sgmatWidenBytes <= device.limits.maxBufferSize and sgmatWidenOutBytes <= device.limits.maxStorageBufferBindingSize and sgmatWidenOutBytes <= device.limits.maxBufferSize"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  },
228
- "constants": { "quantType": "attrs.quant_type", "ABSMAX_LEN": "ceilDiv(attrs.N * attrs.K, attrs.block_size)" },
229
  "variants": [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  {
231
  "id": "gemv",
232
  "priority": 20,
233
  "when": ["gemvShapeValid", "portableWorkgroupFits"],
234
- "constants": {
235
  "workgroupSize": "portableWorkgroupSize",
236
- "aScalar": "\"f16\" if tensorDtypes.A == \"float16\" else \"f32\"",
237
- "usesF16": "tensorDtypes.A == \"float16\"",
238
- "absmaxScalar": "\"f16\" if tensorDtypes.absmax == \"float16\" else \"f32\""
239
  },
240
  "passes": [
241
  {
242
  "id": "main",
243
  "shader": "matmul-bnb4-gemv.wgsl.jinja",
244
- "bindings": "gemv",
245
- "dispatch": { "workgroups": "attrs.N" }
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
247
  ]
248
  },
249
  {
250
  "id": "sgmat",
251
  "priority": 15,
 
252
  "requires": {
253
  "features": ["subgroups", "chromium-experimental-subgroup-matrix"],
254
  "limits": { "maxComputeWorkgroupStorageSize": 8192 },
255
  "subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
256
  },
257
- "when": ["commonShapeValid", "tensorDtypes.A == \"float32\"", "dim(shapes.A, 0) >= sgmatTileRows", "dim(shapes.A, 0) % sgmatTileRows == 0", "attrs.N % tunables.SGMAT_TILE_COLS == 0", "attrs.K % tunables.SGMAT_TILE_K == 0", "attrs.K % attrs.block_size == 0", "attrs.block_size % sgmatLoadWidth == 0", "wave32Effective", "sgmatWorkgroupFits"],
258
- "constants": {
259
  "K": "attrs.K",
260
  "N": "attrs.N",
261
  "blockSize": "attrs.block_size",
@@ -273,13 +345,13 @@
273
  "bLoadsPerRow": "sgmatBLoadsPerRow",
274
  "aScalar": "\"f32\"",
275
  "usesF16": false,
276
- "absmaxScalar": "\"f16\" if tensorDtypes.absmax == \"float16\" else \"f32\""
277
  },
278
  "passes": [
279
  {
280
  "id": "main",
281
  "shader": "matmul-bnb4-sgmat.wgsl.jinja",
282
- "bindings": "sgmat",
283
  "dispatch": { "x": "sgmatDispatchN", "y": "sgmatDispatchM" }
284
  }
285
  ]
@@ -287,13 +359,13 @@
287
  {
288
  "id": "sgmat_widened",
289
  "priority": 16,
 
290
  "requires": {
291
  "features": ["subgroups", "chromium-experimental-subgroup-matrix"],
292
  "limits": { "maxComputeWorkgroupStorageSize": 8192 },
293
  "subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
294
  },
295
- "when": ["commonShapeValid", "tensorDtypes.A == \"float16\"", "dim(shapes.A, 0) >= sgmatTileRows", "dim(shapes.A, 0) % sgmatTileRows == 0", "attrs.N % tunables.SGMAT_TILE_COLS == 0", "attrs.K % tunables.SGMAT_TILE_K == 0", "attrs.K % attrs.block_size == 0", "attrs.block_size % sgmatLoadWidth == 0", "wave32Effective", "sgmatWorkgroupFits", "sgmatWidenFits"],
296
- "constants": {
297
  "K": "attrs.K",
298
  "N": "attrs.N",
299
  "blockSize": "attrs.block_size",
@@ -311,61 +383,79 @@
311
  "bLoadsPerRow": "sgmatBLoadsPerRow",
312
  "aScalar": "\"f32\"",
313
  "usesF16": true,
314
- "absmaxScalar": "\"f16\" if tensorDtypes.absmax == \"float16\" else \"f32\"",
315
  "srcScalar": "\"f16\"",
316
  "outScalar": "\"f32\"",
317
  "wrapNarrowInt": false,
318
  "wrapSigned": false
319
  },
 
 
 
 
320
  "passes": [
321
  {
322
  "id": "widen_a",
323
  "name": "MatMulBnb4.WidenActivations",
324
  "shader": "cast-scalar-x4.wgsl.jinja",
325
- "bindings": "castA",
326
- "dispatch": { "threads": "ceilDiv(numel(shapes.A), 4)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
 
 
 
 
 
 
 
 
327
  },
328
  {
329
  "id": "main",
330
  "name": "MatMulBnb4.SubgroupMatrixWidened",
331
  "shader": "matmul-bnb4-sgmat.wgsl.jinja",
332
- "bindings": "sgmatWiden",
 
 
 
 
 
333
  "dispatch": { "x": "sgmatDispatchN", "y": "sgmatDispatchM" }
334
  },
335
  {
336
  "id": "narrow_y",
337
  "name": "MatMulBnb4.NarrowOutput",
338
  "shader": "cast-scalar-x4.wgsl.jinja",
339
- "bindings": "castY",
340
- "constants": { "outScalar": "\"f16\"" },
 
 
 
 
341
  "dispatch": {
342
- "threads": "ceilDiv(dim(shapes.A, 0) * attrs.N, 4)",
343
- "workgroupSize": "tunables.WORKGROUP_SIZE"
 
344
  }
345
  }
346
- ],
347
- "description": "Runs the subgroup-matrix tier for a float16 request by widening the activations to float32 either side of the multiply. The matrix units this operator uses accumulate in float32 from float32 operands; the device's float16 configuration returns a float16 result, so feeding them float16 directly would drop the accumulator's precision.",
348
- "intermediates": [
349
- { "id": "aF32", "dtype": "float32", "shape": "[numel(shapes.A)]" },
350
- { "id": "yF32", "dtype": "float32", "shape": "[dim(shapes.A, 0) * attrs.N]" }
351
  ]
352
  },
353
  {
354
  "id": "tiled",
355
  "priority": 10,
356
  "when": ["tileEligible", "tileWorkgroupFits"],
357
- "constants": {
358
  "tileK": "tunables.PORTABLE_TILE_K",
359
- "aScalar": "\"f16\" if tensorDtypes.A == \"float16\" else \"f32\"",
360
- "usesF16": "tensorDtypes.A == \"float16\"",
361
- "absmaxScalar": "\"f16\" if tensorDtypes.absmax == \"float16\" else \"f32\""
 
362
  },
363
  "passes": [
364
  {
365
  "id": "main",
366
  "shader": "matmul-bnb4-tiled.wgsl.jinja",
367
- "bindings": "main",
368
- "dispatch": { "x": "ceilDiv(attrs.N, 64)", "y": "ceilDiv(dim(shapes.A, 0), 64)" }
369
  }
370
  ]
371
  },
@@ -373,18 +463,22 @@
373
  "id": "scalar",
374
  "priority": 0,
375
  "when": ["commonShapeValid", "portableWorkgroupSize > 0"],
376
- "constants": {
377
  "workgroupSize": "portableWorkgroupSize",
378
- "aScalar": "\"f16\" if tensorDtypes.A == \"float16\" else \"f32\"",
379
- "usesF16": "tensorDtypes.A == \"float16\"",
380
- "absmaxScalar": "\"f16\" if tensorDtypes.absmax == \"float16\" else \"f32\""
381
  },
382
  "passes": [
383
  {
384
  "id": "main",
385
  "shader": "matmul-bnb4.wgsl.jinja",
386
- "bindings": "main",
387
- "dispatch": { "threads": "numel(shapes.Y)", "workgroupSize": "constants.workgroupSize" }
 
 
 
 
388
  }
389
  ]
390
  }
 
2
  "domain": "com.microsoft",
3
  "name": "MatMulBnb4",
4
  "sinceVersion": 1,
5
+ "inputs": {
6
+ "aT": { "onnx": "A", "dtype": "T1", "rank": 2 },
7
+ "bT": { "onnx": "B", "dtype": "T2", "rank": 1 },
8
+ "absmaxT": { "onnx": "absmax", "dtype": "T1", "rank": 1 }
9
+ },
10
+ "outputs": { "yT": { "onnx": "Y", "dtype": "T1", "rank": 2, "shape": "[dim(shapes.aT, 0), attrs.N]" } },
11
+ "attributes": {
12
+ "training_mode": { "default": 0 },
13
+ "transB": { "default": 1 },
14
+ "K": {},
15
+ "N": {},
16
+ "block_size": {},
17
+ "quant_type": {}
18
+ },
 
 
 
 
 
 
 
 
 
 
 
 
19
  "attributeConstraints": {
20
  "K": { "required": true },
21
  "N": { "required": true },
 
24
  "training_mode": { "values": [0] },
25
  "transB": { "values": [1] }
26
  },
 
 
 
 
 
 
 
 
27
  "typeConstraints": { "T1": ["float32", "float16"], "T2": ["uint8"] },
 
 
 
 
 
 
28
  "tunables": {
29
+ "WORKGROUP_SIZE": { "default": 64 },
30
+ "TILE_MIN_M": { "default": 4 },
31
+ "PORTABLE_TILE_K": { "default": 16 },
32
+ "SGMAT_TILE_ROWS": { "default": 64 },
33
+ "SGMAT_TALL_TILE_ROWS": { "default": 128 },
34
+ "SGMAT_TALL_MIN_M": { "default": 128 },
35
+ "SGMAT_TILE_COLS": { "default": 64 },
36
+ "SGMAT_TILE_K": { "default": 32 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  },
38
  "derive": {
39
  "deviceWorkgroupCap": "min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)",
 
41
  "canPinSubgroupSize32": "device.features.has(\"subgroups\") and device.features.has(\"subgroup-size-control\") and has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize <= 32 and device.adapterInfo.subgroupMaxSize >= 32",
42
  "pinSubgroupSize32": "canPinSubgroupSize32 and not wave32Adapter",
43
  "wave32Effective": "wave32Adapter or pinSubgroupSize32",
44
+ "portableTileRows": "8 * min(8, max(1, ceilDiv(dim(shapes.aT, 0), 8)))",
45
  "packedBytesExpected": "ceilDiv(attrs.N * attrs.K, 2)",
46
  "absmaxCountExpected": "ceilDiv(attrs.N * attrs.K, attrs.block_size)",
47
+ "aFloatOk": "(tensorDtypes.aT == \"float32\" or tensorDtypes.aT == \"float16\") and f16Ok(tensorDtypes.aT)",
48
  "portableWorkgroupSize": "min(tunables.WORKGROUP_SIZE, deviceWorkgroupCap)",
49
+ "commonShapeValid": "ranks.aT == 2 and ranks.bT == 1 and ranks.absmaxT == 1 and ranks.yT == 2 and aFloatOk and tensorDtypes.bT == \"uint8\" and tensorDtypes.absmaxT == tensorDtypes.aT and tensorDtypes.yT == tensorDtypes.aT and attrs.K > 0 and attrs.N > 0 and attrs.block_size >= 16 and pow2ceil(attrs.block_size) == attrs.block_size and dim(shapes.aT, 1) == attrs.K and dim(shapes.bT, 0) == packedBytesExpected and dim(shapes.absmaxT, 0) == absmaxCountExpected and dim(shapes.yT, 0) == dim(shapes.aT, 0) and dim(shapes.yT, 1) == attrs.N",
50
+ "gemvShapeValid": "commonShapeValid and dim(shapes.aT, 0) == 1",
51
  "portableWorkgroupFits": "portableWorkgroupSize > 0 and portableWorkgroupSize * 16 <= device.limits.maxComputeWorkgroupStorageSize",
52
  "portableTileKValid": "tunables.PORTABLE_TILE_K >= 8 and tunables.PORTABLE_TILE_K % 8 == 0",
53
+ "tileEligible": "commonShapeValid and dim(shapes.aT, 0) >= tunables.TILE_MIN_M and portableTileKValid",
54
+ "tileWorkgroupStorageBytes": "(portableTileRows * dtypeBytes(tensorDtypes.aT) + 64 * 4) * tunables.PORTABLE_TILE_K",
55
+ "tileWorkgroupFits": "16 <= device.limits.maxComputeWorkgroupSizeX and 8 <= device.limits.maxComputeWorkgroupSizeY and 128 <= device.limits.maxComputeInvocationsPerWorkgroup and tileWorkgroupStorageBytes <= device.limits.maxComputeWorkgroupStorageSize and ceilDiv(attrs.N, 64) <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535) and ceilDiv(dim(shapes.aT, 0), portableTileRows) <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)",
56
  "sgmatMatrixSize": "8",
57
+ "sgmatTileRows": "tunables.SGMAT_TALL_TILE_ROWS if dim(shapes.aT, 0) >= tunables.SGMAT_TALL_MIN_M else tunables.SGMAT_TILE_ROWS",
58
  "sgmatRowSubtiles": "4",
59
  "sgmatSubRows": "sgmatTileRows / sgmatRowSubtiles",
60
  "sgmatSubCols": "4 * sgmatMatrixSize",
61
  "sgmatLoadWidth": "sgmatMatrixSize",
62
  "sgmatColSubtiles": "tunables.SGMAT_TILE_COLS / sgmatSubCols",
63
  "sgmatNumSubgroups": "sgmatRowSubtiles * sgmatColSubtiles",
64
+ "sgmatSubgroupSize": "32",
65
  "sgmatWorkgroupSize": "sgmatNumSubgroups * sgmatSubgroupSize",
66
  "sgmatBLoadsPerRow": "tunables.SGMAT_TILE_K / sgmatLoadWidth",
67
  "sgmatWorkgroupStorageBytes": "4 * tunables.SGMAT_TILE_COLS * tunables.SGMAT_TILE_K",
68
  "sgmatDispatchN": "ceilDiv(attrs.N, tunables.SGMAT_TILE_COLS)",
69
+ "sgmatDispatchM": "ceilDiv(dim(shapes.aT, 0), sgmatTileRows)",
70
+ "sgmatWorkgroupFits": "sgmatWorkgroupSize <= deviceWorkgroupCap and sgmatWorkgroupStorageBytes <= device.limits.maxComputeWorkgroupStorageSize and sgmatDispatchN <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535) and sgmatDispatchM <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)",
71
+ "sgmatWidenBytes": "numel(shapes.aT) * 4",
72
+ "sgmatWidenOutBytes": "dim(shapes.aT, 0) * attrs.N * 4",
73
+ "sgmatWidenFits": "sgmatWidenBytes <= device.limits.maxStorageBufferBindingSize and sgmatWidenBytes <= device.limits.maxBufferSize and sgmatWidenOutBytes <= device.limits.maxStorageBufferBindingSize and sgmatWidenOutBytes <= device.limits.maxBufferSize",
74
+ "quantType": "attrs.quant_type",
75
+ "ABSMAX_LEN": "ceilDiv(attrs.N * attrs.K, attrs.block_size)",
76
+ "stagedGeometryValid": "tunables.SGMAT_TILE_COLS >= sgmatSubCols and tunables.SGMAT_TILE_COLS % sgmatSubCols == 0 and tunables.SGMAT_TILE_K >= sgmatMatrixSize and tunables.SGMAT_TILE_K % sgmatMatrixSize == 0",
77
+ "stagedRowSubtiles": "max(1, min(sgmatRowSubtiles, pow2ceil(ceilDiv(dim(shapes.aT, 0), sgmatMatrixSize)), floor(deviceWorkgroupCap / (32 * max(1, sgmatColSubtiles))), floor(tunables.SGMAT_TILE_K / sgmatMatrixSize), floor((device.limits.maxComputeWorkgroupStorageSize - sgmatWorkgroupStorageBytes) / (4 * sgmatMatrixSize * max(1, tunables.SGMAT_TILE_K)))))",
78
+ "stagedTileRows": "stagedRowSubtiles * sgmatMatrixSize",
79
+ "stagedLoadWorkgroupTarget": "max(1, min(deviceWorkgroupCap, tunables.SGMAT_TILE_COLS * tunables.SGMAT_TILE_K / sgmatLoadWidth))",
80
+ "stagedColumnMatrices": "min(4, pow2ceil(max(1, ceilDiv(stagedRowSubtiles * tunables.SGMAT_TILE_COLS * 32, stagedLoadWorkgroupTarget * sgmatMatrixSize))))",
81
+ "stagedSubCols": "stagedColumnMatrices * sgmatMatrixSize",
82
+ "stagedWorkgroupSize": "stagedRowSubtiles * (tunables.SGMAT_TILE_COLS / stagedSubCols) * 32",
83
+ "stagedStorageBytes": "4 * (stagedTileRows + tunables.SGMAT_TILE_COLS) * tunables.SGMAT_TILE_K",
84
+ "stagedResourcesFit": "stagedWorkgroupSize <= deviceWorkgroupCap and stagedStorageBytes <= device.limits.maxComputeWorkgroupStorageSize and sgmatDispatchN <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535) and ceilDiv(dim(shapes.aT, 0), stagedTileRows) <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)",
85
+ "sgmatGeometryValid": "tunables.SGMAT_TILE_COLS >= sgmatSubCols and tunables.SGMAT_TILE_COLS % sgmatSubCols == 0 and tunables.SGMAT_TILE_K >= sgmatMatrixSize and tunables.SGMAT_TILE_K % sgmatMatrixSize == 0 and sgmatTileRows >= sgmatRowSubtiles * sgmatMatrixSize and sgmatTileRows % (sgmatRowSubtiles * sgmatMatrixSize) == 0",
86
+ "prefixTileRows": "tunables.SGMAT_TILE_ROWS",
87
+ "sgmatFullRows": "floor(dim(shapes.aT, 0) / max(1, prefixTileRows)) * prefixTileRows",
88
+ "sgmatTailRows": "dim(shapes.aT, 0) - sgmatFullRows",
89
+ "tailGeometryValid": "tunables.SGMAT_TILE_COLS >= sgmatSubCols and tunables.SGMAT_TILE_COLS % sgmatSubCols == 0 and tunables.SGMAT_TILE_K >= sgmatMatrixSize and tunables.SGMAT_TILE_K % sgmatMatrixSize == 0",
90
+ "tailRowSubtiles": "max(1, min(sgmatRowSubtiles, pow2ceil(ceilDiv(sgmatTailRows, sgmatMatrixSize)), floor(deviceWorkgroupCap / (32 * max(1, sgmatColSubtiles))), floor(tunables.SGMAT_TILE_K / sgmatMatrixSize), floor((device.limits.maxComputeWorkgroupStorageSize - sgmatWorkgroupStorageBytes) / (4 * sgmatMatrixSize * max(1, tunables.SGMAT_TILE_K)))))",
91
+ "prefixGeometryValid": "tunables.SGMAT_TILE_COLS >= sgmatSubCols and tunables.SGMAT_TILE_COLS % sgmatSubCols == 0 and tunables.SGMAT_TILE_K >= sgmatMatrixSize and tunables.SGMAT_TILE_K % sgmatMatrixSize == 0 and prefixTileRows >= sgmatRowSubtiles * sgmatMatrixSize and prefixTileRows % (sgmatRowSubtiles * sgmatMatrixSize) == 0",
92
+ "prefixResourcesFit": "sgmatWorkgroupFits and ceilDiv(sgmatFullRows, max(1, prefixTileRows)) <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)",
93
+ "hybridTailRowSubtiles": "pow2ceil(tailRowSubtiles) / (2 if pow2ceil(tailRowSubtiles) > tailRowSubtiles else 1)",
94
+ "hybridTailTileRows": "hybridTailRowSubtiles * sgmatMatrixSize",
95
+ "hybridTailSubCols": "sgmatSubCols * hybridTailRowSubtiles / sgmatRowSubtiles",
96
+ "hybridStorageBytes": "4 * (tunables.SGMAT_TILE_COLS + hybridTailTileRows) * tunables.SGMAT_TILE_K",
97
+ "hybridDispatchRows": "sgmatFullRows / max(1, prefixTileRows) + ceilDiv(sgmatTailRows, hybridTailTileRows)",
98
+ "hybridResourcesFit": "prefixResourcesFit and hybridStorageBytes <= device.limits.maxComputeWorkgroupStorageSize and hybridDispatchRows <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)"
99
+ },
100
+ "bindings": {
101
+ "a": { "arg": "aT", "buffer": "read-only-storage", "elementType": "$aScalar" },
102
+ "b": { "arg": "bT", "buffer": "read-only-storage", "elementType": "u32" },
103
+ "absmax": {
104
+ "arg": "absmaxT",
105
+ "buffer": "read-only-storage",
106
+ "elementType": "$absmaxScalar",
107
+ "length": "$ABSMAX_LEN"
108
+ },
109
+ "y": { "arg": "yT", "buffer": "storage", "elementType": "$aScalar" },
110
+ "params": {
111
+ "buffer": "uniform",
112
+ "struct": [
113
+ { "name": "rows", "type": "u32", "value": "dim(shapes.aT, 0)" },
114
+ { "name": "K", "type": "u32", "value": "attrs.K" },
115
+ { "name": "N", "type": "u32", "value": "attrs.N" },
116
+ { "name": "blockSize", "type": "u32", "value": "attrs.block_size" }
117
+ ]
118
+ }
119
  },
 
120
  "variants": [
121
+ {
122
+ "id": "sgmat_hybrid_rows",
123
+ "priority": 21,
124
+ "when": ["prefixGeometryValid", "commonShapeValid", "tensorDtypes.aT == \"float32\"", "attrs.N % tunables.SGMAT_TILE_COLS == 0", "attrs.K % tunables.SGMAT_TILE_K == 0", "attrs.K % attrs.block_size == 0", "attrs.block_size % sgmatLoadWidth == 0", "wave32Effective", "prefixResourcesFit", "sgmatFullRows > 0", "sgmatTailRows > 0", "tailGeometryValid", "hybridResourcesFit"],
125
+ "requires": {
126
+ "features": ["subgroups", "chromium-experimental-subgroup-matrix"],
127
+ "limits": { "maxComputeWorkgroupStorageSize": 8192 },
128
+ "subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
129
+ },
130
+ "derive": {
131
+ "K": "attrs.K",
132
+ "N": "attrs.N",
133
+ "blockSize": "attrs.block_size",
134
+ "tileRows": "prefixTileRows",
135
+ "tileCols": "tunables.SGMAT_TILE_COLS",
136
+ "tileK": "tunables.SGMAT_TILE_K",
137
+ "subRows": "prefixTileRows / sgmatRowSubtiles",
138
+ "subCols": "sgmatSubCols",
139
+ "matrixSize": "sgmatMatrixSize",
140
+ "rowMatrices": "prefixTileRows / (sgmatRowSubtiles * sgmatMatrixSize)",
141
+ "colMatrices": "sgmatSubCols / sgmatMatrixSize",
142
+ "loadWidth": "sgmatLoadWidth",
143
+ "rowSubtiles": "sgmatRowSubtiles",
144
+ "workgroupSize": "sgmatWorkgroupSize",
145
+ "bLoadsPerRow": "sgmatBLoadsPerRow",
146
+ "aScalar": "\"f32\"",
147
+ "usesF16": false,
148
+ "absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
149
+ "hybridRows": true,
150
+ "rowCount": "dim(shapes.aT, 0)",
151
+ "fullDispatchRows": "sgmatFullRows / prefixTileRows",
152
+ "rowOffset": "sgmatFullRows"
153
+ },
154
+ "passes": [
155
+ {
156
+ "id": "main",
157
+ "shader": "matmul-bnb4-sgmat.wgsl.jinja",
158
+ "bindings": ["a", "b", "absmax", "y"],
159
+ "dispatch": { "x": "sgmatDispatchN", "y": "hybridDispatchRows" }
160
+ }
161
+ ]
162
+ },
163
+ {
164
+ "id": "sgmat_hybrid_rows_widened",
165
+ "priority": 21,
166
+ "when": ["prefixGeometryValid", "commonShapeValid", "tensorDtypes.aT == \"float16\"", "attrs.N % tunables.SGMAT_TILE_COLS == 0", "attrs.K % tunables.SGMAT_TILE_K == 0", "attrs.K % attrs.block_size == 0", "attrs.block_size % sgmatLoadWidth == 0", "wave32Effective", "prefixResourcesFit", "sgmatWidenFits", "sgmatFullRows > 0", "sgmatTailRows > 0", "tailGeometryValid", "hybridResourcesFit"],
167
+ "requires": {
168
+ "features": ["subgroups", "chromium-experimental-subgroup-matrix"],
169
+ "limits": { "maxComputeWorkgroupStorageSize": 8192 },
170
+ "subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
171
+ },
172
+ "derive": {
173
+ "K": "attrs.K",
174
+ "N": "attrs.N",
175
+ "blockSize": "attrs.block_size",
176
+ "tileRows": "prefixTileRows",
177
+ "tileCols": "tunables.SGMAT_TILE_COLS",
178
+ "tileK": "tunables.SGMAT_TILE_K",
179
+ "subRows": "prefixTileRows / sgmatRowSubtiles",
180
+ "subCols": "sgmatSubCols",
181
+ "matrixSize": "sgmatMatrixSize",
182
+ "rowMatrices": "prefixTileRows / (sgmatRowSubtiles * sgmatMatrixSize)",
183
+ "colMatrices": "sgmatSubCols / sgmatMatrixSize",
184
+ "loadWidth": "sgmatLoadWidth",
185
+ "rowSubtiles": "sgmatRowSubtiles",
186
+ "workgroupSize": "sgmatWorkgroupSize",
187
+ "bLoadsPerRow": "sgmatBLoadsPerRow",
188
+ "aScalar": "\"f32\"",
189
+ "usesF16": true,
190
+ "absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
191
+ "srcScalar": "\"f16\"",
192
+ "outScalar": "\"f32\"",
193
+ "wrapNarrowInt": false,
194
+ "wrapSigned": false,
195
+ "hybridRows": true,
196
+ "rowCount": "dim(shapes.aT, 0)",
197
+ "fullDispatchRows": "sgmatFullRows / prefixTileRows",
198
+ "rowOffset": "sgmatFullRows"
199
+ },
200
+ "intermediates": [
201
+ { "id": "aF32", "dtype": "float32", "shape": "[numel(shapes.aT)]" },
202
+ { "id": "yF32", "dtype": "float32", "shape": "[numel(shapes.yT)]" }
203
+ ],
204
+ "passes": [
205
+ {
206
+ "id": "widen_a",
207
+ "name": "MatMulBnb4.WidenActivations",
208
+ "shader": "cast-scalar-x4.wgsl.jinja",
209
+ "bindings": [
210
+ { "arg": "aT", "name": "x", "elementType": "$srcScalar" },
211
+ { "scratch": "aF32", "name": "y", "elementType": "f32" },
212
+ { "name": "params", "struct": [{ "name": "count", "type": "u32", "value": "numel(shapes.aT)" }] }
213
+ ],
214
+ "dispatch": {
215
+ "x": "min(ceilDiv((ceilDiv(numel(shapes.aT), 4)), (tunables.WORKGROUP_SIZE)), 65535)",
216
+ "y": "ceilDiv(ceilDiv((ceilDiv(numel(shapes.aT), 4)), (tunables.WORKGROUP_SIZE)), 65535)",
217
+ "z": 1
218
+ }
219
+ },
220
+ {
221
+ "id": "main",
222
+ "name": "MatMulBnb4.SubgroupMatrixWidened",
223
+ "shader": "matmul-bnb4-sgmat.wgsl.jinja",
224
+ "bindings": [
225
+ { "scratch": "aF32", "name": "a", "buffer": "read-only-storage", "elementType": "f32" },
226
+ "b",
227
+ "absmax",
228
+ { "scratch": "yF32", "name": "y", "elementType": "f32" }
229
+ ],
230
+ "dispatch": { "x": "sgmatDispatchN", "y": "hybridDispatchRows" }
231
+ },
232
+ {
233
+ "id": "narrow_y",
234
+ "name": "MatMulBnb4.NarrowOutput",
235
+ "shader": "cast-scalar-x4.wgsl.jinja",
236
+ "derive": { "outScalar": "\"f16\"" },
237
+ "bindings": [
238
+ { "scratch": "yF32", "name": "x", "buffer": "read-only-storage", "elementType": "f32" },
239
+ { "arg": "yT", "name": "y", "elementType": "$srcScalar" },
240
+ { "name": "params", "struct": [{ "name": "count", "type": "u32", "value": "numel(shapes.yT)" }] }
241
+ ],
242
+ "dispatch": {
243
+ "x": "min(ceilDiv((ceilDiv(numel(shapes.yT), 4)), (tunables.WORKGROUP_SIZE)), 65535)",
244
+ "y": "ceilDiv(ceilDiv((ceilDiv(numel(shapes.yT), 4)), (tunables.WORKGROUP_SIZE)), 65535)",
245
+ "z": 1
246
+ }
247
+ }
248
+ ]
249
+ },
250
+ {
251
+ "id": "sgmat_staged_rows",
252
+ "priority": 19,
253
+ "when": ["commonShapeValid", "dim(shapes.aT, 0) > 1", "dim(shapes.aT, 0) < sgmatTileRows or dim(shapes.aT, 0) % sgmatTileRows != 0", "stagedGeometryValid", "attrs.N % tunables.SGMAT_TILE_COLS == 0", "attrs.K % tunables.SGMAT_TILE_K == 0", "attrs.K % attrs.block_size == 0", "attrs.block_size % sgmatLoadWidth == 0", "wave32Effective", "stagedResourcesFit"],
254
+ "requires": {
255
+ "features": ["subgroups", "chromium-experimental-subgroup-matrix"],
256
+ "subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
257
+ },
258
+ "derive": {
259
+ "K": "attrs.K",
260
+ "N": "attrs.N",
261
+ "blockSize": "attrs.block_size",
262
+ "tileRows": "stagedTileRows",
263
+ "tileCols": "tunables.SGMAT_TILE_COLS",
264
+ "tileK": "tunables.SGMAT_TILE_K",
265
+ "subRows": "sgmatMatrixSize",
266
+ "subCols": "stagedSubCols",
267
+ "matrixSize": "sgmatMatrixSize",
268
+ "rowMatrices": 1,
269
+ "colMatrices": "stagedColumnMatrices",
270
+ "loadWidth": "sgmatLoadWidth",
271
+ "rowSubtiles": "stagedRowSubtiles",
272
+ "workgroupSize": "stagedWorkgroupSize",
273
+ "bLoadsPerRow": "sgmatBLoadsPerRow",
274
+ "aScalar": "\"f16\" if tensorDtypes.aT == \"float16\" else \"f32\"",
275
+ "usesF16": "tensorDtypes.aT == \"float16\"",
276
+ "absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
277
+ "stageActivations": true,
278
+ "rowCount": "dim(shapes.aT, 0)"
279
+ },
280
+ "passes": [
281
+ {
282
+ "id": "main",
283
+ "shader": "matmul-bnb4-sgmat.wgsl.jinja",
284
+ "bindings": ["a", "b", "absmax", "y"],
285
+ "dispatch": { "x": "sgmatDispatchN", "y": "ceilDiv(dim(shapes.aT, 0), stagedTileRows)" }
286
+ }
287
+ ]
288
+ },
289
  {
290
  "id": "gemv",
291
  "priority": 20,
292
  "when": ["gemvShapeValid", "portableWorkgroupFits"],
293
+ "derive": {
294
  "workgroupSize": "portableWorkgroupSize",
295
+ "aScalar": "\"f16\" if tensorDtypes.aT == \"float16\" else \"f32\"",
296
+ "usesF16": "tensorDtypes.aT == \"float16\"",
297
+ "absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\""
298
  },
299
  "passes": [
300
  {
301
  "id": "main",
302
  "shader": "matmul-bnb4-gemv.wgsl.jinja",
303
+ "bindings": [
304
+ "a",
305
+ "b",
306
+ "absmax",
307
+ "y",
308
+ {
309
+ "name": "params",
310
+ "struct": [
311
+ { "name": "K", "type": "u32", "value": "attrs.K" },
312
+ { "name": "N", "type": "u32", "value": "attrs.N" },
313
+ { "name": "blockSize", "type": "u32", "value": "attrs.block_size" }
314
+ ]
315
+ }
316
+ ],
317
+ "dispatch": { "x": "min(attrs.N, 65535)", "y": "ceilDiv(attrs.N, 65535)", "z": 1 }
318
  }
319
  ]
320
  },
321
  {
322
  "id": "sgmat",
323
  "priority": 15,
324
+ "when": ["sgmatGeometryValid", "commonShapeValid", "tensorDtypes.aT == \"float32\"", "dim(shapes.aT, 0) >= sgmatTileRows", "dim(shapes.aT, 0) % sgmatTileRows == 0", "attrs.N % tunables.SGMAT_TILE_COLS == 0", "attrs.K % tunables.SGMAT_TILE_K == 0", "attrs.K % attrs.block_size == 0", "attrs.block_size % sgmatLoadWidth == 0", "wave32Effective", "sgmatWorkgroupFits"],
325
  "requires": {
326
  "features": ["subgroups", "chromium-experimental-subgroup-matrix"],
327
  "limits": { "maxComputeWorkgroupStorageSize": 8192 },
328
  "subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
329
  },
330
+ "derive": {
 
331
  "K": "attrs.K",
332
  "N": "attrs.N",
333
  "blockSize": "attrs.block_size",
 
345
  "bLoadsPerRow": "sgmatBLoadsPerRow",
346
  "aScalar": "\"f32\"",
347
  "usesF16": false,
348
+ "absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\""
349
  },
350
  "passes": [
351
  {
352
  "id": "main",
353
  "shader": "matmul-bnb4-sgmat.wgsl.jinja",
354
+ "bindings": ["a", "b", "absmax", "y"],
355
  "dispatch": { "x": "sgmatDispatchN", "y": "sgmatDispatchM" }
356
  }
357
  ]
 
359
  {
360
  "id": "sgmat_widened",
361
  "priority": 16,
362
+ "when": ["sgmatGeometryValid", "commonShapeValid", "tensorDtypes.aT == \"float16\"", "dim(shapes.aT, 0) >= sgmatTileRows", "dim(shapes.aT, 0) % sgmatTileRows == 0", "attrs.N % tunables.SGMAT_TILE_COLS == 0", "attrs.K % tunables.SGMAT_TILE_K == 0", "attrs.K % attrs.block_size == 0", "attrs.block_size % sgmatLoadWidth == 0", "wave32Effective", "sgmatWorkgroupFits", "sgmatWidenFits"],
363
  "requires": {
364
  "features": ["subgroups", "chromium-experimental-subgroup-matrix"],
365
  "limits": { "maxComputeWorkgroupStorageSize": 8192 },
366
  "subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
367
  },
368
+ "derive": {
 
369
  "K": "attrs.K",
370
  "N": "attrs.N",
371
  "blockSize": "attrs.block_size",
 
383
  "bLoadsPerRow": "sgmatBLoadsPerRow",
384
  "aScalar": "\"f32\"",
385
  "usesF16": true,
386
+ "absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
387
  "srcScalar": "\"f16\"",
388
  "outScalar": "\"f32\"",
389
  "wrapNarrowInt": false,
390
  "wrapSigned": false
391
  },
392
+ "intermediates": [
393
+ { "id": "aF32", "dtype": "float32", "shape": "[numel(shapes.aT)]" },
394
+ { "id": "yF32", "dtype": "float32", "shape": "[dim(shapes.aT, 0) * attrs.N]" }
395
+ ],
396
  "passes": [
397
  {
398
  "id": "widen_a",
399
  "name": "MatMulBnb4.WidenActivations",
400
  "shader": "cast-scalar-x4.wgsl.jinja",
401
+ "bindings": [
402
+ { "arg": "aT", "name": "x", "elementType": "$srcScalar" },
403
+ { "scratch": "aF32", "name": "y", "elementType": "f32" },
404
+ { "name": "params", "struct": [{ "name": "count", "type": "u32", "value": "numel(shapes.aT)" }] }
405
+ ],
406
+ "dispatch": {
407
+ "x": "min(ceilDiv((ceilDiv(numel(shapes.aT), 4)), (tunables.WORKGROUP_SIZE)), 65535)",
408
+ "y": "ceilDiv(ceilDiv((ceilDiv(numel(shapes.aT), 4)), (tunables.WORKGROUP_SIZE)), 65535)",
409
+ "z": 1
410
+ }
411
  },
412
  {
413
  "id": "main",
414
  "name": "MatMulBnb4.SubgroupMatrixWidened",
415
  "shader": "matmul-bnb4-sgmat.wgsl.jinja",
416
+ "bindings": [
417
+ { "scratch": "aF32", "name": "a", "buffer": "read-only-storage", "elementType": "f32" },
418
+ "b",
419
+ "absmax",
420
+ { "scratch": "yF32", "name": "y", "elementType": "f32" }
421
+ ],
422
  "dispatch": { "x": "sgmatDispatchN", "y": "sgmatDispatchM" }
423
  },
424
  {
425
  "id": "narrow_y",
426
  "name": "MatMulBnb4.NarrowOutput",
427
  "shader": "cast-scalar-x4.wgsl.jinja",
428
+ "derive": { "outScalar": "\"f16\"" },
429
+ "bindings": [
430
+ { "scratch": "yF32", "name": "x", "buffer": "read-only-storage", "elementType": "f32" },
431
+ { "arg": "yT", "name": "y", "elementType": "$srcScalar" },
432
+ { "name": "params", "struct": [{ "name": "count", "type": "u32", "value": "dim(shapes.aT, 0) * attrs.N" }] }
433
+ ],
434
  "dispatch": {
435
+ "x": "min(ceilDiv((ceilDiv(dim(shapes.aT, 0) * attrs.N, 4)), (tunables.WORKGROUP_SIZE)), 65535)",
436
+ "y": "ceilDiv(ceilDiv((ceilDiv(dim(shapes.aT, 0) * attrs.N, 4)), (tunables.WORKGROUP_SIZE)), 65535)",
437
+ "z": 1
438
  }
439
  }
 
 
 
 
 
440
  ]
441
  },
442
  {
443
  "id": "tiled",
444
  "priority": 10,
445
  "when": ["tileEligible", "tileWorkgroupFits"],
446
+ "derive": {
447
  "tileK": "tunables.PORTABLE_TILE_K",
448
+ "aScalar": "\"f16\" if tensorDtypes.aT == \"float16\" else \"f32\"",
449
+ "usesF16": "tensorDtypes.aT == \"float16\"",
450
+ "absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
451
+ "tileRows": "portableTileRows"
452
  },
453
  "passes": [
454
  {
455
  "id": "main",
456
  "shader": "matmul-bnb4-tiled.wgsl.jinja",
457
+ "bindings": ["a", "b", "absmax", "y", "params"],
458
+ "dispatch": { "x": "ceilDiv(attrs.N, 64)", "y": "ceilDiv(dim(shapes.aT, 0), portableTileRows)" }
459
  }
460
  ]
461
  },
 
463
  "id": "scalar",
464
  "priority": 0,
465
  "when": ["commonShapeValid", "portableWorkgroupSize > 0"],
466
+ "derive": {
467
  "workgroupSize": "portableWorkgroupSize",
468
+ "aScalar": "\"f16\" if tensorDtypes.aT == \"float16\" else \"f32\"",
469
+ "usesF16": "tensorDtypes.aT == \"float16\"",
470
+ "absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\""
471
  },
472
  "passes": [
473
  {
474
  "id": "main",
475
  "shader": "matmul-bnb4.wgsl.jinja",
476
+ "bindings": ["a", "b", "absmax", "y", "params"],
477
+ "dispatch": {
478
+ "x": "min(ceilDiv((numel(shapes.yT)), (workgroupSize)), 65535)",
479
+ "y": "ceilDiv(ceilDiv((numel(shapes.yT)), (workgroupSize)), 65535)",
480
+ "z": 1
481
+ }
482
  }
483
  ]
484
  }
build/webgpu/matmul-bnb4-gemv.wgsl.jinja CHANGED
@@ -1,6 +1,3 @@
1
- {% if usesF16 %}
2
- enable f16;
3
- {% endif %}
4
  {{ env.wgsl.resourceDeclarations }}
5
 
6
  const WG: u32 = {{ workgroupSize }}u;
@@ -47,14 +44,13 @@ fn dequant_weight(flat: u32) -> f32 {
47
  @compute @workgroup_size(WG, 1, 1)
48
  fn main(
49
  @builtin(workgroup_id) wid: vec3<u32>,
50
- @builtin(num_workgroups) nwg: vec3<u32>,
51
  @builtin(local_invocation_id) lid: vec3<u32>
52
  ) {
53
  let tid = lid.x;
54
  // 2D-folded dispatch: wid.y carries the high bits past the per-dimension
55
  // limit. The fold over-dispatches, so tail workgroups must leave before the
56
  // first barrier — hence the early return here rather than a guarded write.
57
- let col = wid.x + wid.y * nwg.x;
58
  if (col >= params.N) {
59
  return;
60
  }
 
 
 
 
1
  {{ env.wgsl.resourceDeclarations }}
2
 
3
  const WG: u32 = {{ workgroupSize }}u;
 
44
  @compute @workgroup_size(WG, 1, 1)
45
  fn main(
46
  @builtin(workgroup_id) wid: vec3<u32>,
 
47
  @builtin(local_invocation_id) lid: vec3<u32>
48
  ) {
49
  let tid = lid.x;
50
  // 2D-folded dispatch: wid.y carries the high bits past the per-dimension
51
  // limit. The fold over-dispatches, so tail workgroups must leave before the
52
  // first barrier — hence the early return here rather than a guarded write.
53
+ let col = wid.x + wid.y * {{ DISPATCH_FOLD_WIDTH }}u;
54
  if (col >= params.N) {
55
  return;
56
  }
build/webgpu/matmul-bnb4-sgmat.wgsl.jinja CHANGED
@@ -1,32 +1,46 @@
 
 
 
 
1
  // Large aligned prefill tier. The packed B tile is dequantized once per
2
  // workgroup, then reused by subgroup-matrix f32 multiply-accumulate operations.
3
  // This specialization operates on full A, B, and output tiles, so both
4
  // subgroupMatrixLoad and the direct output stores are in bounds.
5
- enable subgroups;
6
- {% if pinSubgroupSize32 %}
7
- enable subgroup_size_control;
8
- {% endif %}
9
- enable chromium_experimental_subgroup_matrix;
10
  {% if usesF16 %}
11
  // The widened path keeps the activations and the output in f32 for the matrix
12
  // units, but the quantization scales stay in the request's own dtype.
13
  enable f16;
14
  {% endif %}
 
 
 
 
 
15
  diagnostic(off, chromium.subgroup_matrix_uniformity);
16
 
 
17
  {{ env.wgsl.resourceDeclarations }}
18
 
19
  const K: u32 = {{ K }}u;
20
  const N: u32 = {{ N }}u;
21
  const BLOCK_SIZE: u32 = {{ blockSize }}u;
 
22
  const TILE_ROWS: u32 = {{ tileRows }}u;
 
23
  const TILE_COLS: u32 = {{ tileCols }}u;
24
  const TILE_K: u32 = {{ tileK }}u;
 
25
  const SUB_ROWS: u32 = {{ subRows }}u;
 
 
26
  const SUB_COLS: u32 = {{ subCols }}u;
 
27
  const LOAD_WIDTH: u32 = {{ loadWidth }}u;
28
 
29
  var<workgroup> tile_B: array<f32, {{ tileCols * tileK }}>;
 
 
 
30
 
31
  /* bitsandbytes 4-bit weight decoding.
32
 
@@ -64,7 +78,7 @@ fn load_b(tile_base: u32, k_base: u32, row: u32, col_group: u32) {
64
  let tile_offset = row * TILE_K + col;
65
 
66
  // Eligibility guarantees that each aligned LOAD_WIDTH slice stays in one
67
- // quantization block and begins on an even weight. The loader widens each
68
  // packed byte once and reuses both nibbles.
69
  for (var i = 0u; i < LOAD_WIDTH; i = i + 2u) {
70
  let packed = b[(flat + i) >> 1u];
@@ -75,13 +89,7 @@ fn load_b(tile_base: u32, k_base: u32, row: u32, col_group: u32) {
75
  }
76
  }
77
 
78
- @compute @workgroup_size({{ workgroupSize }}, 1, 1){{ " @subgroup_size(32)" if pinSubgroupSize32 else "" }}
79
- fn main(
80
- @builtin(workgroup_id) workgroup_id: vec3<u32>,
81
- @builtin(local_invocation_index) local_idx: u32,
82
- @builtin(subgroup_size) subgroup_size: u32
83
- ) {
84
- let a_base = workgroup_id.y * TILE_ROWS;
85
  let b_base = workgroup_id.x * TILE_COLS;
86
 
87
  let subgroup_id = local_idx / subgroup_size;
@@ -95,14 +103,30 @@ fn main(
95
  {% endfor %}{% endfor %}
96
 
97
  for (var k_base = 0u; k_base < K; k_base += TILE_K) {
 
98
  load_b(b_base, k_base, local_idx / {{ bLoadsPerRow }}u, local_idx % {{ bLoadsPerRow }}u);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  workgroupBarrier();
100
 
101
  for (var step = 0u; step < TILE_K; step += {{ matrixSize }}u) {
102
- let matrix_a_offset = (a_base + base_A) * K + k_base + step;
103
  {% for row in range(rowMatrices) %}
104
  let matA{{ row }} = subgroupMatrixLoad<subgroup_matrix_left<f32, {{ matrixSize }}, {{ matrixSize }}>, row_major>(
105
- &a, matrix_a_offset + {{ row * matrixSize }}u * K, K
106
  );
107
  {% endfor %}
108
  let matrix_b_offset = subtile_idx * SUB_COLS * TILE_K + step;
@@ -118,13 +142,54 @@ fn main(
118
  workgroupBarrier();
119
  }
120
 
121
- let output_offset = (a_base + base_A) * N + b_base + base_B;
122
  {% for row in range(rowMatrices) %}{% for col in range(colMatrices) %}
123
  subgroupMatrixStore<row_major>(
124
- &y,
125
- output_offset + {{ row * matrixSize }}u * N + {{ col * matrixSize }}u,
126
  matC{{ row }}{{ col }},
127
- N
128
  );
129
  {% endfor %}{% endfor %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  }
 
 
 
 
 
 
 
 
 
1
+ {% set hybridRows = hybridRows | default(false) %}
2
+ {% set stageActivations = stageActivations | default(false) %}
3
+ {% set aStride = "TILE_K" if stageActivations else "K" %}
4
+ {% set yStride = "TILE_COLS" if stageActivations else "N" %}
5
  // Large aligned prefill tier. The packed B tile is dequantized once per
6
  // workgroup, then reused by subgroup-matrix f32 multiply-accumulate operations.
7
  // This specialization operates on full A, B, and output tiles, so both
8
  // subgroupMatrixLoad and the direct output stores are in bounds.
 
 
 
 
 
9
  {% if usesF16 %}
10
  // The widened path keeps the activations and the output in f32 for the matrix
11
  // units, but the quantization scales stay in the request's own dtype.
12
  enable f16;
13
  {% endif %}
14
+ enable subgroups;
15
+ {% if pinSubgroupSize32 %}
16
+ enable subgroup_size_control;
17
+ {% endif %}
18
+ enable chromium_experimental_subgroup_matrix;
19
  diagnostic(off, chromium.subgroup_matrix_uniformity);
20
 
21
+
22
  {{ env.wgsl.resourceDeclarations }}
23
 
24
  const K: u32 = {{ K }}u;
25
  const N: u32 = {{ N }}u;
26
  const BLOCK_SIZE: u32 = {{ blockSize }}u;
27
+ {% if not hybridRows %}
28
  const TILE_ROWS: u32 = {{ tileRows }}u;
29
+ {% endif %}
30
  const TILE_COLS: u32 = {{ tileCols }}u;
31
  const TILE_K: u32 = {{ tileK }}u;
32
+ {% if not hybridRows %}
33
  const SUB_ROWS: u32 = {{ subRows }}u;
34
+ {% endif %}
35
+ {% if not hybridRows %}
36
  const SUB_COLS: u32 = {{ subCols }}u;
37
+ {% endif %}
38
  const LOAD_WIDTH: u32 = {{ loadWidth }}u;
39
 
40
  var<workgroup> tile_B: array<f32, {{ tileCols * tileK }}>;
41
+ {% if stageActivations or hybridRows %}
42
+ var<workgroup> tile_A: array<f32, {{ ((hybridTailTileRows | default(0)) if hybridRows else tileRows) * tileK }}>;
43
+ {% endif %}
44
 
45
  /* bitsandbytes 4-bit weight decoding.
46
 
 
78
  let tile_offset = row * TILE_K + col;
79
 
80
  // Eligibility guarantees that each aligned LOAD_WIDTH slice stays in one
81
+ // quantization block and begins on an even weight. This shader widens each
82
  // packed byte once and reuses both nibbles.
83
  for (var i = 0u; i < LOAD_WIDTH; i = i + 2u) {
84
  let packed = b[(flat + i) >> 1u];
 
89
  }
90
  }
91
 
92
+ {% macro tile_body(stageActivations, tileRows, subRows, subCols, rowMatrices, colMatrices, rowSubtiles, workgroupSize, rowOffset, aStride, yStride) %} let a_base = workgroup_id.y * TILE_ROWS{% if (rowOffset | default(0)) > 0 %} + {{ rowOffset | default(0) }}u{% endif %};
 
 
 
 
 
 
93
  let b_base = workgroup_id.x * TILE_COLS;
94
 
95
  let subgroup_id = local_idx / subgroup_size;
 
103
  {% endfor %}{% endfor %}
104
 
105
  for (var k_base = 0u; k_base < K; k_base += TILE_K) {
106
+ {% if workgroupSize == ((tileCols * tileK / loadWidth) | int) %}
107
  load_b(b_base, k_base, local_idx / {{ bLoadsPerRow }}u, local_idx % {{ bLoadsPerRow }}u);
108
+ {% else %}
109
+ for (var group = local_idx; group < {{ ((tileCols * tileK / loadWidth) | int) }}u; group += {{ workgroupSize }}u) {
110
+ load_b(b_base, k_base, group / {{ bLoadsPerRow }}u, group % {{ bLoadsPerRow }}u);
111
+ }
112
+ {% endif %}
113
+ {% if stageActivations %}
114
+ for (var linear = local_idx; linear < {{ tileRows * tileK }}u; linear += {{ workgroupSize }}u) {
115
+ let row = a_base + linear / TILE_K;
116
+ var value = 0.0;
117
+ if (row < {{ rowCount | default(0) }}u) {
118
+ value = f32(a[row * K + k_base + linear % TILE_K]);
119
+ }
120
+ tile_A[linear] = value;
121
+ }
122
+ {% endif %}
123
  workgroupBarrier();
124
 
125
  for (var step = 0u; step < TILE_K; step += {{ matrixSize }}u) {
126
+ let matrix_a_offset = {% if stageActivations %}base_A * TILE_K + step{% else %}(a_base + base_A) * K + k_base + step{% endif %};
127
  {% for row in range(rowMatrices) %}
128
  let matA{{ row }} = subgroupMatrixLoad<subgroup_matrix_left<f32, {{ matrixSize }}, {{ matrixSize }}>, row_major>(
129
+ &{{ "tile_A" if stageActivations else "a" }}, matrix_a_offset + {{ row * matrixSize }}u * {{ aStride }}, {{ aStride }}
130
  );
131
  {% endfor %}
132
  let matrix_b_offset = subtile_idx * SUB_COLS * TILE_K + step;
 
142
  workgroupBarrier();
143
  }
144
 
145
+ let output_offset = {% if stageActivations %}base_A * TILE_COLS + base_B{% else %}(a_base + base_A) * N + b_base + base_B{% endif %};
146
  {% for row in range(rowMatrices) %}{% for col in range(colMatrices) %}
147
  subgroupMatrixStore<row_major>(
148
+ &{{ "tile_B" if stageActivations else "y" }},
149
+ output_offset + {{ row * matrixSize }}u * {{ yStride }} + {{ col * matrixSize }}u,
150
  matC{{ row }}{{ col }},
151
+ {{ yStride }}
152
  );
153
  {% endfor %}{% endfor %}
154
+ {% if stageActivations %}
155
+ // The closing K-loop barrier ends all weight reads. Output banks reuse B
156
+ // staging, then a barrier publishes them for disjoint masked global stores.
157
+ workgroupBarrier();
158
+ for (var linear = local_idx; linear < {{ tileRows * tileCols }}u; linear += {{ workgroupSize }}u) {
159
+ let row = a_base + linear / TILE_COLS;
160
+ if (row < {{ rowCount | default(0) }}u) {
161
+ y[row * N + b_base + linear % TILE_COLS] = {{ aScalar }}(tile_B[linear]);
162
+ }
163
+ }
164
+ {% endif %}{% endmacro %}
165
+ {% if hybridRows %}
166
+ fn full_tile(workgroup_id: vec3<u32>, local_idx: u32, subgroup_size: u32) {
167
+ const TILE_ROWS: u32 = {{ tileRows }}u;
168
+ const SUB_ROWS: u32 = {{ subRows }}u;
169
+ const SUB_COLS: u32 = {{ subCols }}u;
170
+ {{ tile_body(false, tileRows, subRows, subCols, rowMatrices, colMatrices, rowSubtiles, workgroupSize, 0, "K", "N") }}}
171
+ fn partial_tile(workgroup_id: vec3<u32>, local_idx: u32, subgroup_size: u32) {
172
+ const TILE_ROWS: u32 = {{ hybridTailTileRows }}u;
173
+ const SUB_ROWS: u32 = {{ matrixSize }}u;
174
+ const SUB_COLS: u32 = {{ hybridTailSubCols }}u;
175
+ {{ tile_body(true, hybridTailTileRows, matrixSize, hybridTailSubCols, 1, ((hybridTailSubCols / matrixSize) | int), hybridTailRowSubtiles, workgroupSize, rowOffset, "TILE_K", "TILE_COLS") }}}
176
+ @compute @workgroup_size({{ workgroupSize }}, 1, 1){{ " @subgroup_size(32)" if pinSubgroupSize32 else "" }}
177
+ fn main(
178
+ @builtin(workgroup_id) workgroup_id: vec3<u32>,
179
+ @builtin(local_invocation_index) local_idx: u32,
180
+ @builtin(subgroup_size) subgroup_size: u32
181
+ ) {
182
+ if (workgroup_id.y < {{ fullDispatchRows }}u) {
183
+ full_tile(workgroup_id, local_idx, subgroup_size);
184
+ } else {
185
+ partial_tile(vec3<u32>(workgroup_id.x, workgroup_id.y - {{ fullDispatchRows }}u, workgroup_id.z), local_idx, subgroup_size);
186
+ }
187
  }
188
+ {% else %}
189
+ @compute @workgroup_size({{ workgroupSize }}, 1, 1){{ " @subgroup_size(32)" if pinSubgroupSize32 else "" }}
190
+ fn main(
191
+ @builtin(workgroup_id) workgroup_id: vec3<u32>,
192
+ @builtin(local_invocation_index) local_idx: u32,
193
+ @builtin(subgroup_size) subgroup_size: u32
194
+ ) {
195
+ {{ tile_body(stageActivations, tileRows, subRows, subCols, rowMatrices, colMatrices, rowSubtiles, workgroupSize, (rowOffset | default(0)), aStride, yStride) }}}{% endif %}
build/webgpu/matmul-bnb4-tiled.wgsl.jinja CHANGED
@@ -1,10 +1,7 @@
1
- {% if usesF16 %}
2
- enable f16;
3
- {% endif %}
4
  {{ env.wgsl.resourceDeclarations }}
5
 
6
- // Prefill: register-blocked 64x64 shared-memory tiled GEMM (16x8 threads, each
7
- // holding an 8x4 micro-tile, with K stepped in BK chunks).
8
  //
9
  // Each weight is dequantized once into the shared B tile and reused across the
10
  // row block. Both operands are stored K-major — A is [M, K] and the packed
@@ -12,9 +9,9 @@ enable f16;
12
  // staging read is contiguous, and one micro-tile step reads TM + TN vector
13
  // words to issue TM * TN * 4 fused multiply-adds through dot().
14
  const BK: u32 = {{ tileK }}u;
15
- const BM: u32 = 64u;
16
  const BN: u32 = 64u;
17
- const TM: u32 = 8u;
18
  const TN: u32 = 4u;
19
  const WG_X: u32 = 16u;
20
  const WG_SIZE: u32 = 128u;
@@ -97,7 +94,7 @@ fn main(
97
  let aRow = lid.y * TM;
98
  let bCol = lid.x * TN;
99
 
100
- {% for row in range(8) %}
101
  var acc{{ row }} = vec4<f32>(0.0);
102
  {% endfor %}
103
  let numTiles = (params.K + BK - 1u) / BK;
@@ -148,7 +145,7 @@ fn main(
148
  {% for column in range(4) %}
149
  let bv{{ column }} = tileB[bCol + {{ column }}u][kv];
150
  {% endfor %}
151
- {% for row in range(8) %}
152
  let av{{ row }} = vec4<f32>(tileA[aRow + {{ row }}u][kv]);
153
  acc{{ row }} += vec4<f32>({% for column in range(4) %}dot(av{{ row }}, bv{{ column }}){% if not loop.last %}, {% endif %}{% endfor %});
154
  {% endfor %}
@@ -156,7 +153,7 @@ fn main(
156
  workgroupBarrier();
157
  }
158
 
159
- {% for row in range(8) %}
160
  {% for column in range(4) %}
161
  {
162
  let m = mBase + aRow + {{ row }}u;
 
 
 
 
1
  {{ env.wgsl.resourceDeclarations }}
2
 
3
+ // Prefill: register-blocked {{ tileRows }}x64 shared-memory tiled GEMM (16x8 threads, each
4
+ // holding an {{ ((tileRows / 8) | int) }}x4 micro-tile, with K stepped in BK chunks).
5
  //
6
  // Each weight is dequantized once into the shared B tile and reused across the
7
  // row block. Both operands are stored K-major — A is [M, K] and the packed
 
9
  // staging read is contiguous, and one micro-tile step reads TM + TN vector
10
  // words to issue TM * TN * 4 fused multiply-adds through dot().
11
  const BK: u32 = {{ tileK }}u;
12
+ const BM: u32 = {{ tileRows }}u;
13
  const BN: u32 = 64u;
14
+ const TM: u32 = {{ ((tileRows / 8) | int) }}u;
15
  const TN: u32 = 4u;
16
  const WG_X: u32 = 16u;
17
  const WG_SIZE: u32 = 128u;
 
94
  let aRow = lid.y * TM;
95
  let bCol = lid.x * TN;
96
 
97
+ {% for row in range(((tileRows / 8) | int)) %}
98
  var acc{{ row }} = vec4<f32>(0.0);
99
  {% endfor %}
100
  let numTiles = (params.K + BK - 1u) / BK;
 
145
  {% for column in range(4) %}
146
  let bv{{ column }} = tileB[bCol + {{ column }}u][kv];
147
  {% endfor %}
148
+ {% for row in range(((tileRows / 8) | int)) %}
149
  let av{{ row }} = vec4<f32>(tileA[aRow + {{ row }}u][kv]);
150
  acc{{ row }} += vec4<f32>({% for column in range(4) %}dot(av{{ row }}, bv{{ column }}){% if not loop.last %}, {% endif %}{% endfor %});
151
  {% endfor %}
 
153
  workgroupBarrier();
154
  }
155
 
156
+ {% for row in range(((tileRows / 8) | int)) %}
157
  {% for column in range(4) %}
158
  {
159
  let m = mBase + aRow + {{ row }}u;
build/webgpu/matmul-bnb4.wgsl.jinja CHANGED
@@ -1,6 +1,3 @@
1
- {% if usesF16 %}
2
- enable f16;
3
- {% endif %}
4
  {{ env.wgsl.resourceDeclarations }}
5
 
6
  const WG: u32 = {{ workgroupSize }}u;
@@ -41,11 +38,11 @@ fn dequant_weight(flat: u32) -> f32 {
41
 
42
 
43
  @compute @workgroup_size(WG, 1, 1)
44
- fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
45
  // 2D-folded flat output-element index: gid.y carries the high bits past the
46
- // maxComputeWorkgroupsPerDimension dispatch limit. When nwg.y == 1 this
47
  // reduces to gid.x; the index >= total guard drops the tail.
48
- let index = gid.x + gid.y * nwg.x * WG;
49
  let total = params.rows * params.N;
50
 
51
  if (index >= total) {
 
 
 
 
1
  {{ env.wgsl.resourceDeclarations }}
2
 
3
  const WG: u32 = {{ workgroupSize }}u;
 
38
 
39
 
40
  @compute @workgroup_size(WG, 1, 1)
41
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
42
  // 2D-folded flat output-element index: gid.y carries the high bits past the
43
+ // per-axis dispatch fold width. With no fold this
44
  // reduces to gid.x; the index >= total guard drops the tail.
45
+ let index = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * WG;
46
  let total = params.rows * params.N;
47
 
48
  if (index >= total) {
build/webgpu/metadata.json CHANGED
@@ -1,22 +1,34 @@
1
  {
2
  "name": "com.microsoft.MatMulBnb4",
3
- "id": "_com_microsoft_matmulbnb4_webgpu_aab3ed9",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
- "bench.json": "65V0CAoAl7vsenxQG3P5y9j0T4tJEprrb5BwhczZ/So=",
11
- "cast-scalar-x4.wgsl.jinja": "uplwFdE8dJSffJop4txQHZgeGDDJ5K9+F3V4n1CotVo=",
12
- "manifest.json": "TFYtgeuCmTA2Ei4kkTZQ2PUcZP7JT9DEynhMUofG+BU=",
13
- "matmul-bnb4-gemv.wgsl.jinja": "7e4ZY+raLAMG/wmXm72XpSzPsR6adHvvrcKxv2ZKj/4=",
14
- "matmul-bnb4-sgmat.wgsl.jinja": "x3RRM9yb0++oJ2o6qqmhx+qwCqb2MAZui1Pdlof6nsU=",
15
- "matmul-bnb4-tiled.wgsl.jinja": "+pb1pUgFU+RLITtJ+zrnTDl3LUmU7sZDGqIdyKtAmn4=",
16
- "matmul-bnb4.wgsl.jinja": "xzeJm4jFqbXih7plcQup4jUQsRw4h8HpLzcAxWR2aic=",
17
- "test.json": "1oYDh6veLTUP+o7nE+G7nU1FMK88nLKArXE/FcbOfTo="
18
  }
19
  },
20
- "provenance": { "kernel": { "sha": "c928d21e6cc1310861cba3bafb75f5f679ecf5f3", "dirty": false } },
21
- "webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/com.microsoft.MatMulBnb4" }
 
 
 
 
 
 
 
 
 
 
 
 
22
  }
 
1
  {
2
  "name": "com.microsoft.MatMulBnb4",
3
+ "id": "_com_microsoft_matmulbnb4_webgpu_237048a",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
+ "bench.json": "/Z1zFaT4D+0TEFMxG/zqun5CjI9irI93GNGwLZdLXHQ=",
11
+ "cast-scalar-x4.wgsl.jinja": "s8Y9E2+D7cFgYTUEJhiuPsUzvHjv2mXVoiRmv0A0vTU=",
12
+ "manifest.json": "TEJfUwu6Isit+t0fBCRp0Ny+uC8hUjSe2jgG5kCFcEg=",
13
+ "matmul-bnb4-gemv.wgsl.jinja": "7W3L5RH+5dk5/dKNnjwVFtBt+xgCxorJJ04/8zHrySw=",
14
+ "matmul-bnb4-sgmat.wgsl.jinja": "9WS5F6zd/KFztTpbZjBgJe7WIl0l7uiRelcDv/9YbBc=",
15
+ "matmul-bnb4-tiled.wgsl.jinja": "bADcd5OFuhrZ33Qntqh1PXREZolJZ+RKS+VlweAjPo0=",
16
+ "matmul-bnb4.wgsl.jinja": "6rtf2K0op1IJv2+l66HJjq8XnBATGyefxit0Hj5QREI=",
17
+ "test.json": "KPAf0hjucty64auyD+xOS5RAGDEPYeAlUSJPhbig7CA="
18
  }
19
  },
20
+ "provenance": { "kernel": { "sha": "91d990483a174128daf7673f3f37a7c890493ae1", "dirty": false } },
21
+ "webgpu": {
22
+ "manifestSpec": "2.0",
23
+ "variants": {
24
+ "sgmat_hybrid_rows": ["matmul-bnb4-sgmat.wgsl.jinja"],
25
+ "sgmat_hybrid_rows_widened": ["cast-scalar-x4.wgsl.jinja", "matmul-bnb4-sgmat.wgsl.jinja"],
26
+ "sgmat_staged_rows": ["matmul-bnb4-sgmat.wgsl.jinja"],
27
+ "gemv": ["matmul-bnb4-gemv.wgsl.jinja"],
28
+ "sgmat": ["matmul-bnb4-sgmat.wgsl.jinja"],
29
+ "sgmat_widened": ["cast-scalar-x4.wgsl.jinja", "matmul-bnb4-sgmat.wgsl.jinja"],
30
+ "tiled": ["matmul-bnb4-tiled.wgsl.jinja"],
31
+ "scalar": ["matmul-bnb4.wgsl.jinja"]
32
+ }
33
+ }
34
  }
build/webgpu/test.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "com.microsoft.MatMulBnb4",
3
  "fixtureArrays": {
4
  "bnb4_weight_cycle_b_t": [1, 35, 69, 103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16, 90]
5
  },
@@ -408,7 +407,7 @@
408
  {
409
  "name": "nf4_sgmat_widened_f16",
410
  "provenance": {
411
- "notes": "A float16 request on the aligned subgroup-matrix shape. The matrix units take float32 operands and accumulate in float32, so this path widens the activations either side of the multiply rather than using the device's float16 configuration, whose result component is also float16. It is the only case that reaches the widening passes."
412
  },
413
  "attrs": { "K": 64, "N": 64, "block_size": 32, "quant_type": 1 },
414
  "inputs": {
@@ -429,6 +428,1449 @@
429
  }
430
  },
431
  "outputs": { "yT": { "dtype": "float16", "shape": [128, 64], "tolerance": 0.002, "relTolerance": 0.002 } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
  }
433
  ]
434
  }
 
1
  {
 
2
  "fixtureArrays": {
3
  "bnb4_weight_cycle_b_t": [1, 35, 69, 103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16, 90]
4
  },
 
407
  {
408
  "name": "nf4_sgmat_widened_f16",
409
  "provenance": {
410
+ "notes": "A float16 request on an aligned subgroup-matrix shape widens activations to float32 around the multiply, accumulates in float32, and narrows the result afterward."
411
  },
412
  "attrs": { "K": 64, "N": 64, "block_size": 32, "quant_type": 1 },
413
  "inputs": {
 
428
  }
429
  },
430
  "outputs": { "yT": { "dtype": "float16", "shape": [128, 64], "tolerance": 0.002, "relTolerance": 0.002 } }
431
+ },
432
+ {
433
+ "name": "nf4_tiled_speculative_band_m5",
434
+ "provenance": {
435
+ "notes": "A five-row speculative-decoder multiply exercises the tiled route within the 2-to-15-row band, using a ragged K dimension and NF4 block-quantized weights."
436
+ },
437
+ "attrs": { "K": 33, "N": 19, "block_size": 16, "quant_type": 1 },
438
+ "inputs": {
439
+ "aT": {
440
+ "dtype": "float32",
441
+ "shape": [5, 33],
442
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
443
+ },
444
+ "bT": {
445
+ "dtype": "uint8",
446
+ "shape": [314],
447
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
448
+ },
449
+ "absmaxT": {
450
+ "dtype": "float32",
451
+ "shape": [40],
452
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
453
+ }
454
+ },
455
+ "outputs": { "yT": { "dtype": "float32", "shape": [5, 19], "tolerance": 0.00001 } }
456
+ },
457
+ {
458
+ "name": "rows_float32_q0_m2_k64_n64",
459
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
460
+ "inputs": {
461
+ "aT": {
462
+ "dtype": "float32",
463
+ "shape": [2, 64],
464
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
465
+ },
466
+ "bT": {
467
+ "dtype": "uint8",
468
+ "shape": [2048],
469
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
470
+ },
471
+ "absmaxT": {
472
+ "dtype": "float32",
473
+ "shape": [256],
474
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
475
+ }
476
+ },
477
+ "outputs": { "yT": { "dtype": "float32", "shape": [2, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
478
+ "provenance": {
479
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
480
+ }
481
+ },
482
+ {
483
+ "name": "rows_float32_q1_m3_k128_n128",
484
+ "attrs": { "K": 128, "N": 128, "block_size": 32, "quant_type": 1 },
485
+ "inputs": {
486
+ "aT": {
487
+ "dtype": "float32",
488
+ "shape": [3, 128],
489
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
490
+ },
491
+ "bT": {
492
+ "dtype": "uint8",
493
+ "shape": [8192],
494
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
495
+ },
496
+ "absmaxT": {
497
+ "dtype": "float32",
498
+ "shape": [512],
499
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
500
+ }
501
+ },
502
+ "outputs": { "yT": { "dtype": "float32", "shape": [3, 128], "tolerance": 0.00002, "relTolerance": 0.00001 } },
503
+ "provenance": {
504
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
505
+ }
506
+ },
507
+ {
508
+ "name": "rows_float32_q0_m7_k512_n64",
509
+ "attrs": { "K": 512, "N": 64, "block_size": 64, "quant_type": 0 },
510
+ "inputs": {
511
+ "aT": {
512
+ "dtype": "float32",
513
+ "shape": [7, 512],
514
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
515
+ },
516
+ "bT": {
517
+ "dtype": "uint8",
518
+ "shape": [16384],
519
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
520
+ },
521
+ "absmaxT": {
522
+ "dtype": "float32",
523
+ "shape": [512],
524
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
525
+ }
526
+ },
527
+ "outputs": { "yT": { "dtype": "float32", "shape": [7, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
528
+ "provenance": {
529
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
530
+ }
531
+ },
532
+ {
533
+ "name": "rows_float32_q1_m8_k64_n128",
534
+ "attrs": { "K": 64, "N": 128, "block_size": 16, "quant_type": 1 },
535
+ "inputs": {
536
+ "aT": {
537
+ "dtype": "float32",
538
+ "shape": [8, 64],
539
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
540
+ },
541
+ "bT": {
542
+ "dtype": "uint8",
543
+ "shape": [4096],
544
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
545
+ },
546
+ "absmaxT": {
547
+ "dtype": "float32",
548
+ "shape": [512],
549
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
550
+ }
551
+ },
552
+ "outputs": { "yT": { "dtype": "float32", "shape": [8, 128], "tolerance": 0.00002, "relTolerance": 0.00001 } },
553
+ "provenance": {
554
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
555
+ }
556
+ },
557
+ {
558
+ "name": "rows_float32_q0_m9_k128_n64",
559
+ "attrs": { "K": 128, "N": 64, "block_size": 32, "quant_type": 0 },
560
+ "inputs": {
561
+ "aT": {
562
+ "dtype": "float32",
563
+ "shape": [9, 128],
564
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
565
+ },
566
+ "bT": {
567
+ "dtype": "uint8",
568
+ "shape": [4096],
569
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
570
+ },
571
+ "absmaxT": {
572
+ "dtype": "float32",
573
+ "shape": [256],
574
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
575
+ }
576
+ },
577
+ "outputs": { "yT": { "dtype": "float32", "shape": [9, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
578
+ "provenance": {
579
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
580
+ }
581
+ },
582
+ {
583
+ "name": "rows_float32_q1_m15_k512_n128",
584
+ "attrs": { "K": 512, "N": 128, "block_size": 64, "quant_type": 1 },
585
+ "inputs": {
586
+ "aT": {
587
+ "dtype": "float32",
588
+ "shape": [15, 512],
589
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
590
+ },
591
+ "bT": {
592
+ "dtype": "uint8",
593
+ "shape": [32768],
594
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
595
+ },
596
+ "absmaxT": {
597
+ "dtype": "float32",
598
+ "shape": [1024],
599
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
600
+ }
601
+ },
602
+ "outputs": { "yT": { "dtype": "float32", "shape": [15, 128], "tolerance": 0.00002, "relTolerance": 0.00001 } },
603
+ "provenance": {
604
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
605
+ }
606
+ },
607
+ {
608
+ "name": "rows_float32_q0_m16_k64_n64",
609
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
610
+ "inputs": {
611
+ "aT": {
612
+ "dtype": "float32",
613
+ "shape": [16, 64],
614
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
615
+ },
616
+ "bT": {
617
+ "dtype": "uint8",
618
+ "shape": [2048],
619
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
620
+ },
621
+ "absmaxT": {
622
+ "dtype": "float32",
623
+ "shape": [256],
624
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
625
+ }
626
+ },
627
+ "outputs": { "yT": { "dtype": "float32", "shape": [16, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
628
+ "provenance": {
629
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
630
+ }
631
+ },
632
+ {
633
+ "name": "rows_float32_q1_m17_k128_n128",
634
+ "attrs": { "K": 128, "N": 128, "block_size": 32, "quant_type": 1 },
635
+ "inputs": {
636
+ "aT": {
637
+ "dtype": "float32",
638
+ "shape": [17, 128],
639
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
640
+ },
641
+ "bT": {
642
+ "dtype": "uint8",
643
+ "shape": [8192],
644
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
645
+ },
646
+ "absmaxT": {
647
+ "dtype": "float32",
648
+ "shape": [512],
649
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
650
+ }
651
+ },
652
+ "outputs": { "yT": { "dtype": "float32", "shape": [17, 128], "tolerance": 0.00002, "relTolerance": 0.00001 } },
653
+ "provenance": {
654
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
655
+ }
656
+ },
657
+ {
658
+ "name": "rows_float32_q0_m24_k512_n64",
659
+ "attrs": { "K": 512, "N": 64, "block_size": 64, "quant_type": 0 },
660
+ "inputs": {
661
+ "aT": {
662
+ "dtype": "float32",
663
+ "shape": [24, 512],
664
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
665
+ },
666
+ "bT": {
667
+ "dtype": "uint8",
668
+ "shape": [16384],
669
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
670
+ },
671
+ "absmaxT": {
672
+ "dtype": "float32",
673
+ "shape": [512],
674
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
675
+ }
676
+ },
677
+ "outputs": { "yT": { "dtype": "float32", "shape": [24, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
678
+ "provenance": {
679
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
680
+ }
681
+ },
682
+ {
683
+ "name": "rows_float32_q1_m31_k64_n128",
684
+ "attrs": { "K": 64, "N": 128, "block_size": 16, "quant_type": 1 },
685
+ "inputs": {
686
+ "aT": {
687
+ "dtype": "float32",
688
+ "shape": [31, 64],
689
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
690
+ },
691
+ "bT": {
692
+ "dtype": "uint8",
693
+ "shape": [4096],
694
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
695
+ },
696
+ "absmaxT": {
697
+ "dtype": "float32",
698
+ "shape": [512],
699
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
700
+ }
701
+ },
702
+ "outputs": { "yT": { "dtype": "float32", "shape": [31, 128], "tolerance": 0.00002, "relTolerance": 0.00001 } },
703
+ "provenance": {
704
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
705
+ }
706
+ },
707
+ {
708
+ "name": "rows_float32_q0_m33_k128_n64",
709
+ "attrs": { "K": 128, "N": 64, "block_size": 32, "quant_type": 0 },
710
+ "inputs": {
711
+ "aT": {
712
+ "dtype": "float32",
713
+ "shape": [33, 128],
714
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
715
+ },
716
+ "bT": {
717
+ "dtype": "uint8",
718
+ "shape": [4096],
719
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
720
+ },
721
+ "absmaxT": {
722
+ "dtype": "float32",
723
+ "shape": [256],
724
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
725
+ }
726
+ },
727
+ "outputs": { "yT": { "dtype": "float32", "shape": [33, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
728
+ "provenance": {
729
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
730
+ }
731
+ },
732
+ {
733
+ "name": "rows_float32_q1_m63_k512_n128",
734
+ "attrs": { "K": 512, "N": 128, "block_size": 64, "quant_type": 1 },
735
+ "inputs": {
736
+ "aT": {
737
+ "dtype": "float32",
738
+ "shape": [63, 512],
739
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
740
+ },
741
+ "bT": {
742
+ "dtype": "uint8",
743
+ "shape": [32768],
744
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
745
+ },
746
+ "absmaxT": {
747
+ "dtype": "float32",
748
+ "shape": [1024],
749
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
750
+ }
751
+ },
752
+ "outputs": { "yT": { "dtype": "float32", "shape": [63, 128], "tolerance": 0.00002, "relTolerance": 0.00001 } },
753
+ "provenance": {
754
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
755
+ }
756
+ },
757
+ {
758
+ "name": "rows_float32_q0_m65_k64_n64",
759
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
760
+ "inputs": {
761
+ "aT": {
762
+ "dtype": "float32",
763
+ "shape": [65, 64],
764
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
765
+ },
766
+ "bT": {
767
+ "dtype": "uint8",
768
+ "shape": [2048],
769
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
770
+ },
771
+ "absmaxT": {
772
+ "dtype": "float32",
773
+ "shape": [256],
774
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
775
+ }
776
+ },
777
+ "outputs": { "yT": { "dtype": "float32", "shape": [65, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
778
+ "provenance": {
779
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
780
+ }
781
+ },
782
+ {
783
+ "name": "rows_float32_q1_m129_k128_n128",
784
+ "attrs": { "K": 128, "N": 128, "block_size": 32, "quant_type": 1 },
785
+ "inputs": {
786
+ "aT": {
787
+ "dtype": "float32",
788
+ "shape": [129, 128],
789
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
790
+ },
791
+ "bT": {
792
+ "dtype": "uint8",
793
+ "shape": [8192],
794
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
795
+ },
796
+ "absmaxT": {
797
+ "dtype": "float32",
798
+ "shape": [512],
799
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
800
+ }
801
+ },
802
+ "outputs": { "yT": { "dtype": "float32", "shape": [129, 128], "tolerance": 0.00002, "relTolerance": 0.00001 } },
803
+ "provenance": {
804
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
805
+ }
806
+ },
807
+ {
808
+ "name": "rows_float16_q0_m2_k64_n64",
809
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
810
+ "inputs": {
811
+ "aT": {
812
+ "dtype": "float16",
813
+ "shape": [2, 64],
814
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
815
+ },
816
+ "bT": {
817
+ "dtype": "uint8",
818
+ "shape": [2048],
819
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
820
+ },
821
+ "absmaxT": {
822
+ "dtype": "float16",
823
+ "shape": [256],
824
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
825
+ }
826
+ },
827
+ "outputs": { "yT": { "dtype": "float16", "shape": [2, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
828
+ "provenance": {
829
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
830
+ }
831
+ },
832
+ {
833
+ "name": "rows_float16_q1_m3_k128_n128",
834
+ "attrs": { "K": 128, "N": 128, "block_size": 32, "quant_type": 1 },
835
+ "inputs": {
836
+ "aT": {
837
+ "dtype": "float16",
838
+ "shape": [3, 128],
839
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
840
+ },
841
+ "bT": {
842
+ "dtype": "uint8",
843
+ "shape": [8192],
844
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
845
+ },
846
+ "absmaxT": {
847
+ "dtype": "float16",
848
+ "shape": [512],
849
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
850
+ }
851
+ },
852
+ "outputs": { "yT": { "dtype": "float16", "shape": [3, 128], "tolerance": 0.001, "relTolerance": 0.001 } },
853
+ "provenance": {
854
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
855
+ }
856
+ },
857
+ {
858
+ "name": "rows_float16_q0_m7_k512_n64",
859
+ "attrs": { "K": 512, "N": 64, "block_size": 64, "quant_type": 0 },
860
+ "inputs": {
861
+ "aT": {
862
+ "dtype": "float16",
863
+ "shape": [7, 512],
864
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
865
+ },
866
+ "bT": {
867
+ "dtype": "uint8",
868
+ "shape": [16384],
869
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
870
+ },
871
+ "absmaxT": {
872
+ "dtype": "float16",
873
+ "shape": [512],
874
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
875
+ }
876
+ },
877
+ "outputs": { "yT": { "dtype": "float16", "shape": [7, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
878
+ "provenance": {
879
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
880
+ }
881
+ },
882
+ {
883
+ "name": "rows_float16_q1_m8_k64_n128",
884
+ "attrs": { "K": 64, "N": 128, "block_size": 16, "quant_type": 1 },
885
+ "inputs": {
886
+ "aT": {
887
+ "dtype": "float16",
888
+ "shape": [8, 64],
889
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
890
+ },
891
+ "bT": {
892
+ "dtype": "uint8",
893
+ "shape": [4096],
894
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
895
+ },
896
+ "absmaxT": {
897
+ "dtype": "float16",
898
+ "shape": [512],
899
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
900
+ }
901
+ },
902
+ "outputs": { "yT": { "dtype": "float16", "shape": [8, 128], "tolerance": 0.001, "relTolerance": 0.001 } },
903
+ "provenance": {
904
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
905
+ }
906
+ },
907
+ {
908
+ "name": "rows_float16_q0_m9_k128_n64",
909
+ "attrs": { "K": 128, "N": 64, "block_size": 32, "quant_type": 0 },
910
+ "inputs": {
911
+ "aT": {
912
+ "dtype": "float16",
913
+ "shape": [9, 128],
914
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
915
+ },
916
+ "bT": {
917
+ "dtype": "uint8",
918
+ "shape": [4096],
919
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
920
+ },
921
+ "absmaxT": {
922
+ "dtype": "float16",
923
+ "shape": [256],
924
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
925
+ }
926
+ },
927
+ "outputs": { "yT": { "dtype": "float16", "shape": [9, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
928
+ "provenance": {
929
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
930
+ }
931
+ },
932
+ {
933
+ "name": "rows_float16_q1_m15_k512_n128",
934
+ "attrs": { "K": 512, "N": 128, "block_size": 64, "quant_type": 1 },
935
+ "inputs": {
936
+ "aT": {
937
+ "dtype": "float16",
938
+ "shape": [15, 512],
939
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
940
+ },
941
+ "bT": {
942
+ "dtype": "uint8",
943
+ "shape": [32768],
944
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
945
+ },
946
+ "absmaxT": {
947
+ "dtype": "float16",
948
+ "shape": [1024],
949
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
950
+ }
951
+ },
952
+ "outputs": { "yT": { "dtype": "float16", "shape": [15, 128], "tolerance": 0.001, "relTolerance": 0.001 } },
953
+ "provenance": {
954
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
955
+ }
956
+ },
957
+ {
958
+ "name": "rows_float16_q0_m16_k64_n64",
959
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
960
+ "inputs": {
961
+ "aT": {
962
+ "dtype": "float16",
963
+ "shape": [16, 64],
964
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
965
+ },
966
+ "bT": {
967
+ "dtype": "uint8",
968
+ "shape": [2048],
969
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
970
+ },
971
+ "absmaxT": {
972
+ "dtype": "float16",
973
+ "shape": [256],
974
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
975
+ }
976
+ },
977
+ "outputs": { "yT": { "dtype": "float16", "shape": [16, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
978
+ "provenance": {
979
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
980
+ }
981
+ },
982
+ {
983
+ "name": "rows_float16_q1_m17_k128_n128",
984
+ "attrs": { "K": 128, "N": 128, "block_size": 32, "quant_type": 1 },
985
+ "inputs": {
986
+ "aT": {
987
+ "dtype": "float16",
988
+ "shape": [17, 128],
989
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
990
+ },
991
+ "bT": {
992
+ "dtype": "uint8",
993
+ "shape": [8192],
994
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
995
+ },
996
+ "absmaxT": {
997
+ "dtype": "float16",
998
+ "shape": [512],
999
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1000
+ }
1001
+ },
1002
+ "outputs": { "yT": { "dtype": "float16", "shape": [17, 128], "tolerance": 0.001, "relTolerance": 0.001 } },
1003
+ "provenance": {
1004
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1005
+ }
1006
+ },
1007
+ {
1008
+ "name": "rows_float16_q0_m24_k512_n64",
1009
+ "attrs": { "K": 512, "N": 64, "block_size": 64, "quant_type": 0 },
1010
+ "inputs": {
1011
+ "aT": {
1012
+ "dtype": "float16",
1013
+ "shape": [24, 512],
1014
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1015
+ },
1016
+ "bT": {
1017
+ "dtype": "uint8",
1018
+ "shape": [16384],
1019
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1020
+ },
1021
+ "absmaxT": {
1022
+ "dtype": "float16",
1023
+ "shape": [512],
1024
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1025
+ }
1026
+ },
1027
+ "outputs": { "yT": { "dtype": "float16", "shape": [24, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
1028
+ "provenance": {
1029
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1030
+ }
1031
+ },
1032
+ {
1033
+ "name": "rows_float16_q1_m31_k64_n128",
1034
+ "attrs": { "K": 64, "N": 128, "block_size": 16, "quant_type": 1 },
1035
+ "inputs": {
1036
+ "aT": {
1037
+ "dtype": "float16",
1038
+ "shape": [31, 64],
1039
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1040
+ },
1041
+ "bT": {
1042
+ "dtype": "uint8",
1043
+ "shape": [4096],
1044
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1045
+ },
1046
+ "absmaxT": {
1047
+ "dtype": "float16",
1048
+ "shape": [512],
1049
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1050
+ }
1051
+ },
1052
+ "outputs": { "yT": { "dtype": "float16", "shape": [31, 128], "tolerance": 0.001, "relTolerance": 0.001 } },
1053
+ "provenance": {
1054
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1055
+ }
1056
+ },
1057
+ {
1058
+ "name": "rows_float16_q0_m33_k128_n64",
1059
+ "attrs": { "K": 128, "N": 64, "block_size": 32, "quant_type": 0 },
1060
+ "inputs": {
1061
+ "aT": {
1062
+ "dtype": "float16",
1063
+ "shape": [33, 128],
1064
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1065
+ },
1066
+ "bT": {
1067
+ "dtype": "uint8",
1068
+ "shape": [4096],
1069
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1070
+ },
1071
+ "absmaxT": {
1072
+ "dtype": "float16",
1073
+ "shape": [256],
1074
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1075
+ }
1076
+ },
1077
+ "outputs": { "yT": { "dtype": "float16", "shape": [33, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
1078
+ "provenance": {
1079
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1080
+ }
1081
+ },
1082
+ {
1083
+ "name": "rows_float16_q1_m63_k512_n128",
1084
+ "attrs": { "K": 512, "N": 128, "block_size": 64, "quant_type": 1 },
1085
+ "inputs": {
1086
+ "aT": {
1087
+ "dtype": "float16",
1088
+ "shape": [63, 512],
1089
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1090
+ },
1091
+ "bT": {
1092
+ "dtype": "uint8",
1093
+ "shape": [32768],
1094
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1095
+ },
1096
+ "absmaxT": {
1097
+ "dtype": "float16",
1098
+ "shape": [1024],
1099
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1100
+ }
1101
+ },
1102
+ "outputs": { "yT": { "dtype": "float16", "shape": [63, 128], "tolerance": 0.001, "relTolerance": 0.001 } },
1103
+ "provenance": {
1104
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1105
+ }
1106
+ },
1107
+ {
1108
+ "name": "rows_float16_q0_m65_k64_n64",
1109
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
1110
+ "inputs": {
1111
+ "aT": {
1112
+ "dtype": "float16",
1113
+ "shape": [65, 64],
1114
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1115
+ },
1116
+ "bT": {
1117
+ "dtype": "uint8",
1118
+ "shape": [2048],
1119
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1120
+ },
1121
+ "absmaxT": {
1122
+ "dtype": "float16",
1123
+ "shape": [256],
1124
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1125
+ }
1126
+ },
1127
+ "outputs": { "yT": { "dtype": "float16", "shape": [65, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
1128
+ "provenance": {
1129
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1130
+ }
1131
+ },
1132
+ {
1133
+ "name": "rows_float16_q1_m129_k128_n128",
1134
+ "attrs": { "K": 128, "N": 128, "block_size": 32, "quant_type": 1 },
1135
+ "inputs": {
1136
+ "aT": {
1137
+ "dtype": "float16",
1138
+ "shape": [129, 128],
1139
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1140
+ },
1141
+ "bT": {
1142
+ "dtype": "uint8",
1143
+ "shape": [8192],
1144
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1145
+ },
1146
+ "absmaxT": {
1147
+ "dtype": "float16",
1148
+ "shape": [512],
1149
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1150
+ }
1151
+ },
1152
+ "outputs": { "yT": { "dtype": "float16", "shape": [129, 128], "tolerance": 0.001, "relTolerance": 0.001 } },
1153
+ "provenance": {
1154
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1155
+ }
1156
+ },
1157
+ {
1158
+ "name": "matrix_tunable_float32_q0_m15_k192_n64_32_8",
1159
+ "attrs": { "K": 192, "N": 64, "block_size": 16, "quant_type": 0 },
1160
+ "inputs": {
1161
+ "aT": {
1162
+ "dtype": "float32",
1163
+ "shape": [15, 192],
1164
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1165
+ },
1166
+ "bT": {
1167
+ "dtype": "uint8",
1168
+ "shape": [6144],
1169
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1170
+ },
1171
+ "absmaxT": {
1172
+ "dtype": "float32",
1173
+ "shape": [768],
1174
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1175
+ }
1176
+ },
1177
+ "outputs": { "yT": { "dtype": "float32", "shape": [15, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1178
+ "provenance": {
1179
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1180
+ },
1181
+ "tunables": { "SGMAT_TILE_COLS": 32, "SGMAT_TILE_K": 8 }
1182
+ },
1183
+ {
1184
+ "name": "matrix_tunable_float32_q0_m128_k192_n64_32_8",
1185
+ "attrs": { "K": 192, "N": 64, "block_size": 16, "quant_type": 0 },
1186
+ "inputs": {
1187
+ "aT": {
1188
+ "dtype": "float32",
1189
+ "shape": [128, 192],
1190
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1191
+ },
1192
+ "bT": {
1193
+ "dtype": "uint8",
1194
+ "shape": [6144],
1195
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1196
+ },
1197
+ "absmaxT": {
1198
+ "dtype": "float32",
1199
+ "shape": [768],
1200
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1201
+ }
1202
+ },
1203
+ "outputs": { "yT": { "dtype": "float32", "shape": [128, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1204
+ "provenance": {
1205
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1206
+ },
1207
+ "tunables": { "SGMAT_TILE_COLS": 32, "SGMAT_TILE_K": 8 }
1208
+ },
1209
+ {
1210
+ "name": "matrix_tunable_float16_q1_m15_k192_n128_64_16",
1211
+ "attrs": { "K": 192, "N": 128, "block_size": 16, "quant_type": 1 },
1212
+ "inputs": {
1213
+ "aT": {
1214
+ "dtype": "float16",
1215
+ "shape": [15, 192],
1216
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1217
+ },
1218
+ "bT": {
1219
+ "dtype": "uint8",
1220
+ "shape": [12288],
1221
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1222
+ },
1223
+ "absmaxT": {
1224
+ "dtype": "float16",
1225
+ "shape": [1536],
1226
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1227
+ }
1228
+ },
1229
+ "outputs": { "yT": { "dtype": "float16", "shape": [15, 128], "tolerance": 0.001, "relTolerance": 0.001 } },
1230
+ "provenance": {
1231
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1232
+ },
1233
+ "tunables": { "SGMAT_TILE_COLS": 64, "SGMAT_TILE_K": 16 }
1234
+ },
1235
+ {
1236
+ "name": "matrix_tunable_float16_q1_m128_k192_n128_64_16",
1237
+ "attrs": { "K": 192, "N": 128, "block_size": 16, "quant_type": 1 },
1238
+ "inputs": {
1239
+ "aT": {
1240
+ "dtype": "float16",
1241
+ "shape": [128, 192],
1242
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1243
+ },
1244
+ "bT": {
1245
+ "dtype": "uint8",
1246
+ "shape": [12288],
1247
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1248
+ },
1249
+ "absmaxT": {
1250
+ "dtype": "float16",
1251
+ "shape": [1536],
1252
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1253
+ }
1254
+ },
1255
+ "outputs": { "yT": { "dtype": "float16", "shape": [128, 128], "tolerance": 0.001, "relTolerance": 0.001 } },
1256
+ "provenance": {
1257
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1258
+ },
1259
+ "tunables": { "SGMAT_TILE_COLS": 64, "SGMAT_TILE_K": 16 }
1260
+ },
1261
+ {
1262
+ "name": "matrix_tunable_float32_q0_m15_k192_n192_96_24",
1263
+ "attrs": { "K": 192, "N": 192, "block_size": 16, "quant_type": 0 },
1264
+ "inputs": {
1265
+ "aT": {
1266
+ "dtype": "float32",
1267
+ "shape": [15, 192],
1268
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1269
+ },
1270
+ "bT": {
1271
+ "dtype": "uint8",
1272
+ "shape": [18432],
1273
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1274
+ },
1275
+ "absmaxT": {
1276
+ "dtype": "float32",
1277
+ "shape": [2304],
1278
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1279
+ }
1280
+ },
1281
+ "outputs": { "yT": { "dtype": "float32", "shape": [15, 192], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1282
+ "provenance": {
1283
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1284
+ },
1285
+ "tunables": { "SGMAT_TILE_COLS": 96, "SGMAT_TILE_K": 24 }
1286
+ },
1287
+ {
1288
+ "name": "matrix_tunable_float32_q0_m128_k192_n192_96_24",
1289
+ "attrs": { "K": 192, "N": 192, "block_size": 16, "quant_type": 0 },
1290
+ "inputs": {
1291
+ "aT": {
1292
+ "dtype": "float32",
1293
+ "shape": [128, 192],
1294
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1295
+ },
1296
+ "bT": {
1297
+ "dtype": "uint8",
1298
+ "shape": [18432],
1299
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1300
+ },
1301
+ "absmaxT": {
1302
+ "dtype": "float32",
1303
+ "shape": [2304],
1304
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1305
+ }
1306
+ },
1307
+ "outputs": { "yT": { "dtype": "float32", "shape": [128, 192], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1308
+ "provenance": {
1309
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1310
+ },
1311
+ "tunables": { "SGMAT_TILE_COLS": 96, "SGMAT_TILE_K": 24 }
1312
+ },
1313
+ {
1314
+ "name": "matrix_tunable_float16_q1_m15_k192_n256_128_64",
1315
+ "attrs": { "K": 192, "N": 256, "block_size": 16, "quant_type": 1 },
1316
+ "inputs": {
1317
+ "aT": {
1318
+ "dtype": "float16",
1319
+ "shape": [15, 192],
1320
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1321
+ },
1322
+ "bT": {
1323
+ "dtype": "uint8",
1324
+ "shape": [24576],
1325
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1326
+ },
1327
+ "absmaxT": {
1328
+ "dtype": "float16",
1329
+ "shape": [3072],
1330
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1331
+ }
1332
+ },
1333
+ "outputs": { "yT": { "dtype": "float16", "shape": [15, 256], "tolerance": 0.001, "relTolerance": 0.001 } },
1334
+ "provenance": {
1335
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1336
+ },
1337
+ "tunables": { "SGMAT_TILE_COLS": 128, "SGMAT_TILE_K": 64 }
1338
+ },
1339
+ {
1340
+ "name": "matrix_tunable_float16_q1_m128_k192_n256_128_64",
1341
+ "attrs": { "K": 192, "N": 256, "block_size": 16, "quant_type": 1 },
1342
+ "inputs": {
1343
+ "aT": {
1344
+ "dtype": "float16",
1345
+ "shape": [128, 192],
1346
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1347
+ },
1348
+ "bT": {
1349
+ "dtype": "uint8",
1350
+ "shape": [24576],
1351
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1352
+ },
1353
+ "absmaxT": {
1354
+ "dtype": "float16",
1355
+ "shape": [3072],
1356
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1357
+ }
1358
+ },
1359
+ "outputs": { "yT": { "dtype": "float16", "shape": [128, 256], "tolerance": 0.001, "relTolerance": 0.001 } },
1360
+ "provenance": {
1361
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1362
+ },
1363
+ "tunables": { "SGMAT_TILE_COLS": 128, "SGMAT_TILE_K": 64 }
1364
+ },
1365
+ {
1366
+ "name": "matrix_tunable_float32_q0_m15_k192_n64_32_64",
1367
+ "attrs": { "K": 192, "N": 64, "block_size": 16, "quant_type": 0 },
1368
+ "inputs": {
1369
+ "aT": {
1370
+ "dtype": "float32",
1371
+ "shape": [15, 192],
1372
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1373
+ },
1374
+ "bT": {
1375
+ "dtype": "uint8",
1376
+ "shape": [6144],
1377
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1378
+ },
1379
+ "absmaxT": {
1380
+ "dtype": "float32",
1381
+ "shape": [768],
1382
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1383
+ }
1384
+ },
1385
+ "outputs": { "yT": { "dtype": "float32", "shape": [15, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1386
+ "provenance": {
1387
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1388
+ },
1389
+ "tunables": { "SGMAT_TILE_COLS": 32, "SGMAT_TILE_K": 64 }
1390
+ },
1391
+ {
1392
+ "name": "matrix_tunable_float32_q0_m128_k192_n64_32_64",
1393
+ "attrs": { "K": 192, "N": 64, "block_size": 16, "quant_type": 0 },
1394
+ "inputs": {
1395
+ "aT": {
1396
+ "dtype": "float32",
1397
+ "shape": [128, 192],
1398
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1399
+ },
1400
+ "bT": {
1401
+ "dtype": "uint8",
1402
+ "shape": [6144],
1403
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1404
+ },
1405
+ "absmaxT": {
1406
+ "dtype": "float32",
1407
+ "shape": [768],
1408
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1409
+ }
1410
+ },
1411
+ "outputs": { "yT": { "dtype": "float32", "shape": [128, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1412
+ "provenance": {
1413
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1414
+ },
1415
+ "tunables": { "SGMAT_TILE_COLS": 32, "SGMAT_TILE_K": 64 }
1416
+ },
1417
+ {
1418
+ "name": "matrix_tunable_float16_q1_m15_k192_n256_128_8",
1419
+ "attrs": { "K": 192, "N": 256, "block_size": 16, "quant_type": 1 },
1420
+ "inputs": {
1421
+ "aT": {
1422
+ "dtype": "float16",
1423
+ "shape": [15, 192],
1424
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1425
+ },
1426
+ "bT": {
1427
+ "dtype": "uint8",
1428
+ "shape": [24576],
1429
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1430
+ },
1431
+ "absmaxT": {
1432
+ "dtype": "float16",
1433
+ "shape": [3072],
1434
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1435
+ }
1436
+ },
1437
+ "outputs": { "yT": { "dtype": "float16", "shape": [15, 256], "tolerance": 0.001, "relTolerance": 0.001 } },
1438
+ "provenance": {
1439
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1440
+ },
1441
+ "tunables": { "SGMAT_TILE_COLS": 128, "SGMAT_TILE_K": 8 }
1442
+ },
1443
+ {
1444
+ "name": "matrix_tunable_float16_q1_m128_k192_n256_128_8",
1445
+ "attrs": { "K": 192, "N": 256, "block_size": 16, "quant_type": 1 },
1446
+ "inputs": {
1447
+ "aT": {
1448
+ "dtype": "float16",
1449
+ "shape": [128, 192],
1450
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1451
+ },
1452
+ "bT": {
1453
+ "dtype": "uint8",
1454
+ "shape": [24576],
1455
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1456
+ },
1457
+ "absmaxT": {
1458
+ "dtype": "float16",
1459
+ "shape": [3072],
1460
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1461
+ }
1462
+ },
1463
+ "outputs": { "yT": { "dtype": "float16", "shape": [128, 256], "tolerance": 0.001, "relTolerance": 0.001 } },
1464
+ "provenance": {
1465
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1466
+ },
1467
+ "tunables": { "SGMAT_TILE_COLS": 128, "SGMAT_TILE_K": 8 }
1468
+ },
1469
+ {
1470
+ "name": "matrix_tunable_float32_q0_m15_k192_n128_64_24",
1471
+ "attrs": { "K": 192, "N": 128, "block_size": 16, "quant_type": 0 },
1472
+ "inputs": {
1473
+ "aT": {
1474
+ "dtype": "float32",
1475
+ "shape": [15, 192],
1476
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1477
+ },
1478
+ "bT": {
1479
+ "dtype": "uint8",
1480
+ "shape": [12288],
1481
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1482
+ },
1483
+ "absmaxT": {
1484
+ "dtype": "float32",
1485
+ "shape": [1536],
1486
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1487
+ }
1488
+ },
1489
+ "outputs": { "yT": { "dtype": "float32", "shape": [15, 128], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1490
+ "provenance": {
1491
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1492
+ },
1493
+ "tunables": { "SGMAT_TILE_COLS": 64, "SGMAT_TILE_K": 24 }
1494
+ },
1495
+ {
1496
+ "name": "matrix_tunable_float32_q0_m128_k192_n128_64_24",
1497
+ "attrs": { "K": 192, "N": 128, "block_size": 16, "quant_type": 0 },
1498
+ "inputs": {
1499
+ "aT": {
1500
+ "dtype": "float32",
1501
+ "shape": [128, 192],
1502
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1503
+ },
1504
+ "bT": {
1505
+ "dtype": "uint8",
1506
+ "shape": [12288],
1507
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1508
+ },
1509
+ "absmaxT": {
1510
+ "dtype": "float32",
1511
+ "shape": [1536],
1512
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1513
+ }
1514
+ },
1515
+ "outputs": { "yT": { "dtype": "float32", "shape": [128, 128], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1516
+ "provenance": {
1517
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1518
+ },
1519
+ "tunables": { "SGMAT_TILE_COLS": 64, "SGMAT_TILE_K": 24 }
1520
+ },
1521
+ {
1522
+ "name": "matrix_tunable_float16_q1_m15_k192_n192_96_16",
1523
+ "attrs": { "K": 192, "N": 192, "block_size": 16, "quant_type": 1 },
1524
+ "inputs": {
1525
+ "aT": {
1526
+ "dtype": "float16",
1527
+ "shape": [15, 192],
1528
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1529
+ },
1530
+ "bT": {
1531
+ "dtype": "uint8",
1532
+ "shape": [18432],
1533
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1534
+ },
1535
+ "absmaxT": {
1536
+ "dtype": "float16",
1537
+ "shape": [2304],
1538
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1539
+ }
1540
+ },
1541
+ "outputs": { "yT": { "dtype": "float16", "shape": [15, 192], "tolerance": 0.001, "relTolerance": 0.001 } },
1542
+ "provenance": {
1543
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1544
+ },
1545
+ "tunables": { "SGMAT_TILE_COLS": 96, "SGMAT_TILE_K": 16 }
1546
+ },
1547
+ {
1548
+ "name": "matrix_tunable_float16_q1_m128_k192_n192_96_16",
1549
+ "attrs": { "K": 192, "N": 192, "block_size": 16, "quant_type": 1 },
1550
+ "inputs": {
1551
+ "aT": {
1552
+ "dtype": "float16",
1553
+ "shape": [128, 192],
1554
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1555
+ },
1556
+ "bT": {
1557
+ "dtype": "uint8",
1558
+ "shape": [18432],
1559
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1560
+ },
1561
+ "absmaxT": {
1562
+ "dtype": "float16",
1563
+ "shape": [2304],
1564
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1565
+ }
1566
+ },
1567
+ "outputs": { "yT": { "dtype": "float16", "shape": [128, 192], "tolerance": 0.001, "relTolerance": 0.001 } },
1568
+ "provenance": {
1569
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1570
+ },
1571
+ "tunables": { "SGMAT_TILE_COLS": 96, "SGMAT_TILE_K": 16 }
1572
+ },
1573
+ {
1574
+ "name": "row_and_weight_tails_float32_q1_m9_k31_n65",
1575
+ "attrs": { "K": 31, "N": 65, "block_size": 16, "quant_type": 1 },
1576
+ "inputs": {
1577
+ "aT": {
1578
+ "dtype": "float32",
1579
+ "shape": [9, 31],
1580
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1581
+ },
1582
+ "bT": {
1583
+ "dtype": "uint8",
1584
+ "shape": [1008],
1585
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1586
+ },
1587
+ "absmaxT": {
1588
+ "dtype": "float32",
1589
+ "shape": [126],
1590
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1591
+ }
1592
+ },
1593
+ "outputs": { "yT": { "dtype": "float32", "shape": [9, 65], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1594
+ "provenance": {
1595
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1596
+ }
1597
+ },
1598
+ {
1599
+ "name": "row_and_weight_tails_float32_q1_m33_k129_n127",
1600
+ "attrs": { "K": 129, "N": 127, "block_size": 16, "quant_type": 1 },
1601
+ "inputs": {
1602
+ "aT": {
1603
+ "dtype": "float32",
1604
+ "shape": [33, 129],
1605
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1606
+ },
1607
+ "bT": {
1608
+ "dtype": "uint8",
1609
+ "shape": [8192],
1610
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1611
+ },
1612
+ "absmaxT": {
1613
+ "dtype": "float32",
1614
+ "shape": [1024],
1615
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1616
+ }
1617
+ },
1618
+ "outputs": { "yT": { "dtype": "float32", "shape": [33, 127], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1619
+ "provenance": {
1620
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1621
+ }
1622
+ },
1623
+ {
1624
+ "name": "row_and_weight_tails_float16_q1_m9_k31_n65",
1625
+ "attrs": { "K": 31, "N": 65, "block_size": 16, "quant_type": 1 },
1626
+ "inputs": {
1627
+ "aT": {
1628
+ "dtype": "float16",
1629
+ "shape": [9, 31],
1630
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1631
+ },
1632
+ "bT": {
1633
+ "dtype": "uint8",
1634
+ "shape": [1008],
1635
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1636
+ },
1637
+ "absmaxT": {
1638
+ "dtype": "float16",
1639
+ "shape": [126],
1640
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1641
+ }
1642
+ },
1643
+ "outputs": { "yT": { "dtype": "float16", "shape": [9, 65], "tolerance": 0.001, "relTolerance": 0.001 } },
1644
+ "provenance": {
1645
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1646
+ }
1647
+ },
1648
+ {
1649
+ "name": "row_and_weight_tails_float16_q1_m33_k129_n127",
1650
+ "attrs": { "K": 129, "N": 127, "block_size": 16, "quant_type": 1 },
1651
+ "inputs": {
1652
+ "aT": {
1653
+ "dtype": "float16",
1654
+ "shape": [33, 129],
1655
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1656
+ },
1657
+ "bT": {
1658
+ "dtype": "uint8",
1659
+ "shape": [8192],
1660
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1661
+ },
1662
+ "absmaxT": {
1663
+ "dtype": "float16",
1664
+ "shape": [1024],
1665
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1666
+ }
1667
+ },
1668
+ "outputs": { "yT": { "dtype": "float16", "shape": [33, 127], "tolerance": 0.001, "relTolerance": 0.001 } },
1669
+ "provenance": {
1670
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1671
+ }
1672
+ },
1673
+ {
1674
+ "name": "portable_f16_tunable_float16_q0_m17_k129_n65_32",
1675
+ "attrs": { "K": 129, "N": 65, "block_size": 16, "quant_type": 0 },
1676
+ "inputs": {
1677
+ "aT": {
1678
+ "dtype": "float16",
1679
+ "shape": [17, 129],
1680
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1681
+ },
1682
+ "bT": {
1683
+ "dtype": "uint8",
1684
+ "shape": [4193],
1685
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1686
+ },
1687
+ "absmaxT": {
1688
+ "dtype": "float16",
1689
+ "shape": [525],
1690
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1691
+ }
1692
+ },
1693
+ "outputs": { "yT": { "dtype": "float16", "shape": [17, 65], "tolerance": 0.001, "relTolerance": 0.001 } },
1694
+ "provenance": {
1695
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1696
+ },
1697
+ "tunables": { "PORTABLE_TILE_K": 32 }
1698
+ },
1699
+ {
1700
+ "name": "portable_f16_tunable_float16_q0_m17_k129_n65_64",
1701
+ "attrs": { "K": 129, "N": 65, "block_size": 16, "quant_type": 0 },
1702
+ "inputs": {
1703
+ "aT": {
1704
+ "dtype": "float16",
1705
+ "shape": [17, 129],
1706
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1707
+ },
1708
+ "bT": {
1709
+ "dtype": "uint8",
1710
+ "shape": [4193],
1711
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1712
+ },
1713
+ "absmaxT": {
1714
+ "dtype": "float16",
1715
+ "shape": [525],
1716
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1717
+ }
1718
+ },
1719
+ "outputs": { "yT": { "dtype": "float16", "shape": [17, 65], "tolerance": 0.001, "relTolerance": 0.001 } },
1720
+ "provenance": {
1721
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1722
+ },
1723
+ "tunables": { "PORTABLE_TILE_K": 64 }
1724
+ },
1725
+ {
1726
+ "name": "empty_rows_float32_q1_m0_k32_n64",
1727
+ "attrs": { "K": 32, "N": 64, "block_size": 16, "quant_type": 1 },
1728
+ "inputs": {
1729
+ "aT": {
1730
+ "dtype": "float32",
1731
+ "shape": [0, 32],
1732
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1733
+ },
1734
+ "bT": {
1735
+ "dtype": "uint8",
1736
+ "shape": [1024],
1737
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1738
+ },
1739
+ "absmaxT": {
1740
+ "dtype": "float32",
1741
+ "shape": [128],
1742
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1743
+ }
1744
+ },
1745
+ "outputs": { "yT": { "dtype": "float32", "shape": [0, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1746
+ "provenance": {
1747
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1748
+ }
1749
+ },
1750
+ {
1751
+ "name": "empty_rows_float16_q1_m0_k32_n64",
1752
+ "attrs": { "K": 32, "N": 64, "block_size": 16, "quant_type": 1 },
1753
+ "inputs": {
1754
+ "aT": {
1755
+ "dtype": "float16",
1756
+ "shape": [0, 32],
1757
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1758
+ },
1759
+ "bT": {
1760
+ "dtype": "uint8",
1761
+ "shape": [1024],
1762
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1763
+ },
1764
+ "absmaxT": {
1765
+ "dtype": "float16",
1766
+ "shape": [128],
1767
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1768
+ }
1769
+ },
1770
+ "outputs": { "yT": { "dtype": "float16", "shape": [0, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
1771
+ "provenance": {
1772
+ "notes": "Covers row-tile boundaries, f32 accumulation and position-varying NF4/FP4 weights on matrix and portable capability tiers."
1773
+ }
1774
+ },
1775
+ {
1776
+ "name": "prefix_tail_float32_m95_k64_n64",
1777
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
1778
+ "inputs": {
1779
+ "aT": {
1780
+ "dtype": "float32",
1781
+ "shape": [95, 64],
1782
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1783
+ },
1784
+ "bT": {
1785
+ "dtype": "uint8",
1786
+ "shape": [2048],
1787
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1788
+ },
1789
+ "absmaxT": {
1790
+ "dtype": "float32",
1791
+ "shape": [256],
1792
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1793
+ }
1794
+ },
1795
+ "outputs": { "yT": { "dtype": "float32", "shape": [95, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1796
+ "provenance": {
1797
+ "notes": "The full-row prefix and a multi-fragment tail write disjoint rows, including the last output, with f32 accumulation."
1798
+ }
1799
+ },
1800
+ {
1801
+ "name": "prefix_tail_float32_m191_k64_n64",
1802
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
1803
+ "inputs": {
1804
+ "aT": {
1805
+ "dtype": "float32",
1806
+ "shape": [191, 64],
1807
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1808
+ },
1809
+ "bT": {
1810
+ "dtype": "uint8",
1811
+ "shape": [2048],
1812
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1813
+ },
1814
+ "absmaxT": {
1815
+ "dtype": "float32",
1816
+ "shape": [256],
1817
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1818
+ }
1819
+ },
1820
+ "outputs": { "yT": { "dtype": "float32", "shape": [191, 64], "tolerance": 0.00002, "relTolerance": 0.00001 } },
1821
+ "provenance": {
1822
+ "notes": "The full-row prefix and a multi-fragment tail write disjoint rows, including the last output, with f32 accumulation."
1823
+ }
1824
+ },
1825
+ {
1826
+ "name": "prefix_tail_float16_m95_k64_n64",
1827
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
1828
+ "inputs": {
1829
+ "aT": {
1830
+ "dtype": "float16",
1831
+ "shape": [95, 64],
1832
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1833
+ },
1834
+ "bT": {
1835
+ "dtype": "uint8",
1836
+ "shape": [2048],
1837
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1838
+ },
1839
+ "absmaxT": {
1840
+ "dtype": "float16",
1841
+ "shape": [256],
1842
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1843
+ }
1844
+ },
1845
+ "outputs": { "yT": { "dtype": "float16", "shape": [95, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
1846
+ "provenance": {
1847
+ "notes": "The full-row prefix and a multi-fragment tail write disjoint rows, including the last output, with f32 accumulation."
1848
+ }
1849
+ },
1850
+ {
1851
+ "name": "prefix_tail_float16_m191_k64_n64",
1852
+ "attrs": { "K": 64, "N": 64, "block_size": 16, "quant_type": 0 },
1853
+ "inputs": {
1854
+ "aT": {
1855
+ "dtype": "float16",
1856
+ "shape": [191, 64],
1857
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1858
+ },
1859
+ "bT": {
1860
+ "dtype": "uint8",
1861
+ "shape": [2048],
1862
+ "data": { "kind": "cycle", "values": { "$ref": "#/fixtureArrays/bnb4_weight_cycle_b_t" } }
1863
+ },
1864
+ "absmaxT": {
1865
+ "dtype": "float16",
1866
+ "shape": [256],
1867
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.07, "scale": 0.02, "offset": 0.06 }
1868
+ }
1869
+ },
1870
+ "outputs": { "yT": { "dtype": "float16", "shape": [191, 64], "tolerance": 0.001, "relTolerance": 0.001 } },
1871
+ "provenance": {
1872
+ "notes": "The full-row prefix and a multi-fragment tail write disjoint rows, including the last output, with f32 accumulation."
1873
+ }
1874
  }
1875
  ]
1876
  }