Xenova HF Staff commited on
Commit
f1a8138
·
verified ·
1 Parent(s): 69e74ac

sync 91d990483a17

Browse files
README.md CHANGED
@@ -18,19 +18,19 @@ See the [ONNX Runtime `SkipSimplifiedLayerNormalization` contrib-operator spec](
18
 
19
  ## Inputs
20
 
21
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
22
  | --- | --- | --- | --- | --- | --- | --- |
23
- | `input` | `inputT` | `T` | — | — | Input tensor of shape `(token_count, hidden_size)` or `(batch, sequence, hidden_size)`, normalized over the last axis. | required |
24
- | `skip` | `skipT` | `T` | — | — | Residual tensor of the same shape as `input`, added before normalization. | required |
25
- | `gamma` | `gammaT` | `T` | `1` | — | 1-D scale tensor with shape `(hidden_size)` applied after normalization. | required |
26
- | `bias` | `biasT` | `T` | `1` | — | Optional 1-D bias tensor with shape `(hidden_size)` added to the `input + skip` sum. | optional |
27
 
28
  ## Outputs
29
 
30
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
31
  | --- | --- | --- | --- | --- | --- | --- |
32
- | `output` | `outputT` | `T` | same as `input` | same as `input` | Normalized output tensor with the same shape as `input`. | required |
33
- | `input_skip_bias_sum` | `residualT` | `T` | same as `input` | same as `input` | Sum of `input`, `skip`, and optional `bias` before normalization, with the same shape as `input`. | optional |
34
 
35
  ## Attributes
36
 
@@ -52,7 +52,7 @@ Some implementation variants require `shader-f16`. These are route-specific capa
52
 
53
  ## Files
54
 
55
- - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
56
  - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
57
  - [`test.json`](build/webgpu/test.json) — correctness cases
58
  - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
@@ -61,10 +61,14 @@ Some implementation variants require `shader-f16`. These are route-specific capa
61
 
62
  ## Use with `@huggingface/kernels`
63
 
64
- The loader derives every required output's shape and logical dtype from the manifest contract and this call.
65
- It then allocates the result tensors automatically.
 
 
 
66
 
67
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
 
68
 
69
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
70
 
 
18
 
19
  ## Inputs
20
 
21
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
22
  | --- | --- | --- | --- | --- | --- | --- |
23
+ | `inputT` | `input` | `T` | — | — | Input tensor of shape `(token_count, hidden_size)` or `(batch, sequence, hidden_size)`, normalized over the last axis. | required |
24
+ | `skipT` | `skip` | `T` | — | — | Residual tensor of the same shape as `input`, added before normalization. | required |
25
+ | `gammaT` | `gamma` | `T` | `1` | — | 1-D scale tensor with shape `(hidden_size)` applied after normalization. | required |
26
+ | `biasT` | `bias` | `T` | `1` | — | Optional 1-D bias tensor with shape `(hidden_size)` added to the `input + skip` sum. | optional |
27
 
28
  ## Outputs
29
 
30
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
31
  | --- | --- | --- | --- | --- | --- | --- |
32
+ | `outputT` | `output` | `T` | same as `inputT` | same as `inputT` | Normalized output tensor with the same shape as `input`. | required |
33
+ | `residualT` | `input_skip_bias_sum` | `T` | same as `inputT` | same as `inputT` | Sum of `input`, `skip`, and optional `bias` before normalization, with the same shape as `input`. | optional |
34
 
35
  ## Attributes
36
 
 
52
 
53
  ## Files
54
 
55
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, provenance)
56
  - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
57
  - [`test.json`](build/webgpu/test.json) — correctness cases
58
  - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
 
61
 
62
  ## Use with `@huggingface/kernels`
63
 
64
+ ```sh
65
+ npm install --save-exact @huggingface/kernels@0.0.1-preview.2
66
+ ```
67
+
68
+ Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
69
 
70
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
71
+ It follows the `v1` branch as fixes land. To pin exact artifact bytes, pass a 40-character commit `revision` instead of `version`.
72
 
73
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
74
 
build/webgpu/bench.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "com.microsoft.SkipSimplifiedLayerNormalization",
3
  "cases": [
4
  {
5
  "name": "skip-rmsnorm-f32-256x128",
@@ -46,7 +45,7 @@
46
  "name": "kimi-linear-prefill-f32-64x2304",
47
  "preset": "model",
48
  "provenance": {
49
- "notes": "Original Kimi Linear hidden_size=2304 at the 64-token recurrent chunk boundary; this is a future vectorized-prefill target because the current graph replays T=1."
50
  },
51
  "vars": { "rows": 64, "hidden": 2304 },
52
  "attrs": { "epsilon": 0.00001 },
@@ -65,7 +64,7 @@
65
  "name": "kimi-linear-prefill-f32-512x2304",
66
  "preset": "model",
67
  "provenance": {
68
- "notes": "Original Kimi Linear hidden_size=2304 representative future vectorized-prefill shape; the current graph replays T=1."
69
  },
70
  "vars": { "rows": 512, "hidden": 2304 },
71
  "attrs": { "epsilon": 0.00001 },
@@ -84,7 +83,7 @@
84
  "name": "kimi-linear-prefill-f32-1024x2304",
85
  "preset": "model",
86
  "provenance": {
87
- "notes": "Original Kimi Linear hidden_size=2304 representative future vectorized-prefill shape; the current graph replays T=1."
88
  },
89
  "vars": { "rows": 1024, "hidden": 2304 },
90
  "attrs": { "epsilon": 0.00001 },
 
1
  {
 
2
  "cases": [
3
  {
4
  "name": "skip-rmsnorm-f32-256x128",
 
45
  "name": "kimi-linear-prefill-f32-64x2304",
46
  "preset": "model",
47
  "provenance": {
48
+ "notes": "Kimi Linear hidden size 2304 at the 64-token recurrent chunk boundary, representing a vectorized-prefill workload."
49
  },
50
  "vars": { "rows": 64, "hidden": 2304 },
51
  "attrs": { "epsilon": 0.00001 },
 
64
  "name": "kimi-linear-prefill-f32-512x2304",
65
  "preset": "model",
66
  "provenance": {
67
+ "notes": "Kimi Linear hidden size 2304 over 512 tokens, representing a vectorized-prefill workload."
68
  },
69
  "vars": { "rows": 512, "hidden": 2304 },
70
  "attrs": { "epsilon": 0.00001 },
 
83
  "name": "kimi-linear-prefill-f32-1024x2304",
84
  "preset": "model",
85
  "provenance": {
86
+ "notes": "Kimi Linear hidden size 2304 over 1,024 tokens, representing a vectorized-prefill workload."
87
  },
88
  "vars": { "rows": 1024, "hidden": 2304 },
89
  "attrs": { "epsilon": 0.00001 },
build/webgpu/manifest.json CHANGED
@@ -2,66 +2,31 @@
2
  "domain": "com.microsoft",
3
  "name": "SkipSimplifiedLayerNormalization",
4
  "sinceVersion": 1,
5
- "description": "Adds `input` and `skip` (plus optional `bias`), then applies RMS normalization scaled by `gamma`. The optional second output exposes the pre-normalization sum. The schema's training-only mean and inverse-standard-deviation outputs are not implemented.",
6
- "inputs": [
7
- {
8
- "role": "input",
9
- "dtype": "T",
10
- "description": "Input tensor of shape `(token_count, hidden_size)` or `(batch, sequence, hidden_size)`, normalized over the last axis."
11
- },
12
- {
13
- "role": "skip",
14
- "dtype": "T",
15
- "description": "Residual tensor of the same shape as `input`, added before normalization."
16
- },
17
- {
18
- "role": "gamma",
19
- "dtype": "T",
20
- "rank": 1,
21
- "description": "1-D scale tensor with shape `(hidden_size)` applied after normalization."
22
- },
23
- {
24
- "role": "bias",
25
- "dtype": "T",
26
- "rank": 1,
27
- "optional": true,
28
- "description": "Optional 1-D bias tensor with shape `(hidden_size)` added to the `input + skip` sum."
29
- }
30
- ],
31
- "outputs": [
32
- {
33
- "role": "output",
34
  "dtype": "T",
35
  "rank": "ranks.inputT",
36
- "shape": "shapes.inputT",
37
- "description": "Normalized output tensor with the same shape as `input`."
38
- },
39
- {
40
- "role": "input_skip_bias_sum",
41
- "dtype": "T",
42
  "optional": true,
43
- "rank": "ranks.inputT",
44
- "shape": "shapes.inputT",
45
- "description": "Sum of `input`, `skip`, and optional `bias` before normalization, with the same shape as `input`."
46
  }
47
- ],
48
- "attributes": { "epsilon": 9.999999960041972e-13 },
49
- "attributeDescriptions": { "epsilon": "Non-negative epsilon added to the mean square before taking the square root." },
50
- "args": {
51
- "inputT": { "kind": "tensor", "semantic": "input", "role": "input" },
52
- "skipT": { "kind": "tensor", "semantic": "skip", "role": "input" },
53
- "gammaT": { "kind": "tensor", "semantic": "gamma", "role": "input" },
54
- "biasT": { "kind": "tensor", "semantic": "bias", "role": "input", "required": false },
55
- "outputT": { "kind": "tensor", "semantic": "output", "role": "output" },
56
- "residualT": { "kind": "tensor", "semantic": "input_skip_bias_sum", "role": "output", "required": false }
57
  },
 
58
  "typeConstraints": { "T": ["float32", "float16"] },
 
59
  "derive": {
60
  "rowCount": "numel(shapes.inputT) / max(1, dim(shapes.inputT, -1))",
61
  "hiddenSize": "dim(shapes.inputT, -1)",
62
  "skipWg": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(hiddenSize)))",
63
  "skipWgVec4": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(ceilDiv(hiddenSize, 4))))",
64
- "rowDispatchFits": "rowCount <= device.limits.maxComputeWorkgroupsPerDimension * device.limits.maxComputeWorkgroupsPerDimension",
65
  "normResourcesFit": "skipWg * 8 <= device.limits.maxComputeWorkgroupStorageSize and skipWgVec4 * 8 <= device.limits.maxComputeWorkgroupStorageSize",
66
  "epsilonOk": "attrs.epsilon >= 0",
67
  "coreContract": "epsilonOk and (ranks.inputT == 2 or ranks.inputT == 3) and ranks.skipT == ranks.inputT and ranks.gammaT == 1 and ranks.outputT == ranks.inputT and sameShape(shapes.inputT, shapes.skipT) and sameShape(shapes.outputT, shapes.inputT) and dim(shapes.inputT, -1) > 0 and dim(shapes.gammaT, 0) == dim(shapes.inputT, -1)",
@@ -86,439 +51,64 @@
86
  "f16_no_bias_output_contract": "hasF16 and coreContract and outputOnlyContract and f16MainDtypes and no_bias_contract",
87
  "f16_bias_output_contract": "hasF16 and coreContract and outputOnlyContract and f16MainDtypes and f16_bias_contract"
88
  },
89
- "bindingSets": {
90
- "vec4_no_bias_residual": [
91
- {
92
- "name": "input",
93
- "arg": "inputT",
94
- "semantic": "input",
95
- "buffer": { "type": "read-only-storage" },
96
- "elementType": "$vectorScalar"
97
- },
98
- {
99
- "name": "skip",
100
- "arg": "skipT",
101
- "semantic": "skip",
102
- "buffer": { "type": "read-only-storage" },
103
- "elementType": "$vectorScalar"
104
- },
105
- {
106
- "name": "gamma",
107
- "arg": "gammaT",
108
- "semantic": "gamma",
109
- "buffer": { "type": "read-only-storage" },
110
- "elementType": "$vectorScalar",
111
- "length": "$HIDDEN_LEN"
112
- },
113
- {
114
- "name": "output",
115
- "arg": "outputT",
116
- "semantic": "output",
117
- "buffer": { "type": "storage" },
118
- "elementType": "$vectorScalar"
119
- },
120
- {
121
- "name": "input_skip_bias_sum",
122
- "arg": "residualT",
123
- "semantic": "input_skip_bias_sum",
124
- "buffer": { "type": "storage" },
125
- "elementType": "$vectorScalar"
126
- },
127
- {
128
- "name": "params",
129
- "semantic": "kernel.params",
130
- "buffer": { "type": "uniform" },
131
- "struct": {
132
- "name": "Params",
133
- "fields": [
134
- { "name": "rows", "type": "u32", "value": "rowCount" },
135
- {
136
- "name": "rowStride",
137
- "type": "u32",
138
- "value": "max(1, min(rowCount, device.limits.maxComputeWorkgroupsPerDimension))"
139
- },
140
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
141
- ]
142
- }
143
- }
144
- ],
145
- "vec4_bias_residual": [
146
- {
147
- "name": "input",
148
- "arg": "inputT",
149
- "semantic": "input",
150
- "buffer": { "type": "read-only-storage" },
151
- "elementType": "$vectorScalar"
152
- },
153
- {
154
- "name": "skip",
155
- "arg": "skipT",
156
- "semantic": "skip",
157
- "buffer": { "type": "read-only-storage" },
158
- "elementType": "$vectorScalar"
159
- },
160
- {
161
- "name": "gamma",
162
- "arg": "gammaT",
163
- "semantic": "gamma",
164
- "buffer": { "type": "read-only-storage" },
165
- "elementType": "$vectorScalar",
166
- "length": "$HIDDEN_LEN"
167
- },
168
- {
169
- "name": "bias",
170
- "arg": "biasT",
171
- "semantic": "bias",
172
- "buffer": { "type": "read-only-storage" },
173
- "elementType": "$vectorScalar",
174
- "length": "$HIDDEN_LEN"
175
- },
176
- {
177
- "name": "output",
178
- "arg": "outputT",
179
- "semantic": "output",
180
- "buffer": { "type": "storage" },
181
- "elementType": "$vectorScalar"
182
- },
183
- {
184
- "name": "input_skip_bias_sum",
185
- "arg": "residualT",
186
- "semantic": "input_skip_bias_sum",
187
- "buffer": { "type": "storage" },
188
- "elementType": "$vectorScalar"
189
- },
190
- {
191
- "name": "params",
192
- "semantic": "kernel.params",
193
- "buffer": { "type": "uniform" },
194
- "struct": {
195
- "name": "Params",
196
- "fields": [
197
- { "name": "rows", "type": "u32", "value": "rowCount" },
198
- {
199
- "name": "rowStride",
200
- "type": "u32",
201
- "value": "max(1, min(rowCount, device.limits.maxComputeWorkgroupsPerDimension))"
202
- },
203
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
204
- ]
205
- }
206
- }
207
- ],
208
- "vec4_no_bias_output_only": [
209
- {
210
- "name": "input",
211
- "arg": "inputT",
212
- "semantic": "input",
213
- "buffer": { "type": "read-only-storage" },
214
- "elementType": "$vectorScalar"
215
- },
216
- {
217
- "name": "skip",
218
- "arg": "skipT",
219
- "semantic": "skip",
220
- "buffer": { "type": "read-only-storage" },
221
- "elementType": "$vectorScalar"
222
- },
223
- {
224
- "name": "gamma",
225
- "arg": "gammaT",
226
- "semantic": "gamma",
227
- "buffer": { "type": "read-only-storage" },
228
- "elementType": "$vectorScalar",
229
- "length": "$HIDDEN_LEN"
230
- },
231
- {
232
- "name": "output",
233
- "arg": "outputT",
234
- "semantic": "output",
235
- "buffer": { "type": "storage" },
236
- "elementType": "$vectorScalar"
237
- },
238
- {
239
- "name": "params",
240
- "semantic": "kernel.params",
241
- "buffer": { "type": "uniform" },
242
- "struct": {
243
- "name": "Params",
244
- "fields": [
245
- { "name": "rows", "type": "u32", "value": "rowCount" },
246
- {
247
- "name": "rowStride",
248
- "type": "u32",
249
- "value": "max(1, min(rowCount, device.limits.maxComputeWorkgroupsPerDimension))"
250
- },
251
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
252
- ]
253
- }
254
- }
255
- ],
256
- "vec4_bias_output_only": [
257
- {
258
- "name": "input",
259
- "arg": "inputT",
260
- "semantic": "input",
261
- "buffer": { "type": "read-only-storage" },
262
- "elementType": "$vectorScalar"
263
- },
264
- {
265
- "name": "skip",
266
- "arg": "skipT",
267
- "semantic": "skip",
268
- "buffer": { "type": "read-only-storage" },
269
- "elementType": "$vectorScalar"
270
- },
271
- {
272
- "name": "gamma",
273
- "arg": "gammaT",
274
- "semantic": "gamma",
275
- "buffer": { "type": "read-only-storage" },
276
- "elementType": "$vectorScalar",
277
- "length": "$HIDDEN_LEN"
278
- },
279
- {
280
- "name": "bias",
281
- "arg": "biasT",
282
- "semantic": "bias",
283
- "buffer": { "type": "read-only-storage" },
284
- "elementType": "$vectorScalar",
285
- "length": "$HIDDEN_LEN"
286
- },
287
- {
288
- "name": "output",
289
- "arg": "outputT",
290
- "semantic": "output",
291
- "buffer": { "type": "storage" },
292
- "elementType": "$vectorScalar"
293
- },
294
- {
295
- "name": "params",
296
- "semantic": "kernel.params",
297
- "buffer": { "type": "uniform" },
298
- "struct": {
299
- "name": "Params",
300
- "fields": [
301
- { "name": "rows", "type": "u32", "value": "rowCount" },
302
- {
303
- "name": "rowStride",
304
- "type": "u32",
305
- "value": "max(1, min(rowCount, device.limits.maxComputeWorkgroupsPerDimension))"
306
- },
307
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
308
- ]
309
- }
310
- }
311
- ],
312
- "scalar_no_bias_residual": [
313
- {
314
- "name": "input",
315
- "arg": "inputT",
316
- "semantic": "input",
317
- "buffer": { "type": "read-only-storage" },
318
- "elementType": "$scalar"
319
- },
320
- {
321
- "name": "skip",
322
- "arg": "skipT",
323
- "semantic": "skip",
324
- "buffer": { "type": "read-only-storage" },
325
- "elementType": "$scalar"
326
- },
327
- {
328
- "name": "gamma",
329
- "arg": "gammaT",
330
- "semantic": "gamma",
331
- "buffer": { "type": "read-only-storage" },
332
- "elementType": "$scalar",
333
- "length": "$HIDDEN_LEN"
334
- },
335
- {
336
- "name": "output",
337
- "arg": "outputT",
338
- "semantic": "output",
339
- "buffer": { "type": "storage" },
340
- "elementType": "$scalar"
341
- },
342
- {
343
- "name": "input_skip_bias_sum",
344
- "arg": "residualT",
345
- "semantic": "input_skip_bias_sum",
346
- "buffer": { "type": "storage" },
347
- "elementType": "$scalar"
348
- },
349
- {
350
- "name": "params",
351
- "semantic": "kernel.params",
352
- "buffer": { "type": "uniform" },
353
- "struct": {
354
- "name": "Params",
355
- "fields": [
356
- { "name": "rows", "type": "u32", "value": "rowCount" },
357
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
358
- ]
359
- }
360
- }
361
- ],
362
- "scalar_bias_residual": [
363
- {
364
- "name": "input",
365
- "arg": "inputT",
366
- "semantic": "input",
367
- "buffer": { "type": "read-only-storage" },
368
- "elementType": "$scalar"
369
- },
370
- {
371
- "name": "skip",
372
- "arg": "skipT",
373
- "semantic": "skip",
374
- "buffer": { "type": "read-only-storage" },
375
- "elementType": "$scalar"
376
- },
377
- {
378
- "name": "gamma",
379
- "arg": "gammaT",
380
- "semantic": "gamma",
381
- "buffer": { "type": "read-only-storage" },
382
- "elementType": "$scalar",
383
- "length": "$HIDDEN_LEN"
384
- },
385
- {
386
- "name": "bias",
387
- "arg": "biasT",
388
- "semantic": "bias",
389
- "buffer": { "type": "read-only-storage" },
390
- "elementType": "$scalar",
391
- "length": "$HIDDEN_LEN"
392
- },
393
- {
394
- "name": "output",
395
- "arg": "outputT",
396
- "semantic": "output",
397
- "buffer": { "type": "storage" },
398
- "elementType": "$scalar"
399
- },
400
- {
401
- "name": "input_skip_bias_sum",
402
- "arg": "residualT",
403
- "semantic": "input_skip_bias_sum",
404
- "buffer": { "type": "storage" },
405
- "elementType": "$scalar"
406
- },
407
- {
408
- "name": "params",
409
- "semantic": "kernel.params",
410
- "buffer": { "type": "uniform" },
411
- "struct": {
412
- "name": "Params",
413
- "fields": [
414
- { "name": "rows", "type": "u32", "value": "rowCount" },
415
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
416
- ]
417
- }
418
- }
419
- ],
420
- "scalar_no_bias_output_only": [
421
- {
422
- "name": "input",
423
- "arg": "inputT",
424
- "semantic": "input",
425
- "buffer": { "type": "read-only-storage" },
426
- "elementType": "$scalar"
427
- },
428
- {
429
- "name": "skip",
430
- "arg": "skipT",
431
- "semantic": "skip",
432
- "buffer": { "type": "read-only-storage" },
433
- "elementType": "$scalar"
434
- },
435
- {
436
- "name": "gamma",
437
- "arg": "gammaT",
438
- "semantic": "gamma",
439
- "buffer": { "type": "read-only-storage" },
440
- "elementType": "$scalar",
441
- "length": "$HIDDEN_LEN"
442
- },
443
- {
444
- "name": "output",
445
- "arg": "outputT",
446
- "semantic": "output",
447
- "buffer": { "type": "storage" },
448
- "elementType": "$scalar"
449
- },
450
- {
451
- "name": "params",
452
- "semantic": "kernel.params",
453
- "buffer": { "type": "uniform" },
454
- "struct": {
455
- "name": "Params",
456
- "fields": [
457
- { "name": "rows", "type": "u32", "value": "rowCount" },
458
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
459
- ]
460
- }
461
- }
462
- ],
463
- "scalar_bias_output_only": [
464
- {
465
- "name": "input",
466
- "arg": "inputT",
467
- "semantic": "input",
468
- "buffer": { "type": "read-only-storage" },
469
- "elementType": "$scalar"
470
- },
471
- {
472
- "name": "skip",
473
- "arg": "skipT",
474
- "semantic": "skip",
475
- "buffer": { "type": "read-only-storage" },
476
- "elementType": "$scalar"
477
- },
478
- {
479
- "name": "gamma",
480
- "arg": "gammaT",
481
- "semantic": "gamma",
482
- "buffer": { "type": "read-only-storage" },
483
- "elementType": "$scalar",
484
- "length": "$HIDDEN_LEN"
485
- },
486
- {
487
- "name": "bias",
488
- "arg": "biasT",
489
- "semantic": "bias",
490
- "buffer": { "type": "read-only-storage" },
491
- "elementType": "$scalar",
492
- "length": "$HIDDEN_LEN"
493
- },
494
- {
495
- "name": "output",
496
- "arg": "outputT",
497
- "semantic": "output",
498
- "buffer": { "type": "storage" },
499
- "elementType": "$scalar"
500
- },
501
- {
502
- "name": "params",
503
- "semantic": "kernel.params",
504
- "buffer": { "type": "uniform" },
505
- "struct": {
506
- "name": "Params",
507
- "fields": [
508
- { "name": "rows", "type": "u32", "value": "rowCount" },
509
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
510
- ]
511
- }
512
- }
513
- ]
514
  },
515
- "tunables": { "MAX_WORKGROUP_SIZE": 256 },
516
  "variants": [
517
  {
518
  "id": "no_bias_vec4_f16",
519
  "priority": 21,
520
- "when": ["f16_no_bias_residual_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
521
- "constants": {
522
  "scalar": "\"f16\"",
523
  "vectorScalar": "\"vec4<f16>\"",
524
  "hasBias": "\"no_bias\" == \"bias\"",
@@ -528,32 +118,30 @@
528
  {
529
  "id": "main",
530
  "name": "SkipSimplifiedLayerNormalization.Vec4",
531
- "source": {
532
- "shader": "norm-skip-row-vec4.wgsl.jinja",
533
- "inputs": {
534
- "simplified": true,
535
- "hasBias": "\"no_bias\" == \"bias\"",
536
- "hasBeta": false,
537
- "writeResidualSum": true,
538
- "usesF16": true,
539
- "hidden": "hiddenSize",
540
- "hiddenVec": "hiddenSize / 4",
541
- "wg": "skipWgVec4",
542
- "vecType": "\"vec4<f16>\"",
543
- "useSubgroups": "hasSubgroups"
544
- }
545
  },
546
- "subgroupCollectivesWidth": "portable",
547
- "bindings": "vec4_no_bias_residual",
548
- "dispatch": { "workgroups": "rowCount" }
549
  }
550
  ]
551
  },
552
  {
553
  "id": "no_bias_vec4",
554
  "priority": 20,
555
- "when": ["f32_no_bias_residual_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
556
- "constants": {
557
  "scalar": "\"f32\"",
558
  "vectorScalar": "\"vec4<f32>\"",
559
  "hasBias": "\"no_bias\" == \"bias\"",
@@ -563,32 +151,30 @@
563
  {
564
  "id": "main",
565
  "name": "SkipSimplifiedLayerNormalization.Vec4",
566
- "source": {
567
- "shader": "norm-skip-row-vec4.wgsl.jinja",
568
- "inputs": {
569
- "simplified": true,
570
- "hasBias": "\"no_bias\" == \"bias\"",
571
- "hasBeta": false,
572
- "writeResidualSum": true,
573
- "usesF16": false,
574
- "hidden": "hiddenSize",
575
- "hiddenVec": "hiddenSize / 4",
576
- "wg": "skipWgVec4",
577
- "vecType": "\"vec4<f32>\"",
578
- "useSubgroups": "hasSubgroups"
579
- }
580
  },
581
- "subgroupCollectivesWidth": "portable",
582
- "bindings": "vec4_no_bias_residual",
583
- "dispatch": { "workgroups": "rowCount" }
584
  }
585
  ]
586
  },
587
  {
588
  "id": "no_bias_output_only_vec4",
589
  "priority": 20,
590
- "when": ["f32_no_bias_output_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
591
- "constants": {
592
  "scalar": "\"f32\"",
593
  "vectorScalar": "\"vec4<f32>\"",
594
  "hasBias": "\"no_bias\" == \"bias\"",
@@ -598,32 +184,30 @@
598
  {
599
  "id": "main",
600
  "name": "SkipSimplifiedLayerNormalization.Vec4OutputOnly",
601
- "source": {
602
- "shader": "norm-skip-row-vec4.wgsl.jinja",
603
- "inputs": {
604
- "simplified": true,
605
- "hasBias": "\"no_bias\" == \"bias\"",
606
- "hasBeta": false,
607
- "writeResidualSum": false,
608
- "usesF16": false,
609
- "hidden": "hiddenSize",
610
- "hiddenVec": "hiddenSize / 4",
611
- "wg": "skipWgVec4",
612
- "vecType": "\"vec4<f32>\"",
613
- "useSubgroups": "hasSubgroups"
614
- }
615
  },
616
- "subgroupCollectivesWidth": "portable",
617
- "bindings": "vec4_no_bias_output_only",
618
- "dispatch": { "workgroups": "rowCount" }
619
  }
620
  ]
621
  },
622
  {
623
  "id": "no_bias_output_only_vec4_f16",
624
  "priority": 21,
625
- "when": ["f16_no_bias_output_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
626
- "constants": {
627
  "scalar": "\"f16\"",
628
  "vectorScalar": "\"vec4<f16>\"",
629
  "hasBias": "\"no_bias\" == \"bias\"",
@@ -633,39 +217,36 @@
633
  {
634
  "id": "main",
635
  "name": "SkipSimplifiedLayerNormalization.Vec4OutputOnly",
636
- "source": {
637
- "shader": "norm-skip-row-vec4.wgsl.jinja",
638
- "inputs": {
639
- "simplified": true,
640
- "hasBias": "\"no_bias\" == \"bias\"",
641
- "hasBeta": false,
642
- "writeResidualSum": false,
643
- "usesF16": true,
644
- "hidden": "hiddenSize",
645
- "hiddenVec": "hiddenSize / 4",
646
- "wg": "skipWgVec4",
647
- "vecType": "\"vec4<f16>\"",
648
- "useSubgroups": "hasSubgroups"
649
- }
650
  },
651
- "subgroupCollectivesWidth": "portable",
652
- "bindings": "vec4_no_bias_output_only",
653
- "dispatch": { "workgroups": "rowCount" }
654
  }
655
  ]
656
  },
657
  {
658
  "id": "no_bias",
659
  "priority": 0,
660
- "when": ["f32_no_bias_residual_contract", "normResourcesFit", "rowDispatchFits"],
661
- "constants": {
662
  "simplified": true,
663
  "useSubgroups": false,
664
  "hasBeta": false,
665
  "writeResidualSum": true,
666
  "hasBias": "\"no_bias\" == \"bias\"",
667
  "scalar": "\"f32\"",
668
- "hiddenSize": "dim(shapes.inputT, -1)",
669
  "workgroupSize": "skipWg",
670
  "HIDDEN_LEN": "hiddenSize"
671
  },
@@ -674,17 +255,17 @@
674
  "id": "main",
675
  "name": "SkipSimplifiedLayerNormalization",
676
  "shader": "norm-skip-row.wgsl.jinja",
677
- "bindings": "scalar_no_bias_residual",
678
- "dispatch": { "workgroups": "rowCount" }
679
  }
680
  ]
681
  },
682
  {
683
  "id": "no_bias_f16",
684
- "requires": { "features": ["shader-f16"] },
685
  "priority": 0,
686
- "when": ["f16_no_bias_residual_contract", "normResourcesFit", "rowDispatchFits"],
687
- "constants": {
 
688
  "simplified": true,
689
  "useSubgroups": false,
690
  "hasBeta": false,
@@ -692,7 +273,6 @@
692
  "hasBias": "\"no_bias\" == \"bias\"",
693
  "scalar": "\"f16\"",
694
  "usesF16": true,
695
- "hiddenSize": "dim(shapes.inputT, -1)",
696
  "workgroupSize": "skipWg",
697
  "HIDDEN_LEN": "hiddenSize"
698
  },
@@ -701,17 +281,17 @@
701
  "id": "main",
702
  "name": "SkipSimplifiedLayerNormalization",
703
  "shader": "norm-skip-row.wgsl.jinja",
704
- "bindings": "scalar_no_bias_residual",
705
- "dispatch": { "workgroups": "rowCount" }
706
  }
707
  ]
708
  },
709
  {
710
  "id": "no_bias_output_only_f16",
711
- "requires": { "features": ["shader-f16"] },
712
  "priority": 0,
713
- "when": ["f16_no_bias_output_contract", "normResourcesFit", "rowDispatchFits"],
714
- "constants": {
 
715
  "simplified": true,
716
  "useSubgroups": false,
717
  "hasBeta": false,
@@ -719,7 +299,6 @@
719
  "hasBias": "\"no_bias\" == \"bias\"",
720
  "scalar": "\"f16\"",
721
  "usesF16": true,
722
- "hiddenSize": "dim(shapes.inputT, -1)",
723
  "workgroupSize": "skipWg",
724
  "HIDDEN_LEN": "hiddenSize"
725
  },
@@ -728,23 +307,22 @@
728
  "id": "main",
729
  "name": "SkipSimplifiedLayerNormalization.OutputOnly",
730
  "shader": "norm-skip-row.wgsl.jinja",
731
- "bindings": "scalar_no_bias_output_only",
732
- "dispatch": { "workgroups": "rowCount" }
733
  }
734
  ]
735
  },
736
  {
737
  "id": "no_bias_output_only",
738
  "priority": 0,
739
- "when": ["f32_no_bias_output_contract", "normResourcesFit", "rowDispatchFits"],
740
- "constants": {
741
  "simplified": true,
742
  "useSubgroups": false,
743
  "hasBeta": false,
744
  "writeResidualSum": false,
745
  "hasBias": "\"no_bias\" == \"bias\"",
746
  "scalar": "\"f32\"",
747
- "hiddenSize": "dim(shapes.inputT, -1)",
748
  "workgroupSize": "skipWg",
749
  "HIDDEN_LEN": "hiddenSize"
750
  },
@@ -753,16 +331,16 @@
753
  "id": "main",
754
  "name": "SkipSimplifiedLayerNormalization.OutputOnly",
755
  "shader": "norm-skip-row.wgsl.jinja",
756
- "bindings": "scalar_no_bias_output_only",
757
- "dispatch": { "workgroups": "rowCount" }
758
  }
759
  ]
760
  },
761
  {
762
  "id": "bias_vec4_f16",
763
  "priority": 21,
764
- "when": ["f16_bias_residual_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
765
- "constants": {
766
  "scalar": "\"f16\"",
767
  "vectorScalar": "\"vec4<f16>\"",
768
  "hasBias": "\"bias\" == \"bias\"",
@@ -772,32 +350,30 @@
772
  {
773
  "id": "main",
774
  "name": "SkipSimplifiedLayerNormalization.Vec4",
775
- "source": {
776
- "shader": "norm-skip-row-vec4.wgsl.jinja",
777
- "inputs": {
778
- "simplified": true,
779
- "hasBias": "\"bias\" == \"bias\"",
780
- "hasBeta": false,
781
- "writeResidualSum": true,
782
- "usesF16": true,
783
- "hidden": "hiddenSize",
784
- "hiddenVec": "hiddenSize / 4",
785
- "wg": "skipWgVec4",
786
- "vecType": "\"vec4<f16>\"",
787
- "useSubgroups": "hasSubgroups"
788
- }
789
  },
790
- "subgroupCollectivesWidth": "portable",
791
- "bindings": "vec4_bias_residual",
792
- "dispatch": { "workgroups": "rowCount" }
793
  }
794
  ]
795
  },
796
  {
797
  "id": "bias_vec4",
798
  "priority": 20,
799
- "when": ["f32_bias_residual_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
800
- "constants": {
801
  "scalar": "\"f32\"",
802
  "vectorScalar": "\"vec4<f32>\"",
803
  "hasBias": "\"bias\" == \"bias\"",
@@ -807,32 +383,30 @@
807
  {
808
  "id": "main",
809
  "name": "SkipSimplifiedLayerNormalization.Vec4",
810
- "source": {
811
- "shader": "norm-skip-row-vec4.wgsl.jinja",
812
- "inputs": {
813
- "simplified": true,
814
- "hasBias": "\"bias\" == \"bias\"",
815
- "hasBeta": false,
816
- "writeResidualSum": true,
817
- "usesF16": false,
818
- "hidden": "hiddenSize",
819
- "hiddenVec": "hiddenSize / 4",
820
- "wg": "skipWgVec4",
821
- "vecType": "\"vec4<f32>\"",
822
- "useSubgroups": "hasSubgroups"
823
- }
824
  },
825
- "subgroupCollectivesWidth": "portable",
826
- "bindings": "vec4_bias_residual",
827
- "dispatch": { "workgroups": "rowCount" }
828
  }
829
  ]
830
  },
831
  {
832
  "id": "bias_output_only_vec4",
833
  "priority": 20,
834
- "when": ["f32_bias_output_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
835
- "constants": {
836
  "scalar": "\"f32\"",
837
  "vectorScalar": "\"vec4<f32>\"",
838
  "hasBias": "\"bias\" == \"bias\"",
@@ -842,32 +416,30 @@
842
  {
843
  "id": "main",
844
  "name": "SkipSimplifiedLayerNormalization.Vec4OutputOnly",
845
- "source": {
846
- "shader": "norm-skip-row-vec4.wgsl.jinja",
847
- "inputs": {
848
- "simplified": true,
849
- "hasBias": "\"bias\" == \"bias\"",
850
- "hasBeta": false,
851
- "writeResidualSum": false,
852
- "usesF16": false,
853
- "hidden": "hiddenSize",
854
- "hiddenVec": "hiddenSize / 4",
855
- "wg": "skipWgVec4",
856
- "vecType": "\"vec4<f32>\"",
857
- "useSubgroups": "hasSubgroups"
858
- }
859
  },
860
- "subgroupCollectivesWidth": "portable",
861
- "bindings": "vec4_bias_output_only",
862
- "dispatch": { "workgroups": "rowCount" }
863
  }
864
  ]
865
  },
866
  {
867
  "id": "bias_output_only_vec4_f16",
868
  "priority": 21,
869
- "when": ["f16_bias_output_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
870
- "constants": {
871
  "scalar": "\"f16\"",
872
  "vectorScalar": "\"vec4<f16>\"",
873
  "hasBias": "\"bias\" == \"bias\"",
@@ -877,39 +449,36 @@
877
  {
878
  "id": "main",
879
  "name": "SkipSimplifiedLayerNormalization.Vec4OutputOnly",
880
- "source": {
881
- "shader": "norm-skip-row-vec4.wgsl.jinja",
882
- "inputs": {
883
- "simplified": true,
884
- "hasBias": "\"bias\" == \"bias\"",
885
- "hasBeta": false,
886
- "writeResidualSum": false,
887
- "usesF16": true,
888
- "hidden": "hiddenSize",
889
- "hiddenVec": "hiddenSize / 4",
890
- "wg": "skipWgVec4",
891
- "vecType": "\"vec4<f16>\"",
892
- "useSubgroups": "hasSubgroups"
893
- }
894
  },
895
- "subgroupCollectivesWidth": "portable",
896
- "bindings": "vec4_bias_output_only",
897
- "dispatch": { "workgroups": "rowCount" }
898
  }
899
  ]
900
  },
901
  {
902
  "id": "bias",
903
  "priority": 0,
904
- "when": ["f32_bias_residual_contract", "normResourcesFit", "rowDispatchFits"],
905
- "constants": {
906
  "simplified": true,
907
  "useSubgroups": false,
908
  "hasBeta": false,
909
  "writeResidualSum": true,
910
  "hasBias": "\"bias\" == \"bias\"",
911
  "scalar": "\"f32\"",
912
- "hiddenSize": "dim(shapes.inputT, -1)",
913
  "workgroupSize": "skipWg",
914
  "HIDDEN_LEN": "hiddenSize"
915
  },
@@ -918,17 +487,17 @@
918
  "id": "main",
919
  "name": "SkipSimplifiedLayerNormalization",
920
  "shader": "norm-skip-row.wgsl.jinja",
921
- "bindings": "scalar_bias_residual",
922
- "dispatch": { "workgroups": "rowCount" }
923
  }
924
  ]
925
  },
926
  {
927
  "id": "bias_f16",
928
- "requires": { "features": ["shader-f16"] },
929
  "priority": 0,
930
- "when": ["f16_bias_residual_contract", "normResourcesFit", "rowDispatchFits"],
931
- "constants": {
 
932
  "simplified": true,
933
  "useSubgroups": false,
934
  "hasBeta": false,
@@ -936,7 +505,6 @@
936
  "hasBias": "\"bias\" == \"bias\"",
937
  "scalar": "\"f16\"",
938
  "usesF16": true,
939
- "hiddenSize": "dim(shapes.inputT, -1)",
940
  "workgroupSize": "skipWg",
941
  "HIDDEN_LEN": "hiddenSize"
942
  },
@@ -945,17 +513,17 @@
945
  "id": "main",
946
  "name": "SkipSimplifiedLayerNormalization",
947
  "shader": "norm-skip-row.wgsl.jinja",
948
- "bindings": "scalar_bias_residual",
949
- "dispatch": { "workgroups": "rowCount" }
950
  }
951
  ]
952
  },
953
  {
954
  "id": "bias_output_only_f16",
955
- "requires": { "features": ["shader-f16"] },
956
  "priority": 0,
957
- "when": ["f16_bias_output_contract", "normResourcesFit", "rowDispatchFits"],
958
- "constants": {
 
959
  "simplified": true,
960
  "useSubgroups": false,
961
  "hasBeta": false,
@@ -963,7 +531,6 @@
963
  "hasBias": "\"bias\" == \"bias\"",
964
  "scalar": "\"f16\"",
965
  "usesF16": true,
966
- "hiddenSize": "dim(shapes.inputT, -1)",
967
  "workgroupSize": "skipWg",
968
  "HIDDEN_LEN": "hiddenSize"
969
  },
@@ -972,23 +539,22 @@
972
  "id": "main",
973
  "name": "SkipSimplifiedLayerNormalization.OutputOnly",
974
  "shader": "norm-skip-row.wgsl.jinja",
975
- "bindings": "scalar_bias_output_only",
976
- "dispatch": { "workgroups": "rowCount" }
977
  }
978
  ]
979
  },
980
  {
981
  "id": "bias_output_only",
982
  "priority": 0,
983
- "when": ["f32_bias_output_contract", "normResourcesFit", "rowDispatchFits"],
984
- "constants": {
985
  "simplified": true,
986
  "useSubgroups": false,
987
  "hasBeta": false,
988
  "writeResidualSum": false,
989
  "hasBias": "\"bias\" == \"bias\"",
990
  "scalar": "\"f32\"",
991
- "hiddenSize": "dim(shapes.inputT, -1)",
992
  "workgroupSize": "skipWg",
993
  "HIDDEN_LEN": "hiddenSize"
994
  },
@@ -997,8 +563,8 @@
997
  "id": "main",
998
  "name": "SkipSimplifiedLayerNormalization.OutputOnly",
999
  "shader": "norm-skip-row.wgsl.jinja",
1000
- "bindings": "scalar_bias_output_only",
1001
- "dispatch": { "workgroups": "rowCount" }
1002
  }
1003
  ]
1004
  }
 
2
  "domain": "com.microsoft",
3
  "name": "SkipSimplifiedLayerNormalization",
4
  "sinceVersion": 1,
5
+ "inputs": {
6
+ "inputT": { "onnx": "input", "dtype": "T" },
7
+ "skipT": { "onnx": "skip", "dtype": "T" },
8
+ "gammaT": { "onnx": "gamma", "dtype": "T", "rank": 1 },
9
+ "biasT": { "onnx": "bias", "dtype": "T", "rank": 1, "optional": true }
10
+ },
11
+ "outputs": {
12
+ "outputT": { "onnx": "output", "dtype": "T", "rank": "ranks.inputT", "shape": "shapes.inputT" },
13
+ "residualT": {
14
+ "onnx": "input_skip_bias_sum",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  "dtype": "T",
16
  "rank": "ranks.inputT",
 
 
 
 
 
 
17
  "optional": true,
18
+ "shape": "shapes.inputT"
 
 
19
  }
 
 
 
 
 
 
 
 
 
 
20
  },
21
+ "attributes": { "epsilon": { "default": 9.999999960041972e-13 } },
22
  "typeConstraints": { "T": ["float32", "float16"] },
23
+ "tunables": { "MAX_WORKGROUP_SIZE": { "default": 256 } },
24
  "derive": {
25
  "rowCount": "numel(shapes.inputT) / max(1, dim(shapes.inputT, -1))",
26
  "hiddenSize": "dim(shapes.inputT, -1)",
27
  "skipWg": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(hiddenSize)))",
28
  "skipWgVec4": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(ceilDiv(hiddenSize, 4))))",
29
+ "rowDispatchFits": "rowCount <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535) * min(device.limits.maxComputeWorkgroupsPerDimension, 65535)",
30
  "normResourcesFit": "skipWg * 8 <= device.limits.maxComputeWorkgroupStorageSize and skipWgVec4 * 8 <= device.limits.maxComputeWorkgroupStorageSize",
31
  "epsilonOk": "attrs.epsilon >= 0",
32
  "coreContract": "epsilonOk and (ranks.inputT == 2 or ranks.inputT == 3) and ranks.skipT == ranks.inputT and ranks.gammaT == 1 and ranks.outputT == ranks.inputT and sameShape(shapes.inputT, shapes.skipT) and sameShape(shapes.outputT, shapes.inputT) and dim(shapes.inputT, -1) > 0 and dim(shapes.gammaT, 0) == dim(shapes.inputT, -1)",
 
51
  "f16_no_bias_output_contract": "hasF16 and coreContract and outputOnlyContract and f16MainDtypes and no_bias_contract",
52
  "f16_bias_output_contract": "hasF16 and coreContract and outputOnlyContract and f16MainDtypes and f16_bias_contract"
53
  },
54
+ "when": ["normResourcesFit", "rowDispatchFits"],
55
+ "bindings": {
56
+ "input": { "arg": "inputT", "buffer": "read-only-storage", "elementType": "$vectorScalar" },
57
+ "skip": { "arg": "skipT", "buffer": "read-only-storage", "elementType": "$vectorScalar" },
58
+ "gamma": { "arg": "gammaT", "buffer": "read-only-storage", "elementType": "$vectorScalar", "length": "$HIDDEN_LEN" },
59
+ "output": { "arg": "outputT", "buffer": "storage", "elementType": "$vectorScalar" },
60
+ "input_skip_bias_sum": { "arg": "residualT", "buffer": "storage", "elementType": "$vectorScalar" },
61
+ "params": {
62
+ "buffer": "uniform",
63
+ "struct": [
64
+ { "name": "rows", "type": "u32", "value": "rowCount" },
65
+ {
66
+ "name": "rowStride",
67
+ "type": "u32",
68
+ "value": "max(1, min(rowCount, min(device.limits.maxComputeWorkgroupsPerDimension, 65535)))"
69
+ },
70
+ { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
71
+ ]
72
+ },
73
+ "bias": { "arg": "biasT", "buffer": "read-only-storage", "elementType": "$vectorScalar", "length": "$HIDDEN_LEN" },
74
+ "input_2": { "arg": "inputT", "name": "input", "buffer": "read-only-storage", "elementType": "$scalar" },
75
+ "skip_2": { "arg": "skipT", "name": "skip", "buffer": "read-only-storage", "elementType": "$scalar" },
76
+ "gamma_2": {
77
+ "arg": "gammaT",
78
+ "name": "gamma",
79
+ "buffer": "read-only-storage",
80
+ "elementType": "$scalar",
81
+ "length": "$HIDDEN_LEN"
82
+ },
83
+ "output_2": { "arg": "outputT", "name": "output", "buffer": "storage", "elementType": "$scalar" },
84
+ "input_skip_bias_sum_2": {
85
+ "arg": "residualT",
86
+ "name": "input_skip_bias_sum",
87
+ "buffer": "storage",
88
+ "elementType": "$scalar"
89
+ },
90
+ "params_2": {
91
+ "name": "params",
92
+ "buffer": "uniform",
93
+ "struct": [
94
+ { "name": "rows", "type": "u32", "value": "rowCount" },
95
+ { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
96
+ ]
97
+ },
98
+ "bias_2": {
99
+ "arg": "biasT",
100
+ "name": "bias",
101
+ "buffer": "read-only-storage",
102
+ "elementType": "$scalar",
103
+ "length": "$HIDDEN_LEN"
104
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  },
 
106
  "variants": [
107
  {
108
  "id": "no_bias_vec4_f16",
109
  "priority": 21,
110
+ "when": ["f16_no_bias_residual_contract", "vec4Aligned"],
111
+ "derive": {
112
  "scalar": "\"f16\"",
113
  "vectorScalar": "\"vec4<f16>\"",
114
  "hasBias": "\"no_bias\" == \"bias\"",
 
118
  {
119
  "id": "main",
120
  "name": "SkipSimplifiedLayerNormalization.Vec4",
121
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
122
+ "derive": {
123
+ "simplified": true,
124
+ "hasBias": "\"no_bias\" == \"bias\"",
125
+ "hasBeta": false,
126
+ "writeResidualSum": true,
127
+ "usesF16Spec": true,
128
+ "hidden": "hiddenSize",
129
+ "hiddenVec": "hiddenSize / 4",
130
+ "wg": "skipWgVec4",
131
+ "vecType": "\"vec4<f16>\"",
132
+ "useSubgroups": "hasSubgroups"
 
 
133
  },
134
+ "bindings": ["input", "skip", "gamma", "output", "input_skip_bias_sum", "params"],
135
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
136
+ "subgroupCollectivesWidth": "portable"
137
  }
138
  ]
139
  },
140
  {
141
  "id": "no_bias_vec4",
142
  "priority": 20,
143
+ "when": ["f32_no_bias_residual_contract", "vec4Aligned"],
144
+ "derive": {
145
  "scalar": "\"f32\"",
146
  "vectorScalar": "\"vec4<f32>\"",
147
  "hasBias": "\"no_bias\" == \"bias\"",
 
151
  {
152
  "id": "main",
153
  "name": "SkipSimplifiedLayerNormalization.Vec4",
154
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
155
+ "derive": {
156
+ "simplified": true,
157
+ "hasBias": "\"no_bias\" == \"bias\"",
158
+ "hasBeta": false,
159
+ "writeResidualSum": true,
160
+ "usesF16Spec": false,
161
+ "hidden": "hiddenSize",
162
+ "hiddenVec": "hiddenSize / 4",
163
+ "wg": "skipWgVec4",
164
+ "vecType": "\"vec4<f32>\"",
165
+ "useSubgroups": "hasSubgroups"
 
 
166
  },
167
+ "bindings": ["input", "skip", "gamma", "output", "input_skip_bias_sum", "params"],
168
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
169
+ "subgroupCollectivesWidth": "portable"
170
  }
171
  ]
172
  },
173
  {
174
  "id": "no_bias_output_only_vec4",
175
  "priority": 20,
176
+ "when": ["f32_no_bias_output_contract", "vec4Aligned"],
177
+ "derive": {
178
  "scalar": "\"f32\"",
179
  "vectorScalar": "\"vec4<f32>\"",
180
  "hasBias": "\"no_bias\" == \"bias\"",
 
184
  {
185
  "id": "main",
186
  "name": "SkipSimplifiedLayerNormalization.Vec4OutputOnly",
187
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
188
+ "derive": {
189
+ "simplified": true,
190
+ "hasBias": "\"no_bias\" == \"bias\"",
191
+ "hasBeta": false,
192
+ "writeResidualSum": false,
193
+ "usesF16Spec": false,
194
+ "hidden": "hiddenSize",
195
+ "hiddenVec": "hiddenSize / 4",
196
+ "wg": "skipWgVec4",
197
+ "vecType": "\"vec4<f32>\"",
198
+ "useSubgroups": "hasSubgroups"
 
 
199
  },
200
+ "bindings": ["input", "skip", "gamma", "output", "params"],
201
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
202
+ "subgroupCollectivesWidth": "portable"
203
  }
204
  ]
205
  },
206
  {
207
  "id": "no_bias_output_only_vec4_f16",
208
  "priority": 21,
209
+ "when": ["f16_no_bias_output_contract", "vec4Aligned"],
210
+ "derive": {
211
  "scalar": "\"f16\"",
212
  "vectorScalar": "\"vec4<f16>\"",
213
  "hasBias": "\"no_bias\" == \"bias\"",
 
217
  {
218
  "id": "main",
219
  "name": "SkipSimplifiedLayerNormalization.Vec4OutputOnly",
220
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
221
+ "derive": {
222
+ "simplified": true,
223
+ "hasBias": "\"no_bias\" == \"bias\"",
224
+ "hasBeta": false,
225
+ "writeResidualSum": false,
226
+ "usesF16Spec": true,
227
+ "hidden": "hiddenSize",
228
+ "hiddenVec": "hiddenSize / 4",
229
+ "wg": "skipWgVec4",
230
+ "vecType": "\"vec4<f16>\"",
231
+ "useSubgroups": "hasSubgroups"
 
 
232
  },
233
+ "bindings": ["input", "skip", "gamma", "output", "params"],
234
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
235
+ "subgroupCollectivesWidth": "portable"
236
  }
237
  ]
238
  },
239
  {
240
  "id": "no_bias",
241
  "priority": 0,
242
+ "when": ["f32_no_bias_residual_contract"],
243
+ "derive": {
244
  "simplified": true,
245
  "useSubgroups": false,
246
  "hasBeta": false,
247
  "writeResidualSum": true,
248
  "hasBias": "\"no_bias\" == \"bias\"",
249
  "scalar": "\"f32\"",
 
250
  "workgroupSize": "skipWg",
251
  "HIDDEN_LEN": "hiddenSize"
252
  },
 
255
  "id": "main",
256
  "name": "SkipSimplifiedLayerNormalization",
257
  "shader": "norm-skip-row.wgsl.jinja",
258
+ "bindings": ["input_2", "skip_2", "gamma_2", "output_2", "input_skip_bias_sum_2", "params_2"],
259
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 }
260
  }
261
  ]
262
  },
263
  {
264
  "id": "no_bias_f16",
 
265
  "priority": 0,
266
+ "when": ["f16_no_bias_residual_contract"],
267
+ "requires": { "features": ["shader-f16"] },
268
+ "derive": {
269
  "simplified": true,
270
  "useSubgroups": false,
271
  "hasBeta": false,
 
273
  "hasBias": "\"no_bias\" == \"bias\"",
274
  "scalar": "\"f16\"",
275
  "usesF16": true,
 
276
  "workgroupSize": "skipWg",
277
  "HIDDEN_LEN": "hiddenSize"
278
  },
 
281
  "id": "main",
282
  "name": "SkipSimplifiedLayerNormalization",
283
  "shader": "norm-skip-row.wgsl.jinja",
284
+ "bindings": ["input_2", "skip_2", "gamma_2", "output_2", "input_skip_bias_sum_2", "params_2"],
285
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 }
286
  }
287
  ]
288
  },
289
  {
290
  "id": "no_bias_output_only_f16",
 
291
  "priority": 0,
292
+ "when": ["f16_no_bias_output_contract"],
293
+ "requires": { "features": ["shader-f16"] },
294
+ "derive": {
295
  "simplified": true,
296
  "useSubgroups": false,
297
  "hasBeta": false,
 
299
  "hasBias": "\"no_bias\" == \"bias\"",
300
  "scalar": "\"f16\"",
301
  "usesF16": true,
 
302
  "workgroupSize": "skipWg",
303
  "HIDDEN_LEN": "hiddenSize"
304
  },
 
307
  "id": "main",
308
  "name": "SkipSimplifiedLayerNormalization.OutputOnly",
309
  "shader": "norm-skip-row.wgsl.jinja",
310
+ "bindings": ["input_2", "skip_2", "gamma_2", "output_2", "params_2"],
311
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 }
312
  }
313
  ]
314
  },
315
  {
316
  "id": "no_bias_output_only",
317
  "priority": 0,
318
+ "when": ["f32_no_bias_output_contract"],
319
+ "derive": {
320
  "simplified": true,
321
  "useSubgroups": false,
322
  "hasBeta": false,
323
  "writeResidualSum": false,
324
  "hasBias": "\"no_bias\" == \"bias\"",
325
  "scalar": "\"f32\"",
 
326
  "workgroupSize": "skipWg",
327
  "HIDDEN_LEN": "hiddenSize"
328
  },
 
331
  "id": "main",
332
  "name": "SkipSimplifiedLayerNormalization.OutputOnly",
333
  "shader": "norm-skip-row.wgsl.jinja",
334
+ "bindings": ["input_2", "skip_2", "gamma_2", "output_2", "params_2"],
335
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 }
336
  }
337
  ]
338
  },
339
  {
340
  "id": "bias_vec4_f16",
341
  "priority": 21,
342
+ "when": ["f16_bias_residual_contract", "vec4Aligned"],
343
+ "derive": {
344
  "scalar": "\"f16\"",
345
  "vectorScalar": "\"vec4<f16>\"",
346
  "hasBias": "\"bias\" == \"bias\"",
 
350
  {
351
  "id": "main",
352
  "name": "SkipSimplifiedLayerNormalization.Vec4",
353
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
354
+ "derive": {
355
+ "simplified": true,
356
+ "hasBias": "\"bias\" == \"bias\"",
357
+ "hasBeta": false,
358
+ "writeResidualSum": true,
359
+ "usesF16Spec": true,
360
+ "hidden": "hiddenSize",
361
+ "hiddenVec": "hiddenSize / 4",
362
+ "wg": "skipWgVec4",
363
+ "vecType": "\"vec4<f16>\"",
364
+ "useSubgroups": "hasSubgroups"
 
 
365
  },
366
+ "bindings": ["input", "skip", "gamma", "bias", "output", "input_skip_bias_sum", "params"],
367
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
368
+ "subgroupCollectivesWidth": "portable"
369
  }
370
  ]
371
  },
372
  {
373
  "id": "bias_vec4",
374
  "priority": 20,
375
+ "when": ["f32_bias_residual_contract", "vec4Aligned"],
376
+ "derive": {
377
  "scalar": "\"f32\"",
378
  "vectorScalar": "\"vec4<f32>\"",
379
  "hasBias": "\"bias\" == \"bias\"",
 
383
  {
384
  "id": "main",
385
  "name": "SkipSimplifiedLayerNormalization.Vec4",
386
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
387
+ "derive": {
388
+ "simplified": true,
389
+ "hasBias": "\"bias\" == \"bias\"",
390
+ "hasBeta": false,
391
+ "writeResidualSum": true,
392
+ "usesF16Spec": false,
393
+ "hidden": "hiddenSize",
394
+ "hiddenVec": "hiddenSize / 4",
395
+ "wg": "skipWgVec4",
396
+ "vecType": "\"vec4<f32>\"",
397
+ "useSubgroups": "hasSubgroups"
 
 
398
  },
399
+ "bindings": ["input", "skip", "gamma", "bias", "output", "input_skip_bias_sum", "params"],
400
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
401
+ "subgroupCollectivesWidth": "portable"
402
  }
403
  ]
404
  },
405
  {
406
  "id": "bias_output_only_vec4",
407
  "priority": 20,
408
+ "when": ["f32_bias_output_contract", "vec4Aligned"],
409
+ "derive": {
410
  "scalar": "\"f32\"",
411
  "vectorScalar": "\"vec4<f32>\"",
412
  "hasBias": "\"bias\" == \"bias\"",
 
416
  {
417
  "id": "main",
418
  "name": "SkipSimplifiedLayerNormalization.Vec4OutputOnly",
419
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
420
+ "derive": {
421
+ "simplified": true,
422
+ "hasBias": "\"bias\" == \"bias\"",
423
+ "hasBeta": false,
424
+ "writeResidualSum": false,
425
+ "usesF16Spec": false,
426
+ "hidden": "hiddenSize",
427
+ "hiddenVec": "hiddenSize / 4",
428
+ "wg": "skipWgVec4",
429
+ "vecType": "\"vec4<f32>\"",
430
+ "useSubgroups": "hasSubgroups"
 
 
431
  },
432
+ "bindings": ["input", "skip", "gamma", "bias", "output", "params"],
433
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
434
+ "subgroupCollectivesWidth": "portable"
435
  }
436
  ]
437
  },
438
  {
439
  "id": "bias_output_only_vec4_f16",
440
  "priority": 21,
441
+ "when": ["f16_bias_output_contract", "vec4Aligned"],
442
+ "derive": {
443
  "scalar": "\"f16\"",
444
  "vectorScalar": "\"vec4<f16>\"",
445
  "hasBias": "\"bias\" == \"bias\"",
 
449
  {
450
  "id": "main",
451
  "name": "SkipSimplifiedLayerNormalization.Vec4OutputOnly",
452
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
453
+ "derive": {
454
+ "simplified": true,
455
+ "hasBias": "\"bias\" == \"bias\"",
456
+ "hasBeta": false,
457
+ "writeResidualSum": false,
458
+ "usesF16Spec": true,
459
+ "hidden": "hiddenSize",
460
+ "hiddenVec": "hiddenSize / 4",
461
+ "wg": "skipWgVec4",
462
+ "vecType": "\"vec4<f16>\"",
463
+ "useSubgroups": "hasSubgroups"
 
 
464
  },
465
+ "bindings": ["input", "skip", "gamma", "bias", "output", "params"],
466
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
467
+ "subgroupCollectivesWidth": "portable"
468
  }
469
  ]
470
  },
471
  {
472
  "id": "bias",
473
  "priority": 0,
474
+ "when": ["f32_bias_residual_contract"],
475
+ "derive": {
476
  "simplified": true,
477
  "useSubgroups": false,
478
  "hasBeta": false,
479
  "writeResidualSum": true,
480
  "hasBias": "\"bias\" == \"bias\"",
481
  "scalar": "\"f32\"",
 
482
  "workgroupSize": "skipWg",
483
  "HIDDEN_LEN": "hiddenSize"
484
  },
 
487
  "id": "main",
488
  "name": "SkipSimplifiedLayerNormalization",
489
  "shader": "norm-skip-row.wgsl.jinja",
490
+ "bindings": ["input_2", "skip_2", "gamma_2", "bias_2", "output_2", "input_skip_bias_sum_2", "params_2"],
491
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 }
492
  }
493
  ]
494
  },
495
  {
496
  "id": "bias_f16",
 
497
  "priority": 0,
498
+ "when": ["f16_bias_residual_contract"],
499
+ "requires": { "features": ["shader-f16"] },
500
+ "derive": {
501
  "simplified": true,
502
  "useSubgroups": false,
503
  "hasBeta": false,
 
505
  "hasBias": "\"bias\" == \"bias\"",
506
  "scalar": "\"f16\"",
507
  "usesF16": true,
 
508
  "workgroupSize": "skipWg",
509
  "HIDDEN_LEN": "hiddenSize"
510
  },
 
513
  "id": "main",
514
  "name": "SkipSimplifiedLayerNormalization",
515
  "shader": "norm-skip-row.wgsl.jinja",
516
+ "bindings": ["input_2", "skip_2", "gamma_2", "bias_2", "output_2", "input_skip_bias_sum_2", "params_2"],
517
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 }
518
  }
519
  ]
520
  },
521
  {
522
  "id": "bias_output_only_f16",
 
523
  "priority": 0,
524
+ "when": ["f16_bias_output_contract"],
525
+ "requires": { "features": ["shader-f16"] },
526
+ "derive": {
527
  "simplified": true,
528
  "useSubgroups": false,
529
  "hasBeta": false,
 
531
  "hasBias": "\"bias\" == \"bias\"",
532
  "scalar": "\"f16\"",
533
  "usesF16": true,
 
534
  "workgroupSize": "skipWg",
535
  "HIDDEN_LEN": "hiddenSize"
536
  },
 
539
  "id": "main",
540
  "name": "SkipSimplifiedLayerNormalization.OutputOnly",
541
  "shader": "norm-skip-row.wgsl.jinja",
542
+ "bindings": ["input_2", "skip_2", "gamma_2", "bias_2", "output_2", "params_2"],
543
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 }
544
  }
545
  ]
546
  },
547
  {
548
  "id": "bias_output_only",
549
  "priority": 0,
550
+ "when": ["f32_bias_output_contract"],
551
+ "derive": {
552
  "simplified": true,
553
  "useSubgroups": false,
554
  "hasBeta": false,
555
  "writeResidualSum": false,
556
  "hasBias": "\"bias\" == \"bias\"",
557
  "scalar": "\"f32\"",
 
558
  "workgroupSize": "skipWg",
559
  "HIDDEN_LEN": "hiddenSize"
560
  },
 
563
  "id": "main",
564
  "name": "SkipSimplifiedLayerNormalization.OutputOnly",
565
  "shader": "norm-skip-row.wgsl.jinja",
566
+ "bindings": ["input_2", "skip_2", "gamma_2", "bias_2", "output_2", "params_2"],
567
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 }
568
  }
569
  ]
570
  }
build/webgpu/metadata.json CHANGED
@@ -1,23 +1,39 @@
1
  {
2
  "name": "com.microsoft.SkipSimplifiedLayerNormalization",
3
- "id": "_com_microsoft_skipsimplifiedlayernormalization_webgpu_6026e4e",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
- "bench.json": "Qjd8vGH/qoXU3rXEQhkz+xTQK2qSM5Kl4BHnWY/nzeQ=",
11
- "manifest.json": "0QZ+D26SsY6uIHFcZV326mQMPoEYAClEUEifNI/9jms=",
12
- "norm-skip-row-vec4.wgsl.jinja": "L7sH/FpRWVXbyaGm4QTjBAaLMacnNmwb0dbt2pKie5s=",
13
- "norm-skip-row.wgsl.jinja": "bo/2mKHvO3Xkb7rbXnHkw/csvMsxID6bhdF8Wv7efKM=",
14
- "test.json": "oQayex/aOYAhZXp9ESTPlwVGivSDeuEumSnU6kNNUR0="
15
  }
16
  },
17
- "provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
18
  "webgpu": {
19
- "manifestSpec": "1.0",
20
- "specialized": true,
21
- "opPath": "ops/com.microsoft.SkipSimplifiedLayerNormalization"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  }
23
  }
 
1
  {
2
  "name": "com.microsoft.SkipSimplifiedLayerNormalization",
3
+ "id": "_com_microsoft_skipsimplifiedlayernormalization_webgpu_b8ecf51",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
+ "bench.json": "w8dZhYzUtAD/LB4ByqSaHZ6t6a1LKgH6Fb7sFyVZLY8=",
11
+ "manifest.json": "Z3UvZaHGuT5XUJRtn5Cb07il2Jc1HM60BXm8GXxeWyY=",
12
+ "norm-skip-row-vec4.wgsl.jinja": "gTtEoczLSil0/2T/beWedsZzghnBsunoUp5zcKKAfpM=",
13
+ "norm-skip-row.wgsl.jinja": "HwkrJ+4YZjuFEQ87AvYOJX89/G3JeFc/CfOiU0BcPcU=",
14
+ "test.json": "E137wUKjS95iD915YA7yUZ4fppQlh8c/s3b5V7spWas="
15
  }
16
  },
17
+ "provenance": { "kernel": { "sha": "91d990483a174128daf7673f3f37a7c890493ae1", "dirty": false } },
18
  "webgpu": {
19
+ "manifestSpec": "2.0",
20
+ "variants": {
21
+ "no_bias_vec4_f16": ["norm-skip-row-vec4.wgsl.jinja"],
22
+ "no_bias_vec4": ["norm-skip-row-vec4.wgsl.jinja"],
23
+ "no_bias_output_only_vec4": ["norm-skip-row-vec4.wgsl.jinja"],
24
+ "no_bias_output_only_vec4_f16": ["norm-skip-row-vec4.wgsl.jinja"],
25
+ "no_bias": ["norm-skip-row.wgsl.jinja"],
26
+ "no_bias_f16": ["norm-skip-row.wgsl.jinja"],
27
+ "no_bias_output_only_f16": ["norm-skip-row.wgsl.jinja"],
28
+ "no_bias_output_only": ["norm-skip-row.wgsl.jinja"],
29
+ "bias_vec4_f16": ["norm-skip-row-vec4.wgsl.jinja"],
30
+ "bias_vec4": ["norm-skip-row-vec4.wgsl.jinja"],
31
+ "bias_output_only_vec4": ["norm-skip-row-vec4.wgsl.jinja"],
32
+ "bias_output_only_vec4_f16": ["norm-skip-row-vec4.wgsl.jinja"],
33
+ "bias": ["norm-skip-row.wgsl.jinja"],
34
+ "bias_f16": ["norm-skip-row.wgsl.jinja"],
35
+ "bias_output_only_f16": ["norm-skip-row.wgsl.jinja"],
36
+ "bias_output_only": ["norm-skip-row.wgsl.jinja"]
37
+ }
38
  }
39
  }
build/webgpu/norm-skip-row-vec4.wgsl.jinja CHANGED
@@ -42,8 +42,9 @@
42
  {{ svar }} = {{ svar }} / 2u;
43
  {% endif %}
44
  }
45
- {%- endmacro %}{% set useSubgroups = source.useSubgroups %}
46
- {% if source.usesF16 %}
 
47
  enable f16;
48
  {% endif %}
49
  {% if useSubgroups %}
@@ -51,9 +52,9 @@ enable subgroups;
51
  {% endif %}
52
  {{ env.wgsl.resourceDeclarations }}
53
 
54
- const HIDDEN: u32 = {{ source.hidden }}u;
55
- const HIDDEN_V: u32 = {{ source.hiddenVec }}u;
56
- const WG: u32 = {{ source.wg }}u;
57
 
58
  var<workgroup> sg_partials: array<f32, WG>;
59
 
@@ -84,9 +85,9 @@ fn reduce_scalar(value: f32{% if useSubgroups %}, sg_lane: u32, sg_id: u32, num_
84
  // 4 contiguous residual elements (input[idx] + skip[skip_idx] [+ bias]) at vec4
85
  // index `vi`. skip_idx == idx for the normal (non-broadcast) path; for a skip
86
  // that broadcasts across the leading/batch dim uses a folded index.
87
- fn residual_value(idx: u32, skip_idx: u32{% if source.hasBias %}, vi: u32{% endif %}) -> vec4<f32> {
88
  var value = vec4<f32>(input[idx]) + vec4<f32>(skip[skip_idx]);
89
- {% if source.hasBias %}
90
  value = value + vec4<f32>(bias[vi]);
91
  {% endif %}
92
  return value;
@@ -106,12 +107,18 @@ fn main(
106
  }
107
  let tid = lid.x;
108
  let base = row * HIDDEN_V;
 
 
 
 
 
109
  let skip_base = base;
 
110
 
111
 
112
  var acc = 0.0;
113
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
114
- let v = residual_value(base + i, skip_base + i{% if source.hasBias %}, i{% endif %});
115
  acc = acc + dot(v, v);
116
  }
117
 
@@ -120,10 +127,10 @@ fn main(
120
 
121
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
122
  let idx = base + i;
123
- let residual = residual_value(idx, skip_base + i{% if source.hasBias %}, i{% endif %});
124
- {% if source.writeResidualSum %}
125
- input_skip_bias_sum[idx] = {{ source.vecType }}(residual);
126
  {% endif %}
127
- output[idx] = {{ source.vecType }}(residual * row_inv * vec4<f32>(gamma[i]));
128
  }
129
  }
 
42
  {{ svar }} = {{ svar }} / 2u;
43
  {% endif %}
44
  }
45
+ {%- endmacro %}{% set broadcastSkip = broadcastSkip is defined and broadcastSkip %}
46
+ {% set useSubgroups = useSubgroups %}
47
+ {% if usesF16Spec %}
48
  enable f16;
49
  {% endif %}
50
  {% if useSubgroups %}
 
52
  {% endif %}
53
  {{ env.wgsl.resourceDeclarations }}
54
 
55
+ const HIDDEN: u32 = {{ hidden }}u;
56
+ const HIDDEN_V: u32 = {{ hiddenVec }}u;
57
+ const WG: u32 = {{ wg }}u;
58
 
59
  var<workgroup> sg_partials: array<f32, WG>;
60
 
 
85
  // 4 contiguous residual elements (input[idx] + skip[skip_idx] [+ bias]) at vec4
86
  // index `vi`. skip_idx == idx for the normal (non-broadcast) path; for a skip
87
  // that broadcasts across the leading/batch dim uses a folded index.
88
+ fn residual_value(idx: u32, skip_idx: u32{% if hasBias %}, vi: u32{% endif %}) -> vec4<f32> {
89
  var value = vec4<f32>(input[idx]) + vec4<f32>(skip[skip_idx]);
90
+ {% if hasBias %}
91
  value = value + vec4<f32>(bias[vi]);
92
  {% endif %}
93
  return value;
 
107
  }
108
  let tid = lid.x;
109
  let base = row * HIDDEN_V;
110
+ {% if broadcastSkip %}
111
+ // skip broadcasts across the batch dim: fold row into [0, skipRows) so every
112
+ // batch reuses the same skip row (skipRows == params.rows ⇒ identity).
113
+ let skip_base = (row % params.skipRows) * HIDDEN_V;
114
+ {% else %}
115
  let skip_base = base;
116
+ {% endif %}
117
 
118
 
119
  var acc = 0.0;
120
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
121
+ let v = residual_value(base + i, skip_base + i{% if hasBias %}, i{% endif %});
122
  acc = acc + dot(v, v);
123
  }
124
 
 
127
 
128
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
129
  let idx = base + i;
130
+ let residual = residual_value(idx, skip_base + i{% if hasBias %}, i{% endif %});
131
+ {% if writeResidualSum %}
132
+ input_skip_bias_sum[idx] = {{ vecType }}(residual);
133
  {% endif %}
134
+ output[idx] = {{ vecType }}(residual * row_inv * vec4<f32>(gamma[i]));
135
  }
136
  }
build/webgpu/norm-skip-row.wgsl.jinja CHANGED
@@ -1,65 +1,13 @@
1
- {% macro wgsl_tree_fold_stmt(a, op, idx, svar) %}
2
- {% if op == "max" %}
3
- {{ a }}[{{ idx }}] = max({{ a }}[{{ idx }}], {{ a }}[{{ idx }} + {{ svar }}]);
4
- {%- else %}
5
- {{ a }}[{{ idx }}] = {{ a }}[{{ idx }}] + {{ a }}[{{ idx }} + {{ svar }}];
6
- {%- endif %}
7
- {% endmacro %}
8
- {% macro wgsl_tree_fold(arrays, op="add", idx="lid", wg="WORKGROUP_SIZE", svar="stride", typed=false, form="tail", breakInline=false, bodyInline=false, barrierFirst=false) %}
9
- var {{ svar }}{{ ": u32 " if typed else " " }}= {{ wg }} / 2u;
10
- loop {
11
- {% if form == "head" %}
12
- {% if breakInline %}
13
- if ({{ svar }} == 0u) { break; }
14
- {% else %}
15
- if ({{ svar }} == 0u) {
16
- break;
17
- }
18
- {% endif %}
19
- {% endif %}
20
- {% if bodyInline %}
21
- if ({{ idx }} < {{ svar }}) { {{ wgsl_tree_fold_stmt(arrays[0], op, idx, svar) }} }
22
- {% else %}
23
- if ({{ idx }} < {{ svar }}) {
24
- {% for a in arrays %}
25
- {{ wgsl_tree_fold_stmt(a, op, idx, svar) }}
26
- {% endfor %}
27
- }
28
- {% endif %}
29
- {% if form == "head" %}
30
- {% if barrierFirst %}
31
- workgroupBarrier();
32
- {{ svar }} = {{ svar }} / 2u;
33
- {% else %}
34
- {{ svar }} = {{ svar }} / 2u;
35
- workgroupBarrier();
36
- {% endif %}
37
- {% else %}
38
- workgroupBarrier();
39
- if ({{ svar }} == 1u) {
40
- break;
41
- }
42
- {{ svar }} = {{ svar }} / 2u;
43
- {% endif %}
44
- }
45
- {%- endmacro %}
46
 
47
  /* One workgroup normalizes each row of residual = input + skip, with an
48
  * optional bias. */
49
- {% set degenerateRow = (not simplified) and hiddenSize == 1 %}
50
  {% if usesF16 %}
51
  enable f16;
52
  {% endif %}
53
- {% if useSubgroups and not degenerateRow %}
54
- enable subgroups;
55
- {% endif %}
56
  {{ env.wgsl.resourceDeclarations }}
57
 
58
- {% if not degenerateRow or writeResidualSum %}
59
  const HIDDEN: u32 = {{ hiddenSize }}u;
60
- {% endif %}
61
  const WG: u32 = {{ workgroupSize }}u;
62
- {% if simplified %}
63
 
64
  var<workgroup> partial: array<f32, WG>;
65
  {% macro wgsl_tree_reduce_f32(name, mode, buffer="partial", wg="WG", trailingBarrier=true) %}
@@ -98,39 +46,7 @@ fn {{ name }}(value: f32, tid: u32) -> f32 {
98
 
99
  {{ wgsl_tree_reduce_f32("reduce_sum", "add", "partial", "WG") }}
100
  var<workgroup> row_inv: f32;
101
- {% else %}
102
- {% if not degenerateRow %}
103
-
104
- var<workgroup> pair_partial: array<vec2<f32>, WG>;
105
-
106
- {% if useSubgroups %}
107
- fn reduce_pair(value: vec2<f32>, sg_lane: u32, sg_id: u32, num_sg: u32) -> vec2<f32> {
108
- let s = vec2<f32>(subgroupAdd(value.x), subgroupAdd(value.y));
109
- if (num_sg == 1u) {
110
- return s;
111
- }
112
- if (sg_lane == 0u) {
113
- pair_partial[sg_id] = s;
114
- }
115
- workgroupBarrier();
116
- var total = vec2<f32>(0.0, 0.0);
117
- for (var i = 0u; i < num_sg; i = i + 1u) {
118
- total = total + pair_partial[i];
119
- }
120
- return total;
121
- }
122
- {% else %}
123
- fn reduce_pair(value: vec2<f32>, tid: u32) -> vec2<f32> {
124
- pair_partial[tid] = value;
125
- workgroupBarrier();
126
- {{ wgsl_tree_fold(["pair_partial"], idx="tid", wg="WG", form="head") }}
127
- return pair_partial[0];
128
- }
129
- {% endif %}
130
- {% endif %}
131
- {% endif %}
132
 
133
- {% if not degenerateRow or writeResidualSum %}
134
  fn residual_value(row: u32, d: u32) -> f32 {
135
  let index = row * HIDDEN + d;
136
  var value = f32(input[index]) + f32(skip[index]);
@@ -139,28 +55,19 @@ fn residual_value(row: u32, d: u32) -> f32 {
139
  {% endif %}
140
  return value;
141
  }
142
- {% endif %}
143
 
144
  @compute @workgroup_size(WG, 1, 1)
145
  fn main(
146
  @builtin(workgroup_id) wg: vec3<u32>,
147
- @builtin(num_workgroups) nwg: vec3<u32>{% if not degenerateRow %},
148
- @builtin(local_invocation_id) lid: vec3<u32>{% endif %}{% if useSubgroups and not degenerateRow %},
149
- @builtin(subgroup_invocation_id) sg_lane: u32,
150
- @builtin(subgroup_id) sg_id: u32,
151
- @builtin(num_subgroups) num_sg: u32{% endif %}
152
- ) {
153
- // 2D-folded row index: wg.y carries the high bits past the maxComputeWorkgroupsPerDimension
154
- // workgroup-per-dimension dispatch limit. Reduces to wg.x when nwg.y == 1;
155
  // the row >= params.rows guard drops the over-dispatched tail.
156
- let row = wg.x + wg.y * nwg.x;
157
  if (row >= params.rows) {
158
  return;
159
  }
160
- {% if not degenerateRow %}
161
  let tid = lid.x;
162
- {% endif %}
163
- {% if simplified %}
164
 
165
  // RMS normalization uses one sum-of-squares sweep, without a mean or beta.
166
 
@@ -183,47 +90,4 @@ fn main(
183
  {% endif %}
184
  output[index] = {{ scalar }}(residual * row_inv * f32(gamma[d]));
185
  }
186
- {% elif degenerateRow %}
187
-
188
- // HIDDEN == 1: the row's mean is its only element, so the centered value and
189
- // the variance are exactly zero and the output reduces to beta. The closed
190
- // form avoids computing that zero by subtracting two equal rounded values.
191
- let row_inv = inverseSqrt(params.epsilon);
192
- {% if writeResidualSum %}
193
- let residual = residual_value(row, 0u);
194
- input_skip_bias_sum[row] = {{ scalar }}(residual);
195
- {% endif %}
196
- // 0.0 * row_inv keeps the IEEE result when epsilon == 0 makes row_inv +Inf.
197
- output[row] = {{ scalar }}(0.0 * row_inv * f32(gamma[0]){% if hasBeta %} + f32(beta[0]){% endif %});
198
- {% else %}
199
-
200
- // Shifted moments: accumulating (x - x[0], (x - x[0])^2) keeps the sums
201
- // small for rows with a large common offset; every thread reconstructs the
202
- // row mean and variance from the merged pair.
203
- let shift = residual_value(row, 0u);
204
- var acc = vec2<f32>(0.0, 0.0);
205
- for (var d = tid; d < HIDDEN; d = d + WG) {
206
- let centered = residual_value(row, d) - shift;
207
- acc.x = acc.x + centered;
208
- acc.y = acc.y + centered * centered;
209
- }
210
-
211
- {% if useSubgroups %}
212
- let totals = reduce_pair(acc, sg_lane, sg_id, num_sg);
213
- {% else %}
214
- let totals = reduce_pair(acc, tid);
215
- {% endif %}
216
- let mean_delta = totals.x / f32(HIDDEN);
217
- let row_mean = shift + mean_delta;
218
- let variance = max(totals.y / f32(HIDDEN) - mean_delta * mean_delta, 0.0);
219
- let row_inv = inverseSqrt(variance + params.epsilon);
220
- for (var d = tid; d < HIDDEN; d = d + WG) {
221
- let index = row * HIDDEN + d;
222
- let residual = residual_value(row, d);
223
- {% if writeResidualSum %}
224
- input_skip_bias_sum[index] = {{ scalar }}(residual);
225
- {% endif %}
226
- output[index] = {{ scalar }}((residual - row_mean) * row_inv * f32(gamma[d]){% if hasBeta %} + f32(beta[d]){% endif %});
227
- }
228
- {% endif %}
229
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
 
2
  /* One workgroup normalizes each row of residual = input + skip, with an
3
  * optional bias. */
 
4
  {% if usesF16 %}
5
  enable f16;
6
  {% endif %}
 
 
 
7
  {{ env.wgsl.resourceDeclarations }}
8
 
 
9
  const HIDDEN: u32 = {{ hiddenSize }}u;
 
10
  const WG: u32 = {{ workgroupSize }}u;
 
11
 
12
  var<workgroup> partial: array<f32, WG>;
13
  {% macro wgsl_tree_reduce_f32(name, mode, buffer="partial", wg="WG", trailingBarrier=true) %}
 
46
 
47
  {{ wgsl_tree_reduce_f32("reduce_sum", "add", "partial", "WG") }}
48
  var<workgroup> row_inv: f32;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
 
50
  fn residual_value(row: u32, d: u32) -> f32 {
51
  let index = row * HIDDEN + d;
52
  var value = f32(input[index]) + f32(skip[index]);
 
55
  {% endif %}
56
  return value;
57
  }
 
58
 
59
  @compute @workgroup_size(WG, 1, 1)
60
  fn main(
61
  @builtin(workgroup_id) wg: vec3<u32>,
62
+ @builtin(local_invocation_id) lid: vec3<u32>) {
63
+ // 2D-folded row index: wg.y carries the high bits past the per-axis dispatch fold width.
64
+ // Reduces to wg.x when the dispatch does not fold;
 
 
 
 
 
65
  // the row >= params.rows guard drops the over-dispatched tail.
66
+ let row = wg.x + wg.y * {{ DISPATCH_FOLD_WIDTH }}u;
67
  if (row >= params.rows) {
68
  return;
69
  }
 
70
  let tid = lid.x;
 
 
71
 
72
  // RMS normalization uses one sum-of-squares sweep, without a mean or beta.
73
 
 
90
  {% endif %}
91
  output[index] = {{ scalar }}(residual * row_inv * f32(gamma[d]));
92
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  }
build/webgpu/test.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "com.microsoft.SkipSimplifiedLayerNormalization",
3
  "cases": [
4
  {
5
  "name": "no_bias",
@@ -93,7 +92,7 @@
93
  "inputT": {
94
  "dtype": "float32",
95
  "shape": [2, 4],
96
- "data": { "kind": "values", "values": [5.0, 5.0, 5.0, 5.0, -3.0, -3.0, -3.0, -3.0] }
97
  },
98
  "skipT": {
99
  "dtype": "float32",
@@ -133,7 +132,7 @@
133
  "skipT": {
134
  "dtype": "float32",
135
  "shape": [1, 4],
136
- "data": { "kind": "values", "values": [-39999.0, -40000.0, -40001.0, -40002.0] }
137
  },
138
  "gammaT": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [1.0, 2.0, -1.0, 0.5] } }
139
  },
@@ -147,7 +146,7 @@
147
  "provenance": {
148
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
149
  "test": "SkipLayerNormTest.SkipLayerNormNullInput",
150
- "notes": "Same zero-token lowered shape as ORT's SkipLayerNormalization null-input case, applied to simplified RMS normalization."
151
  },
152
  "attrs": { "epsilon": 1e-12 },
153
  "inputs": {
@@ -275,7 +274,7 @@
275
  "provenance": {
276
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
277
  "test": "SkipLayerNormTest.SkipSimplifiedLayerNormBatch1_Float16",
278
- "notes": "ORT fp16 shape [1, 2, 4] is represented as float32 [2, 4] tokens by this lowered kernel. Epsilon is omitted to exercise the schema default of 1e-12."
279
  },
280
  "inputs": {
281
  "inputT": {
@@ -300,7 +299,7 @@
300
  "provenance": {
301
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
302
  "test": "SkipLayerNormTest.SkipSimplifiedLayerNormBatch1_Bias_Float16",
303
- "notes": "ORT fp16 shape [1, 1, 8] is represented as float32 [1, 8] tokens by this lowered kernel."
304
  },
305
  "attrs": { "epsilon": 0.00001 },
306
  "inputs": {
@@ -373,7 +372,7 @@
373
  {
374
  "name": "no_bias_hidden128_compact",
375
  "provenance": {
376
- "notes": "Compact hidden-size-128 companion for the output-only bench family; keeps the same row width under reference-computed full outputs."
377
  },
378
  "attrs": { "epsilon": 0.00001 },
379
  "inputs": {
@@ -832,6 +831,31 @@
832
  }
833
  },
834
  "outputs": { "outputT": { "dtype": "float16", "shape": [2, 6], "tolerance": 0.01 } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
835
  }
836
  ]
837
  }
 
1
  {
 
2
  "cases": [
3
  {
4
  "name": "no_bias",
 
92
  "inputT": {
93
  "dtype": "float32",
94
  "shape": [2, 4],
95
+ "data": { "kind": "values", "values": [5.0, 5.0, 5.0, 5.0, -3.0, -2.0, -1.0, 0.0] }
96
  },
97
  "skipT": {
98
  "dtype": "float32",
 
132
  "skipT": {
133
  "dtype": "float32",
134
  "shape": [1, 4],
135
+ "data": { "kind": "values", "values": [-39999.0, -39999.5, -40000.0, -40000.5] }
136
  },
137
  "gammaT": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [1.0, 2.0, -1.0, 0.5] } }
138
  },
 
146
  "provenance": {
147
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
148
  "test": "SkipLayerNormTest.SkipLayerNormNullInput",
149
+ "notes": "A zero-token ORT shape is flattened to an empty token-row input for simplified RMS normalization."
150
  },
151
  "attrs": { "epsilon": 1e-12 },
152
  "inputs": {
 
274
  "provenance": {
275
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
276
  "test": "SkipLayerNormTest.SkipSimplifiedLayerNormBatch1_Float16",
277
+ "notes": "This package represents ORT's float16 shape [1, 2, 4] as two float32 token rows of width 4. Epsilon is omitted to exercise the schema default of 1e-12."
278
  },
279
  "inputs": {
280
  "inputT": {
 
299
  "provenance": {
300
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
301
  "test": "SkipLayerNormTest.SkipSimplifiedLayerNormBatch1_Bias_Float16",
302
+ "notes": "This package represents ORT's float16 shape [1, 1, 8] as one float32 token row of width 8."
303
  },
304
  "attrs": { "epsilon": 0.00001 },
305
  "inputs": {
 
372
  {
373
  "name": "no_bias_hidden128_compact",
374
  "provenance": {
375
+ "notes": "A compact hidden-size-128 case exercises full outputs at the row width used by the output-only benchmark family."
376
  },
377
  "attrs": { "epsilon": 0.00001 },
378
  "inputs": {
 
831
  }
832
  },
833
  "outputs": { "outputT": { "dtype": "float16", "shape": [2, 6], "tolerance": 0.01 } }
834
+ },
835
+ {
836
+ "name": "zero_row_epsilon_zero",
837
+ "provenance": {
838
+ "notes": "An all-zero padded row with epsilon 0 computes `inverseSqrt(0) = +Inf` and then `0 * Inf = NaN`; the simplified RMS contract has no finite degenerate-row special case."
839
+ },
840
+ "attrs": { "epsilon": 0 },
841
+ "inputs": {
842
+ "inputT": {
843
+ "dtype": "float32",
844
+ "shape": [1, 4, 64],
845
+ "data": { "kind": "cycle", "values": [0.5, -0.25, 0.75, 0.0, 0.0, 0.0, 0.0, 0.0] }
846
+ },
847
+ "skipT": { "dtype": "float32", "shape": [1, 4, 64], "data": { "kind": "constant", "value": 0.0 } },
848
+ "gammaT": { "dtype": "float32", "shape": [64], "data": { "kind": "constant", "value": 1.0 } }
849
+ },
850
+ "outputs": {
851
+ "outputT": {
852
+ "dtype": "float32",
853
+ "shape": [1, 4, 64],
854
+ "tolerance": 0.00002,
855
+ "relTolerance": 0.00002,
856
+ "allowNaN": true
857
+ }
858
+ }
859
  }
860
  ]
861
  }