Xenova HF Staff commited on
Commit
62736d3
·
verified ·
1 Parent(s): 2760d09

sync 91d990483a17

Browse files
README.md CHANGED
@@ -12,26 +12,26 @@ tags:
12
 
13
  ## Description
14
 
15
- Fuses skip addition with layer normalization. The rank-3 standard surface currently supports float32, required `beta`, no `bias` or residual output, hidden sizes divisible by four, and exact or documented broadcast skip shapes. The provider's rank-2 extension supports float32 output-only with optional `beta`, or `beta` with optional `bias` when emitting the residual; its float16 path requires `beta`, `bias`, a residual output, and four-wide hidden size. Other combinations, bfloat16, and training statistics are not implemented.
16
 
17
  See the [ONNX Runtime `SkipLayerNormalization` contrib-operator spec](https://github.com/microsoft/onnxruntime/blob/main/docs/ContribOperators.md#com.microsoft.SkipLayerNormalization) for the reference semantics.
18
 
19
  ## Inputs
20
 
21
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
22
  | --- | --- | --- | --- | --- | --- | --- |
23
- | `input` | `inputT` | `T` | — | — | Primary input normalized over the final hidden-size axis. Rank 3 is the public shape; rank 2 is an ONNX Runtime provider extension supported by this package. | required |
24
- | `skip` | `skipT` | `T` | — | — | Residual tensor. For rank-3 input it is exact shape, `(1, sequence_length, hidden_size)`, or `(sequence_length, hidden_size)`; rank-2 input requires exact shape. | required |
25
- | `gamma` | `gammaT` | `T` | `1` | — | Layer-norm scale weights of shape `(hidden_size)`. | required |
26
- | `beta` | `betaT` | `T` | `1` | — | Layer-norm bias weights of shape `(hidden_size)`. | optional |
27
- | `bias` | `biasT` | `T` | `1` | — | Optional additive bias of shape `(hidden_size)` added to `input + skip` before normalization. | optional |
28
 
29
  ## Outputs
30
 
31
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
32
  | --- | --- | --- | --- | --- | --- | --- |
33
- | `output` | `outputT` | `T` | same as `input` | same as `input` | Normalized output tensor with the same shape as `input`. | required |
34
- | `input_skip_bias_sum` | `residualT` | `T` | same as `input` | same as `input` | Sum of `input`, `skip`, and `bias` (when present) before normalization, with the same shape as `input`. | optional |
35
 
36
  ## Attributes
37
 
@@ -47,9 +47,13 @@ Default values (overridable per request):
47
  | --- | --- |
48
  | `T` | `float32`, `float16` |
49
 
 
 
 
 
50
  ## Files
51
 
52
- - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
53
  - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
54
  - [`test.json`](build/webgpu/test.json) — correctness cases
55
  - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
@@ -58,10 +62,14 @@ Default values (overridable per request):
58
 
59
  ## Use with `@huggingface/kernels`
60
 
61
- The loader derives every required output's shape and logical dtype from the manifest contract and this call.
62
- It then allocates the result tensors automatically.
 
 
 
63
 
64
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
 
65
 
66
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
67
 
 
12
 
13
  ## Description
14
 
15
+ Fuses skip addition with layer normalization for rank-2 or rank-3 input and a non-empty hidden axis. With exact-shape skip, float32 and float16 output-only paths support optional `beta`; adding `bias` requires `beta`. Returning the residual sum requires `beta`: float32 supports optional `bias` and arbitrary hidden sizes, while float16 requires `bias` and a hidden size divisible by four. Broadcast skip is supported for rank-3 float32 input, required `beta`, no `bias` or residual output, and a hidden size divisible by four. Bfloat16 and training statistics are not implemented.
16
 
17
  See the [ONNX Runtime `SkipLayerNormalization` contrib-operator spec](https://github.com/microsoft/onnxruntime/blob/main/docs/ContribOperators.md#com.microsoft.SkipLayerNormalization) for the reference semantics.
18
 
19
  ## Inputs
20
 
21
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
22
  | --- | --- | --- | --- | --- | --- | --- |
23
+ | `inputT` | `input` | `T` | — | — | Primary input normalized over the final hidden-size axis. Rank 3 is the standard shape; rank 2 is a supported extension. | required |
24
+ | `skipT` | `skip` | `T` | — | — | Residual tensor. For rank-3 input it is exact shape, `(1, sequence_length, hidden_size)`, or `(sequence_length, hidden_size)`; rank-2 input requires exact shape. | required |
25
+ | `gammaT` | `gamma` | `T` | `1` | — | Layer-norm scale weights of shape `(hidden_size)`. | required |
26
+ | `betaT` | `beta` | `T` | `1` | — | Layer-norm bias weights of shape `(hidden_size)`. | optional |
27
+ | `biasT` | `bias` | `T` | `1` | — | Optional additive bias of shape `(hidden_size)` added to `input + skip` before normalization. | optional |
28
 
29
  ## Outputs
30
 
31
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
32
  | --- | --- | --- | --- | --- | --- | --- |
33
+ | `outputT` | `output` | `T` | same as `inputT` | same as `inputT` | Normalized output tensor with the same shape as `input`. | required |
34
+ | `residualT` | `input_skip_bias_sum` | `T` | same as `inputT` | same as `inputT` | Sum of `input`, `skip`, and `bias` (when present) before normalization, with the same shape as `input`. | optional |
35
 
36
  ## Attributes
37
 
 
47
  | --- | --- |
48
  | `T` | `float32`, `float16` |
49
 
50
+ ## Device requirements
51
+
52
+ Some implementation variants require `shader-f16`. These are route-specific capabilities, not package-wide requirements; availability also depends on the request shape and dtype.
53
+
54
  ## Files
55
 
56
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, provenance)
57
  - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
58
  - [`test.json`](build/webgpu/test.json) — correctness cases
59
  - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
 
62
 
63
  ## Use with `@huggingface/kernels`
64
 
65
+ ```sh
66
+ npm install --save-exact @huggingface/kernels@0.0.1-preview.2
67
+ ```
68
+
69
+ Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
70
 
71
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
72
+ It follows the `v1` branch as fixes land. To pin exact artifact bytes, pass a 40-character commit `revision` instead of `version`.
73
 
74
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
75
 
build/webgpu/bench.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "com.microsoft.SkipLayerNormalization",
3
  "cases": [
4
  {
5
  "name": "skip-layernorm-f32-256x128",
@@ -107,7 +106,7 @@
107
  "name": "skip-layernorm-f32-bias-output-only-4096x768",
108
  "preset": "model",
109
  "provenance": {
110
- "notes": "Ordinary inference shape with bias present and all three optional outputs omitted. It uses six storage buffers and writes only the primary output, isolating the output-only path from the full-output sibling at the same geometry."
111
  },
112
  "vars": { "rows": 4096, "hidden": 768 },
113
  "attrs": { "epsilon": 0.00001 },
@@ -139,7 +138,7 @@
139
  "bench": { "metrics": [{ "type": "bandwidth", "value": "4 * (4 * args.rows * args.hidden + 2 * args.hidden)" }] }
140
  },
141
  {
142
- "name": "skip-layernorm-f32-4096x768-hidden768-aligned-sibling",
143
  "preset": "model",
144
  "vars": { "rows": 4096, "hidden": 768 },
145
  "attrs": { "epsilon": 0.00001 },
@@ -173,7 +172,7 @@
173
  "bench": { "metrics": [{ "type": "bandwidth", "value": "4 * (4 * args.rows * args.hidden + 2 * args.hidden)" }] }
174
  },
175
  {
176
- "name": "skip-layernorm-f32-rows4096-hidden4096-prefill-sibling",
177
  "preset": "model",
178
  "vars": { "rows": 4096, "hidden": 4096 },
179
  "attrs": { "epsilon": 0.00001 },
 
1
  {
 
2
  "cases": [
3
  {
4
  "name": "skip-layernorm-f32-256x128",
 
106
  "name": "skip-layernorm-f32-bias-output-only-4096x768",
107
  "preset": "model",
108
  "provenance": {
109
+ "notes": "An ordinary inference shape with bias omits all three optional outputs, uses six storage buffers, and writes only the primary output."
110
  },
111
  "vars": { "rows": 4096, "hidden": 768 },
112
  "attrs": { "epsilon": 0.00001 },
 
138
  "bench": { "metrics": [{ "type": "bandwidth", "value": "4 * (4 * args.rows * args.hidden + 2 * args.hidden)" }] }
139
  },
140
  {
141
+ "name": "skip-layernorm-f32-4096x768-hidden768-aligned",
142
  "preset": "model",
143
  "vars": { "rows": 4096, "hidden": 768 },
144
  "attrs": { "epsilon": 0.00001 },
 
172
  "bench": { "metrics": [{ "type": "bandwidth", "value": "4 * (4 * args.rows * args.hidden + 2 * args.hidden)" }] }
173
  },
174
  {
175
+ "name": "skip-layernorm-f32-rows4096-hidden4096-prefill",
176
  "preset": "model",
177
  "vars": { "rows": 4096, "hidden": 4096 },
178
  "attrs": { "epsilon": 0.00001 },
build/webgpu/manifest.json CHANGED
@@ -2,765 +2,170 @@
2
  "domain": "com.microsoft",
3
  "name": "SkipLayerNormalization",
4
  "sinceVersion": 1,
5
- "description": "Fuses skip addition with layer normalization. The rank-3 standard surface currently supports float32, required `beta`, no `bias` or residual output, hidden sizes divisible by four, and exact or documented broadcast skip shapes. The provider's rank-2 extension supports float32 output-only with optional `beta`, or `beta` with optional `bias` when emitting the residual; its float16 path requires `beta`, `bias`, a residual output, and four-wide hidden size. Other combinations, bfloat16, and training statistics are not implemented.",
6
- "inputs": [
7
- {
8
- "role": "input",
9
- "dtype": "T",
10
- "description": "Primary input normalized over the final hidden-size axis. Rank 3 is the public shape; rank 2 is an ONNX Runtime provider extension supported by this package."
11
- },
12
- {
13
- "role": "skip",
14
- "dtype": "T",
15
- "description": "Residual tensor. For rank-3 input it is exact shape, `(1, sequence_length, hidden_size)`, or `(sequence_length, hidden_size)`; rank-2 input requires exact shape."
16
- },
17
- { "role": "gamma", "dtype": "T", "rank": 1, "description": "Layer-norm scale weights of shape `(hidden_size)`." },
18
- {
19
- "role": "beta",
20
- "dtype": "T",
21
- "rank": 1,
22
- "optional": true,
23
- "description": "Layer-norm bias weights of shape `(hidden_size)`."
24
- },
25
- {
26
- "role": "bias",
27
- "dtype": "T",
28
- "rank": 1,
29
- "optional": true,
30
- "description": "Optional additive bias of shape `(hidden_size)` added to `input + skip` before normalization."
31
- }
32
- ],
33
- "outputs": [
34
- {
35
- "role": "output",
36
- "dtype": "T",
37
- "rank": "ranks.inputT",
38
- "shape": "shapes.inputT",
39
- "description": "Normalized output tensor with the same shape as `input`."
40
- },
41
- {
42
- "role": "input_skip_bias_sum",
43
  "dtype": "T",
44
  "rank": "ranks.inputT",
45
  "optional": true,
46
- "shape": "shapes.inputT",
47
- "description": "Sum of `input`, `skip`, and `bias` (when present) before normalization, with the same shape as `input`."
48
  }
49
- ],
50
- "attributes": { "epsilon": 9.999999960041972e-13 },
51
- "attributeDescriptions": { "epsilon": "Non-negative epsilon added to the variance before taking the square root." },
52
- "args": {
53
- "inputT": { "kind": "tensor", "semantic": "input", "role": "input" },
54
- "skipT": { "kind": "tensor", "semantic": "skip", "role": "input" },
55
- "gammaT": { "kind": "tensor", "semantic": "gamma", "role": "input" },
56
- "betaT": { "kind": "tensor", "semantic": "beta", "role": "input", "required": false },
57
- "biasT": { "kind": "tensor", "semantic": "bias", "role": "input", "required": false },
58
- "outputT": { "kind": "tensor", "semantic": "output", "role": "output" },
59
- "residualT": { "kind": "tensor", "semantic": "input_skip_bias_sum", "role": "output", "required": false }
60
  },
 
61
  "typeConstraints": { "T": ["float32", "float16"] },
 
62
  "derive": {
63
- "rowCount": "dim(shapes.inputT, 0)",
64
- "hiddenSize": "dim(shapes.inputT, 1)",
65
  "skipWg": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(hiddenSize)))",
66
  "skipWgVec4": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(ceilDiv(hiddenSize, 4))))",
67
  "portableWideExecution": "not has(device.adapterInfo, \"subgroupMinSize\") or device.adapterInfo.subgroupMinSize >= 32",
68
  "broadcastRows": "dim(shapes.inputT, 0) * dim(shapes.inputT, 1)",
69
  "broadcastHiddenSize": "dim(shapes.inputT, 2)",
70
  "broadcastSkipWgVec4": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(ceilDiv(broadcastHiddenSize, 4))))",
71
- "rowDispatchFits": "rowCount <= device.limits.maxComputeWorkgroupsPerDimension * device.limits.maxComputeWorkgroupsPerDimension",
72
- "broadcastDispatchFits": "broadcastRows <= device.limits.maxComputeWorkgroupsPerDimension * device.limits.maxComputeWorkgroupsPerDimension",
73
  "normResourcesFit": "skipWg * 8 <= device.limits.maxComputeWorkgroupStorageSize and skipWgVec4 * 8 <= device.limits.maxComputeWorkgroupStorageSize",
74
  "broadcastResourcesFit": "broadcastSkipWgVec4 * 8 <= device.limits.maxComputeWorkgroupStorageSize",
75
  "epsilonOk": "attrs.epsilon >= 0",
76
- "rank2CoreContract": "epsilonOk and ranks.inputT == 2 and ranks.skipT == 2 and ranks.gammaT == 1 and ranks.outputT == 2 and dim(shapes.inputT, 0) == dim(shapes.skipT, 0) and dim(shapes.inputT, 1) == dim(shapes.skipT, 1) and dim(shapes.inputT, 1) > 0 and dim(shapes.gammaT, 0) == dim(shapes.inputT, 1) and dim(shapes.outputT, 0) == dim(shapes.inputT, 0) and dim(shapes.outputT, 1) == dim(shapes.inputT, 1)",
77
- "residualOutputContract": "present.residualT and ranks.residualT == 2 and dim(shapes.residualT, 0) == dim(shapes.inputT, 0) and dim(shapes.residualT, 1) == dim(shapes.inputT, 1)",
78
  "outputOnlyContract": "not present.residualT",
79
- "betaContract": "false if not present.betaT else (ranks.betaT == 1 and dim(shapes.betaT, 0) == dim(shapes.inputT, 1))",
80
  "noBetaContract": "not present.betaT",
81
  "f32MainDtypes": "tensorDtypes.inputT == \"float32\" and tensorDtypes.skipT == \"float32\" and tensorDtypes.gammaT == \"float32\" and tensorDtypes.outputT == \"float32\"",
82
  "f16MainDtypes": "tensorDtypes.inputT == \"float16\" and tensorDtypes.skipT == \"float16\" and tensorDtypes.gammaT == \"float16\" and tensorDtypes.outputT == \"float16\"",
83
  "f32ResidualDtypes": "f32MainDtypes and tensorDtypes.residualT == \"float32\" if present.residualT else false",
84
  "f16ResidualDtypes": "f16MainDtypes and tensorDtypes.residualT == \"float16\" if present.residualT else false",
85
- "vec4Aligned": "dim(shapes.inputT, 1) % 4 == 0",
86
  "broadcastSkipShapeOk": "(ranks.skipT == 2 and dim(shapes.skipT, 0) == dim(shapes.inputT, 1) and dim(shapes.skipT, 1) == dim(shapes.inputT, 2)) or (ranks.skipT == 3 and ((dim(shapes.skipT, 0) == 1 and dim(shapes.skipT, 1) == dim(shapes.inputT, 1) and dim(shapes.skipT, 2) == dim(shapes.inputT, 2)) or sameShape(shapes.skipT, shapes.inputT)))",
87
  "broadcastOutputOnlyContract": "false if ranks.inputT != 3 or not present.betaT else (epsilonOk and not present.biasT and not present.residualT and dim(shapes.inputT, 2) % 4 == 0 and broadcastSkipShapeOk and ranks.gammaT == 1 and ranks.betaT == 1 and ranks.outputT == 3 and tensorDtypes.inputT == \"float32\" and tensorDtypes.skipT == \"float32\" and tensorDtypes.gammaT == \"float32\" and tensorDtypes.betaT == \"float32\" and tensorDtypes.outputT == \"float32\" and dim(shapes.inputT, 2) > 0 and dim(shapes.gammaT, 0) == dim(shapes.inputT, 2) and dim(shapes.betaT, 0) == dim(shapes.inputT, 2) and sameShape(shapes.outputT, shapes.inputT))",
88
  "hasSubgroups": "device.features.has(\"subgroups\") and device.wgslLanguageFeatures.has(\"subgroup_id\")",
89
  "hasF16": "device.features.has(\"shader-f16\")",
90
- "f32_beta_no_bias_residual_contract": "rank2CoreContract and residualOutputContract and betaContract and f32ResidualDtypes and not present.biasT and tensorDtypes.betaT == \"float32\"",
91
- "f32_beta_bias_residual_contract": "false if not present.biasT else (rank2CoreContract and residualOutputContract and betaContract and f32ResidualDtypes and ranks.biasT == 1 and tensorDtypes.betaT == \"float32\" and tensorDtypes.biasT == \"float32\" and dim(shapes.biasT, 0) == hiddenSize)",
92
- "f16_beta_bias_residual_contract": "false if not present.biasT else (hasF16 and rank2CoreContract and residualOutputContract and betaContract and f16ResidualDtypes and ranks.biasT == 1 and tensorDtypes.betaT == \"float16\" and tensorDtypes.biasT == \"float16\" and dim(shapes.biasT, 0) == hiddenSize)",
93
- "f32_no_beta_output_contract": "rank2CoreContract and outputOnlyContract and noBetaContract and f32MainDtypes and not present.biasT",
94
- "f32_beta_no_bias_output_only_contract": "rank2CoreContract and outputOnlyContract and betaContract and f32MainDtypes and not present.biasT and tensorDtypes.betaT == \"float32\"",
95
- "f32_beta_bias_output_only_contract": "false if not present.biasT else (rank2CoreContract and outputOnlyContract and betaContract and f32MainDtypes and ranks.biasT == 1 and tensorDtypes.betaT == \"float32\" and tensorDtypes.biasT == \"float32\" and dim(shapes.biasT, 0) == hiddenSize)"
 
 
 
96
  },
97
- "bindingSets": {
98
- "scalar_no_bias_residual": [
99
- {
100
- "name": "input",
101
- "arg": "inputT",
102
- "semantic": "input",
103
- "buffer": { "type": "read-only-storage" },
104
- "elementType": "$scalar"
105
- },
106
- {
107
- "name": "skip",
108
- "arg": "skipT",
109
- "semantic": "skip",
110
- "buffer": { "type": "read-only-storage" },
111
- "elementType": "$scalar"
112
- },
113
- {
114
- "name": "gamma",
115
- "arg": "gammaT",
116
- "semantic": "gamma",
117
- "buffer": { "type": "read-only-storage" },
118
- "elementType": "$scalar",
119
- "length": "$HIDDEN_LEN"
120
- },
121
- {
122
- "name": "beta",
123
- "arg": "betaT",
124
- "semantic": "beta",
125
- "buffer": { "type": "read-only-storage" },
126
- "elementType": "$scalar",
127
- "length": "$HIDDEN_LEN"
128
- },
129
- {
130
- "name": "output",
131
- "arg": "outputT",
132
- "semantic": "output",
133
- "buffer": { "type": "storage" },
134
- "elementType": "$scalar"
135
- },
136
- {
137
- "name": "input_skip_bias_sum",
138
- "arg": "residualT",
139
- "semantic": "input_skip_bias_sum",
140
- "buffer": { "type": "storage" },
141
- "elementType": "$scalar"
142
- },
143
- {
144
- "name": "params",
145
- "semantic": "kernel.params",
146
- "buffer": { "type": "uniform" },
147
- "struct": {
148
- "name": "Params",
149
- "fields": [
150
- { "name": "rows", "type": "u32", "value": "rowCount" },
151
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
152
- ]
153
- }
154
- }
155
- ],
156
- "scalar_bias_output_residual": [
157
- {
158
- "name": "input",
159
- "arg": "inputT",
160
- "semantic": "input",
161
- "buffer": { "type": "read-only-storage" },
162
- "elementType": "$scalar"
163
- },
164
- {
165
- "name": "skip",
166
- "arg": "skipT",
167
- "semantic": "skip",
168
- "buffer": { "type": "read-only-storage" },
169
- "elementType": "$scalar"
170
- },
171
- {
172
- "name": "bias",
173
- "arg": "biasT",
174
- "semantic": "bias",
175
- "buffer": { "type": "read-only-storage" },
176
- "elementType": "$scalar",
177
- "length": "$HIDDEN_LEN"
178
- },
179
- {
180
- "name": "gamma",
181
- "arg": "gammaT",
182
- "semantic": "gamma",
183
- "buffer": { "type": "read-only-storage" },
184
- "elementType": "$scalar",
185
- "length": "$HIDDEN_LEN"
186
- },
187
- {
188
- "name": "beta",
189
- "arg": "betaT",
190
- "semantic": "beta",
191
- "buffer": { "type": "read-only-storage" },
192
- "elementType": "$scalar",
193
- "length": "$HIDDEN_LEN"
194
- },
195
- {
196
- "name": "output",
197
- "arg": "outputT",
198
- "semantic": "output",
199
- "buffer": { "type": "storage" },
200
- "elementType": "$scalar"
201
- },
202
- {
203
- "name": "input_skip_bias_sum",
204
- "arg": "residualT",
205
- "semantic": "input_skip_bias_sum",
206
- "buffer": { "type": "storage" },
207
- "elementType": "$scalar"
208
- },
209
- {
210
- "name": "params",
211
- "semantic": "kernel.params",
212
- "buffer": { "type": "uniform" },
213
- "struct": {
214
- "name": "Params",
215
- "fields": [
216
- { "name": "rows", "type": "u32", "value": "rowCount" },
217
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
218
- ]
219
- }
220
- }
221
- ],
222
- "vec4_bias_output_residual": [
223
- {
224
- "name": "input",
225
- "arg": "inputT",
226
- "semantic": "input",
227
- "buffer": { "type": "read-only-storage" },
228
- "elementType": "$vectorScalar"
229
- },
230
- {
231
- "name": "skip",
232
- "arg": "skipT",
233
- "semantic": "skip",
234
- "buffer": { "type": "read-only-storage" },
235
- "elementType": "$vectorScalar"
236
- },
237
- {
238
- "name": "bias",
239
- "arg": "biasT",
240
- "semantic": "bias",
241
- "buffer": { "type": "read-only-storage" },
242
- "elementType": "$vectorScalar",
243
- "length": "$HIDDEN_LEN"
244
- },
245
- {
246
- "name": "gamma",
247
- "arg": "gammaT",
248
- "semantic": "gamma",
249
- "buffer": { "type": "read-only-storage" },
250
- "elementType": "$vectorScalar",
251
- "length": "$HIDDEN_LEN"
252
- },
253
- {
254
- "name": "beta",
255
- "arg": "betaT",
256
- "semantic": "beta",
257
- "buffer": { "type": "read-only-storage" },
258
- "elementType": "$vectorScalar",
259
- "length": "$HIDDEN_LEN"
260
- },
261
- {
262
- "name": "output",
263
- "arg": "outputT",
264
- "semantic": "output",
265
- "buffer": { "type": "storage" },
266
- "elementType": "$vectorScalar"
267
- },
268
- {
269
- "name": "input_skip_bias_sum",
270
- "arg": "residualT",
271
- "semantic": "input_skip_bias_sum",
272
- "buffer": { "type": "storage" },
273
- "elementType": "$vectorScalar"
274
- },
275
- {
276
- "name": "params",
277
- "semantic": "kernel.params",
278
- "buffer": { "type": "uniform" },
279
- "struct": {
280
- "name": "Params",
281
- "fields": [
282
- { "name": "rows", "type": "u32", "value": "rowCount" },
283
- {
284
- "name": "rowStride",
285
- "type": "u32",
286
- "value": "max(1, min(rowCount, device.limits.maxComputeWorkgroupsPerDimension))"
287
- },
288
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
289
- ]
290
- }
291
- }
292
- ],
293
- "scalar_no_bias_output_only": [
294
- {
295
- "name": "input",
296
- "arg": "inputT",
297
- "semantic": "input",
298
- "buffer": { "type": "read-only-storage" },
299
- "elementType": "$scalar"
300
- },
301
- {
302
- "name": "skip",
303
- "arg": "skipT",
304
- "semantic": "skip",
305
- "buffer": { "type": "read-only-storage" },
306
- "elementType": "$scalar"
307
- },
308
- {
309
- "name": "gamma",
310
- "arg": "gammaT",
311
- "semantic": "gamma",
312
- "buffer": { "type": "read-only-storage" },
313
- "elementType": "$scalar",
314
- "length": "$HIDDEN_LEN"
315
- },
316
- {
317
- "name": "beta",
318
- "arg": "betaT",
319
- "semantic": "beta",
320
- "buffer": { "type": "read-only-storage" },
321
- "elementType": "$scalar",
322
- "length": "$HIDDEN_LEN"
323
- },
324
- {
325
- "name": "output",
326
- "arg": "outputT",
327
- "semantic": "output",
328
- "buffer": { "type": "storage" },
329
- "elementType": "$scalar"
330
- },
331
- {
332
- "name": "params",
333
- "semantic": "kernel.params",
334
- "buffer": { "type": "uniform" },
335
- "struct": {
336
- "name": "Params",
337
- "fields": [
338
- { "name": "rows", "type": "u32", "value": "rowCount" },
339
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
340
- ]
341
- }
342
- }
343
- ],
344
- "scalar_bias_output_only": [
345
- {
346
- "name": "input",
347
- "arg": "inputT",
348
- "semantic": "input",
349
- "buffer": { "type": "read-only-storage" },
350
- "elementType": "$scalar"
351
- },
352
- {
353
- "name": "skip",
354
- "arg": "skipT",
355
- "semantic": "skip",
356
- "buffer": { "type": "read-only-storage" },
357
- "elementType": "$scalar"
358
- },
359
- {
360
- "name": "bias",
361
- "arg": "biasT",
362
- "semantic": "bias",
363
- "buffer": { "type": "read-only-storage" },
364
- "elementType": "$scalar",
365
- "length": "$HIDDEN_LEN"
366
- },
367
- {
368
- "name": "gamma",
369
- "arg": "gammaT",
370
- "semantic": "gamma",
371
- "buffer": { "type": "read-only-storage" },
372
- "elementType": "$scalar",
373
- "length": "$HIDDEN_LEN"
374
- },
375
- {
376
- "name": "beta",
377
- "arg": "betaT",
378
- "semantic": "beta",
379
- "buffer": { "type": "read-only-storage" },
380
- "elementType": "$scalar",
381
- "length": "$HIDDEN_LEN"
382
- },
383
- {
384
- "name": "output",
385
- "arg": "outputT",
386
- "semantic": "output",
387
- "buffer": { "type": "storage" },
388
- "elementType": "$scalar"
389
- },
390
- {
391
- "name": "params",
392
- "semantic": "kernel.params",
393
- "buffer": { "type": "uniform" },
394
- "struct": {
395
- "name": "Params",
396
- "fields": [
397
- { "name": "rows", "type": "u32", "value": "rowCount" },
398
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
399
- ]
400
- }
401
- }
402
- ],
403
- "scalar_no_beta_output_only": [
404
- {
405
- "name": "input",
406
- "arg": "inputT",
407
- "semantic": "input",
408
- "buffer": { "type": "read-only-storage" },
409
- "elementType": "$scalar"
410
- },
411
- {
412
- "name": "skip",
413
- "arg": "skipT",
414
- "semantic": "skip",
415
- "buffer": { "type": "read-only-storage" },
416
- "elementType": "$scalar"
417
- },
418
- {
419
- "name": "gamma",
420
- "arg": "gammaT",
421
- "semantic": "gamma",
422
- "buffer": { "type": "read-only-storage" },
423
- "elementType": "$scalar",
424
- "length": "$HIDDEN_LEN"
425
- },
426
- {
427
- "name": "output",
428
- "arg": "outputT",
429
- "semantic": "output",
430
- "buffer": { "type": "storage" },
431
- "elementType": "$scalar"
432
- },
433
- {
434
- "name": "params",
435
- "semantic": "kernel.params",
436
- "buffer": { "type": "uniform" },
437
- "struct": {
438
- "name": "Params",
439
- "fields": [
440
- { "name": "rows", "type": "u32", "value": "rowCount" },
441
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
442
- ]
443
- }
444
- }
445
- ],
446
- "vec4_no_bias_residual": [
447
- {
448
- "name": "input",
449
- "arg": "inputT",
450
- "semantic": "input",
451
- "buffer": { "type": "read-only-storage" },
452
- "elementType": "$vectorScalar"
453
- },
454
- {
455
- "name": "skip",
456
- "arg": "skipT",
457
- "semantic": "skip",
458
- "buffer": { "type": "read-only-storage" },
459
- "elementType": "$vectorScalar"
460
- },
461
- {
462
- "name": "gamma",
463
- "arg": "gammaT",
464
- "semantic": "gamma",
465
- "buffer": { "type": "read-only-storage" },
466
- "elementType": "$vectorScalar",
467
- "length": "$HIDDEN_LEN"
468
- },
469
- {
470
- "name": "beta",
471
- "arg": "betaT",
472
- "semantic": "beta",
473
- "buffer": { "type": "read-only-storage" },
474
- "elementType": "$vectorScalar",
475
- "length": "$HIDDEN_LEN"
476
- },
477
- {
478
- "name": "output",
479
- "arg": "outputT",
480
- "semantic": "output",
481
- "buffer": { "type": "storage" },
482
- "elementType": "$vectorScalar"
483
- },
484
- {
485
- "name": "input_skip_bias_sum",
486
- "arg": "residualT",
487
- "semantic": "input_skip_bias_sum",
488
- "buffer": { "type": "storage" },
489
- "elementType": "$vectorScalar"
490
- },
491
- {
492
- "name": "params",
493
- "semantic": "kernel.params",
494
- "buffer": { "type": "uniform" },
495
- "struct": {
496
- "name": "Params",
497
- "fields": [
498
- { "name": "rows", "type": "u32", "value": "rowCount" },
499
- {
500
- "name": "rowStride",
501
- "type": "u32",
502
- "value": "max(1, min(rowCount, device.limits.maxComputeWorkgroupsPerDimension))"
503
- },
504
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
505
- ]
506
- }
507
- }
508
- ],
509
- "vec4_no_bias_output_only": [
510
- {
511
- "name": "input",
512
- "arg": "inputT",
513
- "semantic": "input",
514
- "buffer": { "type": "read-only-storage" },
515
- "elementType": "$vectorScalar"
516
- },
517
- {
518
- "name": "skip",
519
- "arg": "skipT",
520
- "semantic": "skip",
521
- "buffer": { "type": "read-only-storage" },
522
- "elementType": "$vectorScalar"
523
- },
524
- {
525
- "name": "gamma",
526
- "arg": "gammaT",
527
- "semantic": "gamma",
528
- "buffer": { "type": "read-only-storage" },
529
- "elementType": "$vectorScalar",
530
- "length": "$HIDDEN_LEN"
531
- },
532
- {
533
- "name": "beta",
534
- "arg": "betaT",
535
- "semantic": "beta",
536
- "buffer": { "type": "read-only-storage" },
537
- "elementType": "$vectorScalar",
538
- "length": "$HIDDEN_LEN"
539
- },
540
- {
541
- "name": "output",
542
- "arg": "outputT",
543
- "semantic": "output",
544
- "buffer": { "type": "storage" },
545
- "elementType": "$vectorScalar"
546
- },
547
- {
548
- "name": "params",
549
- "semantic": "kernel.params",
550
- "buffer": { "type": "uniform" },
551
- "struct": {
552
- "name": "Params",
553
- "fields": [
554
- { "name": "rows", "type": "u32", "value": "rowCount" },
555
- {
556
- "name": "rowStride",
557
- "type": "u32",
558
- "value": "max(1, min(rowCount, device.limits.maxComputeWorkgroupsPerDimension))"
559
- },
560
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
561
- ]
562
- }
563
- }
564
- ],
565
- "vec4_bias_output_only": [
566
- {
567
- "name": "input",
568
- "arg": "inputT",
569
- "semantic": "input",
570
- "buffer": { "type": "read-only-storage" },
571
- "elementType": "$vectorScalar"
572
- },
573
- {
574
- "name": "skip",
575
- "arg": "skipT",
576
- "semantic": "skip",
577
- "buffer": { "type": "read-only-storage" },
578
- "elementType": "$vectorScalar"
579
- },
580
- {
581
- "name": "gamma",
582
- "arg": "gammaT",
583
- "semantic": "gamma",
584
- "buffer": { "type": "read-only-storage" },
585
- "elementType": "$vectorScalar",
586
- "length": "$HIDDEN_LEN"
587
- },
588
- {
589
- "name": "beta",
590
- "arg": "betaT",
591
- "semantic": "beta",
592
- "buffer": { "type": "read-only-storage" },
593
- "elementType": "$vectorScalar",
594
- "length": "$HIDDEN_LEN"
595
- },
596
- {
597
- "name": "bias",
598
- "arg": "biasT",
599
- "semantic": "bias",
600
- "buffer": { "type": "read-only-storage" },
601
- "elementType": "$vectorScalar",
602
- "length": "$HIDDEN_LEN"
603
- },
604
- {
605
- "name": "output",
606
- "arg": "outputT",
607
- "semantic": "output",
608
- "buffer": { "type": "storage" },
609
- "elementType": "$vectorScalar"
610
- },
611
- {
612
- "name": "params",
613
- "semantic": "kernel.params",
614
- "buffer": { "type": "uniform" },
615
- "struct": {
616
- "name": "Params",
617
- "fields": [
618
- { "name": "rows", "type": "u32", "value": "rowCount" },
619
- {
620
- "name": "rowStride",
621
- "type": "u32",
622
- "value": "max(1, min(rowCount, device.limits.maxComputeWorkgroupsPerDimension))"
623
- },
624
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
625
- ]
626
- }
627
- }
628
- ],
629
- "vec4_no_beta_output_only": [
630
- {
631
- "name": "input",
632
- "arg": "inputT",
633
- "semantic": "input",
634
- "buffer": { "type": "read-only-storage" },
635
- "elementType": "$vectorScalar"
636
- },
637
- {
638
- "name": "skip",
639
- "arg": "skipT",
640
- "semantic": "skip",
641
- "buffer": { "type": "read-only-storage" },
642
- "elementType": "$vectorScalar"
643
- },
644
- {
645
- "name": "gamma",
646
- "arg": "gammaT",
647
- "semantic": "gamma",
648
- "buffer": { "type": "read-only-storage" },
649
- "elementType": "$vectorScalar",
650
- "length": "$HIDDEN_LEN"
651
- },
652
- {
653
- "name": "output",
654
- "arg": "outputT",
655
- "semantic": "output",
656
- "buffer": { "type": "storage" },
657
- "elementType": "$vectorScalar"
658
- },
659
- {
660
- "name": "params",
661
- "semantic": "kernel.params",
662
- "buffer": { "type": "uniform" },
663
- "struct": {
664
- "name": "Params",
665
- "fields": [
666
- { "name": "rows", "type": "u32", "value": "rowCount" },
667
- {
668
- "name": "rowStride",
669
- "type": "u32",
670
- "value": "max(1, min(rowCount, device.limits.maxComputeWorkgroupsPerDimension))"
671
- },
672
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
673
- ]
674
- }
675
- }
676
- ],
677
- "vec4_beta_broadcast_output_only": [
678
- {
679
- "name": "input",
680
- "arg": "inputT",
681
- "semantic": "input",
682
- "buffer": { "type": "read-only-storage" },
683
- "elementType": "$vectorScalar"
684
- },
685
- {
686
- "name": "skip",
687
- "arg": "skipT",
688
- "semantic": "skip",
689
- "buffer": { "type": "read-only-storage" },
690
- "elementType": "$vectorScalar"
691
- },
692
- {
693
- "name": "gamma",
694
- "arg": "gammaT",
695
- "semantic": "gamma",
696
- "buffer": { "type": "read-only-storage" },
697
- "elementType": "$vectorScalar",
698
- "length": "$HIDDEN_LEN"
699
- },
700
- {
701
- "name": "beta",
702
- "arg": "betaT",
703
- "semantic": "beta",
704
- "buffer": { "type": "read-only-storage" },
705
- "elementType": "$vectorScalar",
706
- "length": "$HIDDEN_LEN"
707
- },
708
- {
709
- "name": "output",
710
- "arg": "outputT",
711
- "semantic": "output",
712
- "buffer": { "type": "storage" },
713
- "elementType": "$vectorScalar"
714
- },
715
- {
716
- "name": "params",
717
- "semantic": "kernel.params",
718
- "buffer": { "type": "uniform" },
719
- "struct": {
720
- "name": "Params",
721
- "fields": [
722
- { "name": "rows", "type": "u32", "value": "dim(shapes.inputT, 0) * dim(shapes.inputT, 1)" },
723
- {
724
- "name": "rowStride",
725
- "type": "u32",
726
- "value": "max(1, min(broadcastRows, device.limits.maxComputeWorkgroupsPerDimension))"
727
- },
728
- { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" },
729
- { "name": "skipRows", "type": "u32", "value": "numel(shapes.skipT) / broadcastHiddenSize" }
730
- ]
731
- }
732
- }
733
- ]
734
  },
735
  "variants": [
736
  {
737
  "id": "beta_output_only_vec4_broadcast",
738
  "priority": 19,
739
  "when": ["broadcastOutputOnlyContract", "broadcastResourcesFit", "broadcastDispatchFits"],
740
- "constants": { "scalar": "\"f32\"", "vectorScalar": "\"vec4<f32>\"", "HIDDEN_LEN": "broadcastHiddenSize / 4" },
741
  "passes": [
742
  {
743
  "id": "main",
744
  "name": "SkipLayerNormalization.BroadcastSkip",
745
- "source": {
746
- "shader": "norm-skip-row-vec4.wgsl.jinja",
747
- "inputs": {
748
- "simplified": false,
749
- "hasBias": false,
750
- "hasBeta": true,
751
- "writeResidualSum": false,
752
- "usesF16": false,
753
- "broadcastSkip": true,
754
- "hidden": "broadcastHiddenSize",
755
- "hiddenVec": "broadcastHiddenSize / 4",
756
- "wg": "broadcastSkipWgVec4",
757
- "vecType": "\"vec4<f32>\"",
758
- "useSubgroups": "hasSubgroups"
759
- }
760
  },
761
- "subgroupCollectivesWidth": "portable",
762
- "bindings": "vec4_beta_broadcast_output_only",
763
- "dispatch": { "workgroups": "broadcastRows" }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
764
  }
765
  ]
766
  },
@@ -768,11 +173,10 @@
768
  "id": "beta_bias_vec4",
769
  "priority": 15,
770
  "when": ["f32_beta_bias_residual_contract", "vec4Aligned", "hasSubgroups or \"bias\" == \"bias\" or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
771
- "constants": {
772
  "scalar": "\"f32\"",
773
  "vectorScalar": "\"vec4<f32>\"",
774
  "hasBias": "\"bias\" == \"bias\"",
775
- "hiddenSize": "hiddenSize",
776
  "workgroupSize": "skipWg",
777
  "HIDDEN_LEN": "hiddenSize / 4"
778
  },
@@ -780,24 +184,22 @@
780
  {
781
  "id": "normalize",
782
  "name": "SkipLayerNormalization.Vec4.Normalize",
783
- "source": {
784
- "shader": "norm-skip-row-vec4.wgsl.jinja",
785
- "inputs": {
786
- "simplified": false,
787
- "hasBias": "\"bias\" == \"bias\"",
788
- "hasBeta": true,
789
- "writeResidualSum": true,
790
- "usesF16": false,
791
- "hidden": "hiddenSize",
792
- "hiddenVec": "hiddenSize / 4",
793
- "wg": "skipWgVec4",
794
- "vecType": "\"vec4<f32>\"",
795
- "useSubgroups": "hasSubgroups"
796
- }
797
  },
798
- "subgroupCollectivesWidth": "portable",
799
- "bindings": "vec4_bias_output_residual",
800
- "dispatch": { "workgroups": "rowCount" }
801
  }
802
  ]
803
  },
@@ -805,14 +207,13 @@
805
  "id": "beta_bias_row",
806
  "priority": 5,
807
  "when": ["f32_beta_bias_residual_contract", "normResourcesFit", "rowDispatchFits"],
808
- "constants": {
809
  "simplified": false,
810
  "useSubgroups": "hasSubgroups",
811
  "hasBeta": true,
812
  "writeResidualSum": true,
813
  "hasBias": "\"bias\" == \"bias\"",
814
  "scalar": "\"f32\"",
815
- "hiddenSize": "hiddenSize",
816
  "workgroupSize": "skipWg",
817
  "HIDDEN_LEN": "hiddenSize"
818
  },
@@ -821,10 +222,10 @@
821
  "id": "normalize",
822
  "name": "SkipLayerNormalization.Row.Normalize",
823
  "shader": "norm-skip-row.wgsl.jinja",
824
- "subgroupCollectivesWidth": "portable",
825
- "bindings": "scalar_bias_output_residual",
826
- "dispatch": { "workgroups": "rowCount" },
827
- "constants": { "writeResidualSum": true }
828
  }
829
  ]
830
  },
@@ -832,29 +233,27 @@
832
  "id": "beta_bias_vec4_f16",
833
  "priority": 21,
834
  "when": ["f16_beta_bias_residual_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
835
- "constants": { "scalar": "\"f16\"", "vectorScalar": "\"vec4<f16>\"", "HIDDEN_LEN": "hiddenSize / 4" },
836
  "passes": [
837
  {
838
  "id": "main",
839
  "name": "SkipLayerNormalization.Vec4",
840
- "source": {
841
- "shader": "norm-skip-row-vec4.wgsl.jinja",
842
- "inputs": {
843
- "simplified": false,
844
- "hasBias": true,
845
- "hasBeta": true,
846
- "writeResidualSum": true,
847
- "usesF16": true,
848
- "hidden": "hiddenSize",
849
- "hiddenVec": "hiddenSize / 4",
850
- "wg": "skipWgVec4",
851
- "vecType": "\"vec4<f16>\"",
852
- "useSubgroups": "hasSubgroups"
853
- }
854
  },
855
- "subgroupCollectivesWidth": "portable",
856
- "bindings": "vec4_bias_output_residual",
857
- "dispatch": { "workgroups": "rowCount" }
858
  }
859
  ]
860
  },
@@ -862,29 +261,27 @@
862
  "id": "no_beta_output_only_vec4",
863
  "priority": 20,
864
  "when": ["f32_no_beta_output_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
865
- "constants": { "scalar": "\"f32\"", "vectorScalar": "\"vec4<f32>\"", "HIDDEN_LEN": "hiddenSize / 4" },
866
  "passes": [
867
  {
868
  "id": "main",
869
  "name": "SkipLayerNormalization.NoBetaOutputOnly.Vec4",
870
- "source": {
871
- "shader": "norm-skip-row-vec4.wgsl.jinja",
872
- "inputs": {
873
- "simplified": false,
874
- "hasBias": false,
875
- "hasBeta": false,
876
- "writeResidualSum": false,
877
- "usesF16": false,
878
- "hidden": "hiddenSize",
879
- "hiddenVec": "hiddenSize / 4",
880
- "wg": "skipWgVec4",
881
- "vecType": "\"vec4<f32>\"",
882
- "useSubgroups": "hasSubgroups"
883
- }
884
  },
885
- "subgroupCollectivesWidth": "portable",
886
- "bindings": "vec4_no_beta_output_only",
887
- "dispatch": { "workgroups": "rowCount" }
888
  }
889
  ]
890
  },
@@ -892,14 +289,13 @@
892
  "id": "no_beta_output_only_row",
893
  "priority": 10,
894
  "when": ["f32_no_beta_output_contract", "normResourcesFit", "rowDispatchFits"],
895
- "constants": {
896
  "simplified": false,
897
  "hasBias": false,
898
  "hasBeta": false,
899
  "writeResidualSum": false,
900
  "useSubgroups": "hasSubgroups",
901
  "scalar": "\"f32\"",
902
- "hiddenSize": "hiddenSize",
903
  "workgroupSize": "skipWg",
904
  "HIDDEN_LEN": "hiddenSize"
905
  },
@@ -908,9 +304,63 @@
908
  "id": "main",
909
  "name": "SkipLayerNormalization.NoBetaOutputOnly.Row",
910
  "shader": "norm-skip-row.wgsl.jinja",
911
- "subgroupCollectivesWidth": "portable",
912
- "bindings": "scalar_no_beta_output_only",
913
- "dispatch": { "workgroups": "rowCount" }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
914
  }
915
  ]
916
  },
@@ -918,11 +368,10 @@
918
  "id": "beta_no_bias_vec4",
919
  "priority": 20,
920
  "when": ["f32_beta_no_bias_residual_contract", "vec4Aligned", "hasSubgroups or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
921
- "constants": {
922
  "scalar": "\"f32\"",
923
  "vectorScalar": "\"vec4<f32>\"",
924
  "hasBias": "\"no_bias\" == \"bias\"",
925
- "hiddenSize": "hiddenSize",
926
  "workgroupSize": "skipWg",
927
  "HIDDEN_LEN": "hiddenSize / 4"
928
  },
@@ -930,24 +379,22 @@
930
  {
931
  "id": "main",
932
  "name": "SkipLayerNormalization.Vec4",
933
- "source": {
934
- "shader": "norm-skip-row-vec4.wgsl.jinja",
935
- "inputs": {
936
- "simplified": false,
937
- "hasBias": "\"no_bias\" == \"bias\"",
938
- "hasBeta": true,
939
- "writeResidualSum": true,
940
- "usesF16": false,
941
- "hidden": "hiddenSize",
942
- "hiddenVec": "hiddenSize / 4",
943
- "wg": "skipWgVec4",
944
- "vecType": "\"vec4<f32>\"",
945
- "useSubgroups": "hasSubgroups"
946
- }
947
  },
948
- "subgroupCollectivesWidth": "portable",
949
- "bindings": "vec4_no_bias_residual",
950
- "dispatch": { "workgroups": "rowCount" }
951
  }
952
  ]
953
  },
@@ -955,14 +402,13 @@
955
  "id": "beta_no_bias_row",
956
  "priority": 10,
957
  "when": ["f32_beta_no_bias_residual_contract", "normResourcesFit", "rowDispatchFits"],
958
- "constants": {
959
  "simplified": false,
960
  "useSubgroups": "hasSubgroups",
961
  "hasBeta": true,
962
  "writeResidualSum": true,
963
  "hasBias": "\"no_bias\" == \"bias\"",
964
  "scalar": "\"f32\"",
965
- "hiddenSize": "hiddenSize",
966
  "workgroupSize": "skipWg",
967
  "HIDDEN_LEN": "hiddenSize"
968
  },
@@ -971,9 +417,9 @@
971
  "id": "main",
972
  "name": "SkipLayerNormalization.Row",
973
  "shader": "norm-skip-row.wgsl.jinja",
974
- "subgroupCollectivesWidth": "portable",
975
- "bindings": "scalar_no_bias_residual",
976
- "dispatch": { "workgroups": "rowCount" }
977
  }
978
  ]
979
  },
@@ -981,11 +427,10 @@
981
  "id": "beta_no_bias_output_only_vec4",
982
  "priority": 20,
983
  "when": ["f32_beta_no_bias_output_only_contract", "vec4Aligned", "hasSubgroups or \"no_bias\" == \"bias\" or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
984
- "constants": {
985
  "scalar": "\"f32\"",
986
  "vectorScalar": "\"vec4<f32>\"",
987
  "hasBias": "\"no_bias\" == \"bias\"",
988
- "hiddenSize": "hiddenSize",
989
  "workgroupSize": "skipWg",
990
  "HIDDEN_LEN": "hiddenSize / 4"
991
  },
@@ -993,24 +438,22 @@
993
  {
994
  "id": "main",
995
  "name": "SkipLayerNormalization.Vec4",
996
- "source": {
997
- "shader": "norm-skip-row-vec4.wgsl.jinja",
998
- "inputs": {
999
- "simplified": false,
1000
- "hasBias": "\"no_bias\" == \"bias\"",
1001
- "hasBeta": true,
1002
- "writeResidualSum": false,
1003
- "usesF16": false,
1004
- "hidden": "hiddenSize",
1005
- "hiddenVec": "hiddenSize / 4",
1006
- "wg": "skipWgVec4",
1007
- "vecType": "\"vec4<f32>\"",
1008
- "useSubgroups": "hasSubgroups"
1009
- }
1010
  },
1011
- "subgroupCollectivesWidth": "portable",
1012
- "bindings": "vec4_no_bias_output_only",
1013
- "dispatch": { "workgroups": "rowCount" }
1014
  }
1015
  ]
1016
  },
@@ -1018,14 +461,13 @@
1018
  "id": "beta_no_bias_output_only_row",
1019
  "priority": 10,
1020
  "when": ["f32_beta_no_bias_output_only_contract", "normResourcesFit", "rowDispatchFits"],
1021
- "constants": {
1022
  "simplified": false,
1023
  "useSubgroups": "hasSubgroups",
1024
  "hasBeta": true,
1025
  "writeResidualSum": false,
1026
  "hasBias": "\"no_bias\" == \"bias\"",
1027
  "scalar": "\"f32\"",
1028
- "hiddenSize": "hiddenSize",
1029
  "workgroupSize": "skipWg",
1030
  "HIDDEN_LEN": "hiddenSize"
1031
  },
@@ -1034,9 +476,9 @@
1034
  "id": "main",
1035
  "name": "SkipLayerNormalization.Row",
1036
  "shader": "norm-skip-row.wgsl.jinja",
1037
- "subgroupCollectivesWidth": "portable",
1038
- "bindings": "scalar_no_bias_output_only",
1039
- "dispatch": { "workgroups": "rowCount" }
1040
  }
1041
  ]
1042
  },
@@ -1044,11 +486,10 @@
1044
  "id": "beta_bias_output_only_vec4",
1045
  "priority": 20,
1046
  "when": ["f32_beta_bias_output_only_contract", "vec4Aligned", "hasSubgroups or \"bias\" == \"bias\" or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
1047
- "constants": {
1048
  "scalar": "\"f32\"",
1049
  "vectorScalar": "\"vec4<f32>\"",
1050
  "hasBias": "\"bias\" == \"bias\"",
1051
- "hiddenSize": "hiddenSize",
1052
  "workgroupSize": "skipWg",
1053
  "HIDDEN_LEN": "hiddenSize / 4"
1054
  },
@@ -1056,24 +497,22 @@
1056
  {
1057
  "id": "main",
1058
  "name": "SkipLayerNormalization.Vec4",
1059
- "source": {
1060
- "shader": "norm-skip-row-vec4.wgsl.jinja",
1061
- "inputs": {
1062
- "simplified": false,
1063
- "hasBias": "\"bias\" == \"bias\"",
1064
- "hasBeta": true,
1065
- "writeResidualSum": false,
1066
- "usesF16": false,
1067
- "hidden": "hiddenSize",
1068
- "hiddenVec": "hiddenSize / 4",
1069
- "wg": "skipWgVec4",
1070
- "vecType": "\"vec4<f32>\"",
1071
- "useSubgroups": "hasSubgroups"
1072
- }
1073
  },
1074
- "subgroupCollectivesWidth": "portable",
1075
- "bindings": "vec4_bias_output_only",
1076
- "dispatch": { "workgroups": "rowCount" }
1077
  }
1078
  ]
1079
  },
@@ -1081,14 +520,13 @@
1081
  "id": "beta_bias_output_only_row",
1082
  "priority": 10,
1083
  "when": ["f32_beta_bias_output_only_contract", "normResourcesFit", "rowDispatchFits"],
1084
- "constants": {
1085
  "simplified": false,
1086
  "useSubgroups": "hasSubgroups",
1087
  "hasBeta": true,
1088
  "writeResidualSum": false,
1089
  "hasBias": "\"bias\" == \"bias\"",
1090
  "scalar": "\"f32\"",
1091
- "hiddenSize": "hiddenSize",
1092
  "workgroupSize": "skipWg",
1093
  "HIDDEN_LEN": "hiddenSize"
1094
  },
@@ -1097,12 +535,131 @@
1097
  "id": "main",
1098
  "name": "SkipLayerNormalization.Row",
1099
  "shader": "norm-skip-row.wgsl.jinja",
1100
- "subgroupCollectivesWidth": "portable",
1101
- "bindings": "scalar_bias_output_only",
1102
- "dispatch": { "workgroups": "rowCount" }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1103
  }
1104
  ]
1105
  }
1106
- ],
1107
- "tunables": { "MAX_WORKGROUP_SIZE": 256 }
1108
  }
 
2
  "domain": "com.microsoft",
3
  "name": "SkipLayerNormalization",
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
+ "betaT": { "onnx": "beta", "dtype": "T", "rank": 1, "optional": true },
10
+ "biasT": { "onnx": "bias", "dtype": "T", "rank": 1, "optional": true }
11
+ },
12
+ "outputs": {
13
+ "outputT": { "onnx": "output", "dtype": "T", "rank": "ranks.inputT", "shape": "shapes.inputT" },
14
+ "residualT": {
15
+ "onnx": "input_skip_bias_sum",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  "dtype": "T",
17
  "rank": "ranks.inputT",
18
  "optional": true,
19
+ "shape": "shapes.inputT"
 
20
  }
 
 
 
 
 
 
 
 
 
 
 
21
  },
22
+ "attributes": { "epsilon": { "default": 9.999999960041972e-13 } },
23
  "typeConstraints": { "T": ["float32", "float16"] },
24
+ "tunables": { "MAX_WORKGROUP_SIZE": { "default": 256 } },
25
  "derive": {
26
+ "rowCount": "numel(shapes.inputT) / max(1, dim(shapes.inputT, -1))",
27
+ "hiddenSize": "dim(shapes.inputT, -1)",
28
  "skipWg": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(hiddenSize)))",
29
  "skipWgVec4": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(ceilDiv(hiddenSize, 4))))",
30
  "portableWideExecution": "not has(device.adapterInfo, \"subgroupMinSize\") or device.adapterInfo.subgroupMinSize >= 32",
31
  "broadcastRows": "dim(shapes.inputT, 0) * dim(shapes.inputT, 1)",
32
  "broadcastHiddenSize": "dim(shapes.inputT, 2)",
33
  "broadcastSkipWgVec4": "max(1, min(tunables.MAX_WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, pow2ceil(ceilDiv(broadcastHiddenSize, 4))))",
34
+ "rowDispatchFits": "rowCount <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535) * min(device.limits.maxComputeWorkgroupsPerDimension, 65535)",
35
+ "broadcastDispatchFits": "broadcastRows <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535) * min(device.limits.maxComputeWorkgroupsPerDimension, 65535)",
36
  "normResourcesFit": "skipWg * 8 <= device.limits.maxComputeWorkgroupStorageSize and skipWgVec4 * 8 <= device.limits.maxComputeWorkgroupStorageSize",
37
  "broadcastResourcesFit": "broadcastSkipWgVec4 * 8 <= device.limits.maxComputeWorkgroupStorageSize",
38
  "epsilonOk": "attrs.epsilon >= 0",
39
+ "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)",
40
+ "residualOutputContract": "present.residualT and sameShape(shapes.residualT, shapes.inputT)",
41
  "outputOnlyContract": "not present.residualT",
42
+ "betaContract": "false if not present.betaT else (ranks.betaT == 1 and dim(shapes.betaT, 0) == dim(shapes.inputT, -1))",
43
  "noBetaContract": "not present.betaT",
44
  "f32MainDtypes": "tensorDtypes.inputT == \"float32\" and tensorDtypes.skipT == \"float32\" and tensorDtypes.gammaT == \"float32\" and tensorDtypes.outputT == \"float32\"",
45
  "f16MainDtypes": "tensorDtypes.inputT == \"float16\" and tensorDtypes.skipT == \"float16\" and tensorDtypes.gammaT == \"float16\" and tensorDtypes.outputT == \"float16\"",
46
  "f32ResidualDtypes": "f32MainDtypes and tensorDtypes.residualT == \"float32\" if present.residualT else false",
47
  "f16ResidualDtypes": "f16MainDtypes and tensorDtypes.residualT == \"float16\" if present.residualT else false",
48
+ "vec4Aligned": "dim(shapes.inputT, -1) % 4 == 0",
49
  "broadcastSkipShapeOk": "(ranks.skipT == 2 and dim(shapes.skipT, 0) == dim(shapes.inputT, 1) and dim(shapes.skipT, 1) == dim(shapes.inputT, 2)) or (ranks.skipT == 3 and ((dim(shapes.skipT, 0) == 1 and dim(shapes.skipT, 1) == dim(shapes.inputT, 1) and dim(shapes.skipT, 2) == dim(shapes.inputT, 2)) or sameShape(shapes.skipT, shapes.inputT)))",
50
  "broadcastOutputOnlyContract": "false if ranks.inputT != 3 or not present.betaT else (epsilonOk and not present.biasT and not present.residualT and dim(shapes.inputT, 2) % 4 == 0 and broadcastSkipShapeOk and ranks.gammaT == 1 and ranks.betaT == 1 and ranks.outputT == 3 and tensorDtypes.inputT == \"float32\" and tensorDtypes.skipT == \"float32\" and tensorDtypes.gammaT == \"float32\" and tensorDtypes.betaT == \"float32\" and tensorDtypes.outputT == \"float32\" and dim(shapes.inputT, 2) > 0 and dim(shapes.gammaT, 0) == dim(shapes.inputT, 2) and dim(shapes.betaT, 0) == dim(shapes.inputT, 2) and sameShape(shapes.outputT, shapes.inputT))",
51
  "hasSubgroups": "device.features.has(\"subgroups\") and device.wgslLanguageFeatures.has(\"subgroup_id\")",
52
  "hasF16": "device.features.has(\"shader-f16\")",
53
+ "f32_beta_no_bias_residual_contract": "coreContract and residualOutputContract and betaContract and f32ResidualDtypes and not present.biasT and tensorDtypes.betaT == \"float32\"",
54
+ "f32_beta_bias_residual_contract": "false if not present.biasT else (coreContract and residualOutputContract and betaContract and f32ResidualDtypes and ranks.biasT == 1 and tensorDtypes.betaT == \"float32\" and tensorDtypes.biasT == \"float32\" and dim(shapes.biasT, 0) == hiddenSize)",
55
+ "f16_beta_bias_residual_contract": "false if not present.biasT else (hasF16 and coreContract and residualOutputContract and betaContract and f16ResidualDtypes and ranks.biasT == 1 and tensorDtypes.betaT == \"float16\" and tensorDtypes.biasT == \"float16\" and dim(shapes.biasT, 0) == hiddenSize)",
56
+ "f32_no_beta_output_contract": "coreContract and outputOnlyContract and noBetaContract and f32MainDtypes and not present.biasT",
57
+ "f32_beta_no_bias_output_only_contract": "coreContract and outputOnlyContract and betaContract and f32MainDtypes and not present.biasT and tensorDtypes.betaT == \"float32\"",
58
+ "f32_beta_bias_output_only_contract": "false if not present.biasT else (coreContract and outputOnlyContract and betaContract and f32MainDtypes and ranks.biasT == 1 and tensorDtypes.betaT == \"float32\" and tensorDtypes.biasT == \"float32\" and dim(shapes.biasT, 0) == hiddenSize)",
59
+ "f16_no_beta_output_contract": "hasF16 and coreContract and outputOnlyContract and noBetaContract and f16MainDtypes and not present.biasT",
60
+ "f16_beta_no_bias_output_only_contract": "hasF16 and coreContract and outputOnlyContract and betaContract and f16MainDtypes and not present.biasT and tensorDtypes.betaT == \"float16\"",
61
+ "f16_beta_bias_output_only_contract": "false if not present.biasT else (hasF16 and coreContract and outputOnlyContract and betaContract and f16MainDtypes and ranks.biasT == 1 and tensorDtypes.betaT == \"float16\" and tensorDtypes.biasT == \"float16\" and dim(shapes.biasT, 0) == hiddenSize)"
62
  },
63
+ "bindings": {
64
+ "input": { "arg": "inputT", "buffer": "read-only-storage", "elementType": "$vectorScalar" },
65
+ "skip": { "arg": "skipT", "buffer": "read-only-storage", "elementType": "$vectorScalar" },
66
+ "gamma": { "arg": "gammaT", "buffer": "read-only-storage", "elementType": "$vectorScalar", "length": "$HIDDEN_LEN" },
67
+ "beta": { "arg": "betaT", "buffer": "read-only-storage", "elementType": "$vectorScalar", "length": "$HIDDEN_LEN" },
68
+ "output": { "arg": "outputT", "buffer": "storage", "elementType": "$vectorScalar" },
69
+ "bias": { "arg": "biasT", "buffer": "read-only-storage", "elementType": "$vectorScalar", "length": "$HIDDEN_LEN" },
70
+ "input_skip_bias_sum": { "arg": "residualT", "buffer": "storage", "elementType": "$vectorScalar" },
71
+ "params_2": {
72
+ "name": "params",
73
+ "buffer": "uniform",
74
+ "struct": [
75
+ { "name": "rows", "type": "u32", "value": "rowCount" },
76
+ {
77
+ "name": "rowStride",
78
+ "type": "u32",
79
+ "value": "max(1, min(rowCount, min(device.limits.maxComputeWorkgroupsPerDimension, 65535)))"
80
+ },
81
+ { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
82
+ ]
83
+ },
84
+ "input_2": { "arg": "inputT", "name": "input", "buffer": "read-only-storage", "elementType": "$scalar" },
85
+ "skip_2": { "arg": "skipT", "name": "skip", "buffer": "read-only-storage", "elementType": "$scalar" },
86
+ "bias_2": {
87
+ "arg": "biasT",
88
+ "name": "bias",
89
+ "buffer": "read-only-storage",
90
+ "elementType": "$scalar",
91
+ "length": "$HIDDEN_LEN"
92
+ },
93
+ "gamma_2": {
94
+ "arg": "gammaT",
95
+ "name": "gamma",
96
+ "buffer": "read-only-storage",
97
+ "elementType": "$scalar",
98
+ "length": "$HIDDEN_LEN"
99
+ },
100
+ "beta_2": {
101
+ "arg": "betaT",
102
+ "name": "beta",
103
+ "buffer": "read-only-storage",
104
+ "elementType": "$scalar",
105
+ "length": "$HIDDEN_LEN"
106
+ },
107
+ "output_2": { "arg": "outputT", "name": "output", "buffer": "storage", "elementType": "$scalar" },
108
+ "input_skip_bias_sum_2": {
109
+ "arg": "residualT",
110
+ "name": "input_skip_bias_sum",
111
+ "buffer": "storage",
112
+ "elementType": "$scalar"
113
+ },
114
+ "params_3": {
115
+ "name": "params",
116
+ "buffer": "uniform",
117
+ "struct": [
118
+ { "name": "rows", "type": "u32", "value": "rowCount" },
119
+ { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" }
120
+ ]
121
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  },
123
  "variants": [
124
  {
125
  "id": "beta_output_only_vec4_broadcast",
126
  "priority": 19,
127
  "when": ["broadcastOutputOnlyContract", "broadcastResourcesFit", "broadcastDispatchFits"],
128
+ "derive": { "scalar": "\"f32\"", "vectorScalar": "\"vec4<f32>\"", "HIDDEN_LEN": "broadcastHiddenSize / 4" },
129
  "passes": [
130
  {
131
  "id": "main",
132
  "name": "SkipLayerNormalization.BroadcastSkip",
133
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
134
+ "derive": {
135
+ "simplified": false,
136
+ "hasBias": false,
137
+ "hasBeta": true,
138
+ "writeResidualSum": false,
139
+ "usesF16Spec": false,
140
+ "broadcastSkip": true,
141
+ "hidden": "broadcastHiddenSize",
142
+ "hiddenVec": "broadcastHiddenSize / 4",
143
+ "wg": "broadcastSkipWgVec4",
144
+ "vecType": "\"vec4<f32>\"",
145
+ "useSubgroups": "hasSubgroups"
 
 
146
  },
147
+ "bindings": [
148
+ "input",
149
+ "skip",
150
+ "gamma",
151
+ "beta",
152
+ "output",
153
+ {
154
+ "name": "params",
155
+ "struct": [
156
+ { "name": "rows", "type": "u32", "value": "dim(shapes.inputT, 0) * dim(shapes.inputT, 1)" },
157
+ {
158
+ "name": "rowStride",
159
+ "type": "u32",
160
+ "value": "max(1, min(broadcastRows, min(device.limits.maxComputeWorkgroupsPerDimension, 65535)))"
161
+ },
162
+ { "name": "epsilon", "type": "f32", "value": "attrs.epsilon" },
163
+ { "name": "skipRows", "type": "u32", "value": "numel(shapes.skipT) / broadcastHiddenSize" }
164
+ ]
165
+ }
166
+ ],
167
+ "dispatch": { "x": "min(broadcastRows, 65535)", "y": "ceilDiv(broadcastRows, 65535)", "z": 1 },
168
+ "subgroupCollectivesWidth": "portable"
169
  }
170
  ]
171
  },
 
173
  "id": "beta_bias_vec4",
174
  "priority": 15,
175
  "when": ["f32_beta_bias_residual_contract", "vec4Aligned", "hasSubgroups or \"bias\" == \"bias\" or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
176
+ "derive": {
177
  "scalar": "\"f32\"",
178
  "vectorScalar": "\"vec4<f32>\"",
179
  "hasBias": "\"bias\" == \"bias\"",
 
180
  "workgroupSize": "skipWg",
181
  "HIDDEN_LEN": "hiddenSize / 4"
182
  },
 
184
  {
185
  "id": "normalize",
186
  "name": "SkipLayerNormalization.Vec4.Normalize",
187
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
188
+ "derive": {
189
+ "simplified": false,
190
+ "hasBias": "\"bias\" == \"bias\"",
191
+ "hasBeta": true,
192
+ "writeResidualSum": true,
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", "bias", "gamma", "beta", "output", "input_skip_bias_sum", "params_2"],
201
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
202
+ "subgroupCollectivesWidth": "portable"
203
  }
204
  ]
205
  },
 
207
  "id": "beta_bias_row",
208
  "priority": 5,
209
  "when": ["f32_beta_bias_residual_contract", "normResourcesFit", "rowDispatchFits"],
210
+ "derive": {
211
  "simplified": false,
212
  "useSubgroups": "hasSubgroups",
213
  "hasBeta": true,
214
  "writeResidualSum": true,
215
  "hasBias": "\"bias\" == \"bias\"",
216
  "scalar": "\"f32\"",
 
217
  "workgroupSize": "skipWg",
218
  "HIDDEN_LEN": "hiddenSize"
219
  },
 
222
  "id": "normalize",
223
  "name": "SkipLayerNormalization.Row.Normalize",
224
  "shader": "norm-skip-row.wgsl.jinja",
225
+ "derive": { "writeResidualSum": true },
226
+ "bindings": ["input_2", "skip_2", "bias_2", "gamma_2", "beta_2", "output_2", "input_skip_bias_sum_2", "params_3"],
227
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
228
+ "subgroupCollectivesWidth": "portable"
229
  }
230
  ]
231
  },
 
233
  "id": "beta_bias_vec4_f16",
234
  "priority": 21,
235
  "when": ["f16_beta_bias_residual_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
236
+ "derive": { "scalar": "\"f16\"", "vectorScalar": "\"vec4<f16>\"", "HIDDEN_LEN": "hiddenSize / 4" },
237
  "passes": [
238
  {
239
  "id": "main",
240
  "name": "SkipLayerNormalization.Vec4",
241
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
242
+ "derive": {
243
+ "simplified": false,
244
+ "hasBias": true,
245
+ "hasBeta": true,
246
+ "writeResidualSum": true,
247
+ "usesF16Spec": true,
248
+ "hidden": "hiddenSize",
249
+ "hiddenVec": "hiddenSize / 4",
250
+ "wg": "skipWgVec4",
251
+ "vecType": "\"vec4<f16>\"",
252
+ "useSubgroups": "hasSubgroups"
 
 
253
  },
254
+ "bindings": ["input", "skip", "bias", "gamma", "beta", "output", "input_skip_bias_sum", "params_2"],
255
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
256
+ "subgroupCollectivesWidth": "portable"
257
  }
258
  ]
259
  },
 
261
  "id": "no_beta_output_only_vec4",
262
  "priority": 20,
263
  "when": ["f32_no_beta_output_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
264
+ "derive": { "scalar": "\"f32\"", "vectorScalar": "\"vec4<f32>\"", "HIDDEN_LEN": "hiddenSize / 4" },
265
  "passes": [
266
  {
267
  "id": "main",
268
  "name": "SkipLayerNormalization.NoBetaOutputOnly.Vec4",
269
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
270
+ "derive": {
271
+ "simplified": false,
272
+ "hasBias": false,
273
+ "hasBeta": false,
274
+ "writeResidualSum": false,
275
+ "usesF16Spec": false,
276
+ "hidden": "hiddenSize",
277
+ "hiddenVec": "hiddenSize / 4",
278
+ "wg": "skipWgVec4",
279
+ "vecType": "\"vec4<f32>\"",
280
+ "useSubgroups": "hasSubgroups"
 
 
281
  },
282
+ "bindings": ["input", "skip", "gamma", "output", "params_2"],
283
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
284
+ "subgroupCollectivesWidth": "portable"
285
  }
286
  ]
287
  },
 
289
  "id": "no_beta_output_only_row",
290
  "priority": 10,
291
  "when": ["f32_no_beta_output_contract", "normResourcesFit", "rowDispatchFits"],
292
+ "derive": {
293
  "simplified": false,
294
  "hasBias": false,
295
  "hasBeta": false,
296
  "writeResidualSum": false,
297
  "useSubgroups": "hasSubgroups",
298
  "scalar": "\"f32\"",
 
299
  "workgroupSize": "skipWg",
300
  "HIDDEN_LEN": "hiddenSize"
301
  },
 
304
  "id": "main",
305
  "name": "SkipLayerNormalization.NoBetaOutputOnly.Row",
306
  "shader": "norm-skip-row.wgsl.jinja",
307
+ "bindings": ["input_2", "skip_2", "gamma_2", "output_2", "params_3"],
308
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
309
+ "subgroupCollectivesWidth": "portable"
310
+ }
311
+ ]
312
+ },
313
+ {
314
+ "id": "no_beta_output_only_vec4_f16",
315
+ "priority": 20,
316
+ "when": ["f16_no_beta_output_contract", "vec4Aligned", "normResourcesFit", "rowDispatchFits"],
317
+ "derive": { "scalar": "\"f16\"", "vectorScalar": "\"vec4<f16>\"", "HIDDEN_LEN": "hiddenSize / 4" },
318
+ "passes": [
319
+ {
320
+ "id": "main",
321
+ "name": "SkipLayerNormalization.NoBetaOutputOnly.Vec4.F16",
322
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
323
+ "derive": {
324
+ "simplified": false,
325
+ "hasBias": false,
326
+ "hasBeta": false,
327
+ "writeResidualSum": false,
328
+ "usesF16Spec": true,
329
+ "hidden": "hiddenSize",
330
+ "hiddenVec": "hiddenSize / 4",
331
+ "wg": "skipWgVec4",
332
+ "vecType": "\"vec4<f16>\"",
333
+ "useSubgroups": "hasSubgroups"
334
+ },
335
+ "bindings": ["input", "skip", "gamma", "output", "params_2"],
336
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
337
+ "subgroupCollectivesWidth": "portable"
338
+ }
339
+ ]
340
+ },
341
+ {
342
+ "id": "no_beta_output_only_row_f16",
343
+ "priority": 10,
344
+ "when": ["f16_no_beta_output_contract", "normResourcesFit", "rowDispatchFits"],
345
+ "derive": {
346
+ "simplified": false,
347
+ "hasBias": false,
348
+ "hasBeta": false,
349
+ "writeResidualSum": false,
350
+ "useSubgroups": "hasSubgroups",
351
+ "scalar": "\"f16\"",
352
+ "usesF16": true,
353
+ "workgroupSize": "skipWg",
354
+ "HIDDEN_LEN": "hiddenSize"
355
+ },
356
+ "passes": [
357
+ {
358
+ "id": "main",
359
+ "name": "SkipLayerNormalization.NoBetaOutputOnly.Row.F16",
360
+ "shader": "norm-skip-row.wgsl.jinja",
361
+ "bindings": ["input_2", "skip_2", "gamma_2", "output_2", "params_3"],
362
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
363
+ "subgroupCollectivesWidth": "portable"
364
  }
365
  ]
366
  },
 
368
  "id": "beta_no_bias_vec4",
369
  "priority": 20,
370
  "when": ["f32_beta_no_bias_residual_contract", "vec4Aligned", "hasSubgroups or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
371
+ "derive": {
372
  "scalar": "\"f32\"",
373
  "vectorScalar": "\"vec4<f32>\"",
374
  "hasBias": "\"no_bias\" == \"bias\"",
 
375
  "workgroupSize": "skipWg",
376
  "HIDDEN_LEN": "hiddenSize / 4"
377
  },
 
379
  {
380
  "id": "main",
381
  "name": "SkipLayerNormalization.Vec4",
382
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
383
+ "derive": {
384
+ "simplified": false,
385
+ "hasBias": "\"no_bias\" == \"bias\"",
386
+ "hasBeta": true,
387
+ "writeResidualSum": true,
388
+ "usesF16Spec": false,
389
+ "hidden": "hiddenSize",
390
+ "hiddenVec": "hiddenSize / 4",
391
+ "wg": "skipWgVec4",
392
+ "vecType": "\"vec4<f32>\"",
393
+ "useSubgroups": "hasSubgroups"
 
 
394
  },
395
+ "bindings": ["input", "skip", "gamma", "beta", "output", "input_skip_bias_sum", "params_2"],
396
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
397
+ "subgroupCollectivesWidth": "portable"
398
  }
399
  ]
400
  },
 
402
  "id": "beta_no_bias_row",
403
  "priority": 10,
404
  "when": ["f32_beta_no_bias_residual_contract", "normResourcesFit", "rowDispatchFits"],
405
+ "derive": {
406
  "simplified": false,
407
  "useSubgroups": "hasSubgroups",
408
  "hasBeta": true,
409
  "writeResidualSum": true,
410
  "hasBias": "\"no_bias\" == \"bias\"",
411
  "scalar": "\"f32\"",
 
412
  "workgroupSize": "skipWg",
413
  "HIDDEN_LEN": "hiddenSize"
414
  },
 
417
  "id": "main",
418
  "name": "SkipLayerNormalization.Row",
419
  "shader": "norm-skip-row.wgsl.jinja",
420
+ "bindings": ["input_2", "skip_2", "gamma_2", "beta_2", "output_2", "input_skip_bias_sum_2", "params_3"],
421
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
422
+ "subgroupCollectivesWidth": "portable"
423
  }
424
  ]
425
  },
 
427
  "id": "beta_no_bias_output_only_vec4",
428
  "priority": 20,
429
  "when": ["f32_beta_no_bias_output_only_contract", "vec4Aligned", "hasSubgroups or \"no_bias\" == \"bias\" or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
430
+ "derive": {
431
  "scalar": "\"f32\"",
432
  "vectorScalar": "\"vec4<f32>\"",
433
  "hasBias": "\"no_bias\" == \"bias\"",
 
434
  "workgroupSize": "skipWg",
435
  "HIDDEN_LEN": "hiddenSize / 4"
436
  },
 
438
  {
439
  "id": "main",
440
  "name": "SkipLayerNormalization.Vec4",
441
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
442
+ "derive": {
443
+ "simplified": false,
444
+ "hasBias": "\"no_bias\" == \"bias\"",
445
+ "hasBeta": true,
446
+ "writeResidualSum": false,
447
+ "usesF16Spec": false,
448
+ "hidden": "hiddenSize",
449
+ "hiddenVec": "hiddenSize / 4",
450
+ "wg": "skipWgVec4",
451
+ "vecType": "\"vec4<f32>\"",
452
+ "useSubgroups": "hasSubgroups"
 
 
453
  },
454
+ "bindings": ["input", "skip", "gamma", "beta", "output", "params_2"],
455
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
456
+ "subgroupCollectivesWidth": "portable"
457
  }
458
  ]
459
  },
 
461
  "id": "beta_no_bias_output_only_row",
462
  "priority": 10,
463
  "when": ["f32_beta_no_bias_output_only_contract", "normResourcesFit", "rowDispatchFits"],
464
+ "derive": {
465
  "simplified": false,
466
  "useSubgroups": "hasSubgroups",
467
  "hasBeta": true,
468
  "writeResidualSum": false,
469
  "hasBias": "\"no_bias\" == \"bias\"",
470
  "scalar": "\"f32\"",
 
471
  "workgroupSize": "skipWg",
472
  "HIDDEN_LEN": "hiddenSize"
473
  },
 
476
  "id": "main",
477
  "name": "SkipLayerNormalization.Row",
478
  "shader": "norm-skip-row.wgsl.jinja",
479
+ "bindings": ["input_2", "skip_2", "gamma_2", "beta_2", "output_2", "params_3"],
480
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
481
+ "subgroupCollectivesWidth": "portable"
482
  }
483
  ]
484
  },
 
486
  "id": "beta_bias_output_only_vec4",
487
  "priority": 20,
488
  "when": ["f32_beta_bias_output_only_contract", "vec4Aligned", "hasSubgroups or \"bias\" == \"bias\" or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
489
+ "derive": {
490
  "scalar": "\"f32\"",
491
  "vectorScalar": "\"vec4<f32>\"",
492
  "hasBias": "\"bias\" == \"bias\"",
 
493
  "workgroupSize": "skipWg",
494
  "HIDDEN_LEN": "hiddenSize / 4"
495
  },
 
497
  {
498
  "id": "main",
499
  "name": "SkipLayerNormalization.Vec4",
500
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
501
+ "derive": {
502
+ "simplified": false,
503
+ "hasBias": "\"bias\" == \"bias\"",
504
+ "hasBeta": true,
505
+ "writeResidualSum": false,
506
+ "usesF16Spec": false,
507
+ "hidden": "hiddenSize",
508
+ "hiddenVec": "hiddenSize / 4",
509
+ "wg": "skipWgVec4",
510
+ "vecType": "\"vec4<f32>\"",
511
+ "useSubgroups": "hasSubgroups"
 
 
512
  },
513
+ "bindings": ["input", "skip", "gamma", "beta", "bias", "output", "params_2"],
514
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
515
+ "subgroupCollectivesWidth": "portable"
516
  }
517
  ]
518
  },
 
520
  "id": "beta_bias_output_only_row",
521
  "priority": 10,
522
  "when": ["f32_beta_bias_output_only_contract", "normResourcesFit", "rowDispatchFits"],
523
+ "derive": {
524
  "simplified": false,
525
  "useSubgroups": "hasSubgroups",
526
  "hasBeta": true,
527
  "writeResidualSum": false,
528
  "hasBias": "\"bias\" == \"bias\"",
529
  "scalar": "\"f32\"",
 
530
  "workgroupSize": "skipWg",
531
  "HIDDEN_LEN": "hiddenSize"
532
  },
 
535
  "id": "main",
536
  "name": "SkipLayerNormalization.Row",
537
  "shader": "norm-skip-row.wgsl.jinja",
538
+ "bindings": ["input_2", "skip_2", "bias_2", "gamma_2", "beta_2", "output_2", "params_3"],
539
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
540
+ "subgroupCollectivesWidth": "portable"
541
+ }
542
+ ]
543
+ },
544
+ {
545
+ "id": "beta_no_bias_output_only_vec4_f16",
546
+ "priority": 20,
547
+ "when": ["f16_beta_no_bias_output_only_contract", "vec4Aligned", "hasSubgroups or \"no_bias\" == \"bias\" or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
548
+ "derive": {
549
+ "scalar": "\"f16\"",
550
+ "vectorScalar": "\"vec4<f16>\"",
551
+ "hasBias": "\"no_bias\" == \"bias\"",
552
+ "workgroupSize": "skipWg",
553
+ "HIDDEN_LEN": "hiddenSize / 4"
554
+ },
555
+ "passes": [
556
+ {
557
+ "id": "main",
558
+ "name": "SkipLayerNormalization.Vec4.F16",
559
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
560
+ "derive": {
561
+ "simplified": false,
562
+ "hasBias": "\"no_bias\" == \"bias\"",
563
+ "hasBeta": true,
564
+ "writeResidualSum": false,
565
+ "usesF16Spec": true,
566
+ "hidden": "hiddenSize",
567
+ "hiddenVec": "hiddenSize / 4",
568
+ "wg": "skipWgVec4",
569
+ "vecType": "\"vec4<f16>\"",
570
+ "useSubgroups": "hasSubgroups"
571
+ },
572
+ "bindings": ["input", "skip", "gamma", "beta", "output", "params_2"],
573
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
574
+ "subgroupCollectivesWidth": "portable"
575
+ }
576
+ ]
577
+ },
578
+ {
579
+ "id": "beta_no_bias_output_only_row_f16",
580
+ "priority": 10,
581
+ "when": ["f16_beta_no_bias_output_only_contract", "normResourcesFit", "rowDispatchFits"],
582
+ "derive": {
583
+ "simplified": false,
584
+ "useSubgroups": "hasSubgroups",
585
+ "hasBeta": true,
586
+ "writeResidualSum": false,
587
+ "hasBias": "\"no_bias\" == \"bias\"",
588
+ "scalar": "\"f16\"",
589
+ "usesF16": true,
590
+ "workgroupSize": "skipWg",
591
+ "HIDDEN_LEN": "hiddenSize"
592
+ },
593
+ "passes": [
594
+ {
595
+ "id": "main",
596
+ "name": "SkipLayerNormalization.Row.F16",
597
+ "shader": "norm-skip-row.wgsl.jinja",
598
+ "bindings": ["input_2", "skip_2", "gamma_2", "beta_2", "output_2", "params_3"],
599
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
600
+ "subgroupCollectivesWidth": "portable"
601
+ }
602
+ ]
603
+ },
604
+ {
605
+ "id": "beta_bias_output_only_vec4_f16",
606
+ "priority": 20,
607
+ "when": ["f16_beta_bias_output_only_contract", "vec4Aligned", "hasSubgroups or \"bias\" == \"bias\" or portableWideExecution", "normResourcesFit", "rowDispatchFits"],
608
+ "derive": {
609
+ "scalar": "\"f16\"",
610
+ "vectorScalar": "\"vec4<f16>\"",
611
+ "hasBias": "\"bias\" == \"bias\"",
612
+ "workgroupSize": "skipWg",
613
+ "HIDDEN_LEN": "hiddenSize / 4"
614
+ },
615
+ "passes": [
616
+ {
617
+ "id": "main",
618
+ "name": "SkipLayerNormalization.Vec4.F16",
619
+ "shader": "norm-skip-row-vec4.wgsl.jinja",
620
+ "derive": {
621
+ "simplified": false,
622
+ "hasBias": "\"bias\" == \"bias\"",
623
+ "hasBeta": true,
624
+ "writeResidualSum": false,
625
+ "usesF16Spec": true,
626
+ "hidden": "hiddenSize",
627
+ "hiddenVec": "hiddenSize / 4",
628
+ "wg": "skipWgVec4",
629
+ "vecType": "\"vec4<f16>\"",
630
+ "useSubgroups": "hasSubgroups"
631
+ },
632
+ "bindings": ["input", "skip", "gamma", "beta", "bias", "output", "params_2"],
633
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
634
+ "subgroupCollectivesWidth": "portable"
635
+ }
636
+ ]
637
+ },
638
+ {
639
+ "id": "beta_bias_output_only_row_f16",
640
+ "priority": 10,
641
+ "when": ["f16_beta_bias_output_only_contract", "normResourcesFit", "rowDispatchFits"],
642
+ "derive": {
643
+ "simplified": false,
644
+ "useSubgroups": "hasSubgroups",
645
+ "hasBeta": true,
646
+ "writeResidualSum": false,
647
+ "hasBias": "\"bias\" == \"bias\"",
648
+ "scalar": "\"f16\"",
649
+ "usesF16": true,
650
+ "workgroupSize": "skipWg",
651
+ "HIDDEN_LEN": "hiddenSize"
652
+ },
653
+ "passes": [
654
+ {
655
+ "id": "main",
656
+ "name": "SkipLayerNormalization.Row.F16",
657
+ "shader": "norm-skip-row.wgsl.jinja",
658
+ "bindings": ["input_2", "skip_2", "bias_2", "gamma_2", "beta_2", "output_2", "params_3"],
659
+ "dispatch": { "x": "min(rowCount, 65535)", "y": "ceilDiv(rowCount, 65535)", "z": 1 },
660
+ "subgroupCollectivesWidth": "portable"
661
  }
662
  ]
663
  }
664
+ ]
 
665
  }
build/webgpu/metadata.json CHANGED
@@ -1,19 +1,41 @@
1
  {
2
  "name": "com.microsoft.SkipLayerNormalization",
3
- "id": "_com_microsoft_skiplayernormalization_webgpu_1767bd7",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
- "bench.json": "STz1miuskWFMJijUblWNS3pG/DHJsRwQo0M+up/ng3s=",
11
- "manifest.json": "MM5RYZ3xnC2rbelhnBH9kdS+qwkWaQmvEVXhBmag8jg=",
12
- "norm-skip-row-vec4.wgsl.jinja": "qHoa8QjoRD1rgxTGGuJpfVb16Jou8PEg2CF1GjDt78s=",
13
- "norm-skip-row.wgsl.jinja": "ck3s/G7WRph2YZRJs4LTft+R0IDjMPeE5Oy4UXDsqQs=",
14
- "test.json": "Dkphsy4eO4Z8f2ZY1wfBJVmLcKNVWcOupJHOighE3RU="
15
  }
16
  },
17
- "provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
18
- "webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/com.microsoft.SkipLayerNormalization" }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
 
1
  {
2
  "name": "com.microsoft.SkipLayerNormalization",
3
+ "id": "_com_microsoft_skiplayernormalization_webgpu_28a934b",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
+ "bench.json": "dZADuGnHvG3kWGPS0BGgmikuwdi16tD/Sk4HbGC9UV0=",
11
+ "manifest.json": "G6ZofqPdSuhkAxEuuKIlW4fQ/fCsDwxEzafKwVqGEY8=",
12
+ "norm-skip-row-vec4.wgsl.jinja": "bH8L9BYJ/3XQXE2zP8kvZc4wlhAbcAolI4/p0xXskzM=",
13
+ "norm-skip-row.wgsl.jinja": "aERQfDDXx6lwKuyahwcemgFllRSq46egf2++7f6bNtA=",
14
+ "test.json": "K+KtXhWTSxbRlFwFfszdd1YKz9JnAOuDZ9ebLg7Y8w0="
15
  }
16
  },
17
+ "provenance": { "kernel": { "sha": "91d990483a174128daf7673f3f37a7c890493ae1", "dirty": false } },
18
+ "webgpu": {
19
+ "manifestSpec": "2.0",
20
+ "variants": {
21
+ "beta_output_only_vec4_broadcast": ["norm-skip-row-vec4.wgsl.jinja"],
22
+ "beta_bias_vec4": ["norm-skip-row-vec4.wgsl.jinja"],
23
+ "beta_bias_row": ["norm-skip-row.wgsl.jinja"],
24
+ "beta_bias_vec4_f16": ["norm-skip-row-vec4.wgsl.jinja"],
25
+ "no_beta_output_only_vec4": ["norm-skip-row-vec4.wgsl.jinja"],
26
+ "no_beta_output_only_row": ["norm-skip-row.wgsl.jinja"],
27
+ "no_beta_output_only_vec4_f16": ["norm-skip-row-vec4.wgsl.jinja"],
28
+ "no_beta_output_only_row_f16": ["norm-skip-row.wgsl.jinja"],
29
+ "beta_no_bias_vec4": ["norm-skip-row-vec4.wgsl.jinja"],
30
+ "beta_no_bias_row": ["norm-skip-row.wgsl.jinja"],
31
+ "beta_no_bias_output_only_vec4": ["norm-skip-row-vec4.wgsl.jinja"],
32
+ "beta_no_bias_output_only_row": ["norm-skip-row.wgsl.jinja"],
33
+ "beta_bias_output_only_vec4": ["norm-skip-row-vec4.wgsl.jinja"],
34
+ "beta_bias_output_only_row": ["norm-skip-row.wgsl.jinja"],
35
+ "beta_no_bias_output_only_vec4_f16": ["norm-skip-row-vec4.wgsl.jinja"],
36
+ "beta_no_bias_output_only_row_f16": ["norm-skip-row.wgsl.jinja"],
37
+ "beta_bias_output_only_vec4_f16": ["norm-skip-row-vec4.wgsl.jinja"],
38
+ "beta_bias_output_only_row_f16": ["norm-skip-row.wgsl.jinja"]
39
+ }
40
+ }
41
  }
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<vec2<f32>, WG>;
59
 
@@ -84,9 +85,9 @@ fn reduce_pair(value: vec2<f32>{% if useSubgroups %}, sg_lane: u32, sg_id: u32,
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,7 +107,7 @@ fn main(
106
  }
107
  let tid = lid.x;
108
  let base = row * HIDDEN_V;
109
- {% if source.broadcastSkip %}
110
  // skip broadcasts across the batch dim: fold row into [0, skipRows) so every
111
  // batch reuses the same skip row (skipRows == params.rows ⇒ identity).
112
  let skip_base = (row % params.skipRows) * HIDDEN_V;
@@ -114,11 +115,11 @@ fn main(
114
  let skip_base = base;
115
  {% endif %}
116
 
117
- let shift = residual_value(base, skip_base{% if source.hasBias %}, 0u{% endif %}).x;
118
 
119
  var acc = vec2<f32>(0.0, 0.0);
120
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
121
- let v = residual_value(base + i, skip_base + i{% if source.hasBias %}, i{% endif %});
122
  let d = v - vec4<f32>(shift);
123
  acc.x = acc.x + d.x + d.y + d.z + d.w;
124
  acc.y = acc.y + dot(d, d);
@@ -132,14 +133,14 @@ fn main(
132
 
133
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
134
  let idx = base + i;
135
- let residual = residual_value(idx, skip_base + i{% if source.hasBias %}, i{% endif %});
136
- {% if source.writeResidualSum %}
137
- input_skip_bias_sum[idx] = {{ source.vecType }}(residual);
138
  {% endif %}
139
  var value = (residual - vec4<f32>(row_mean)) * row_inv * vec4<f32>(gamma[i]);
140
- {% if source.hasBeta %}
141
  value = value + vec4<f32>(beta[i]);
142
  {% endif %}
143
- output[idx] = {{ source.vecType }}(value);
144
  }
145
  }
 
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<vec2<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;
 
115
  let skip_base = base;
116
  {% endif %}
117
 
118
+ let shift = residual_value(base, skip_base{% if hasBias %}, 0u{% endif %}).x;
119
 
120
  var acc = vec2<f32>(0.0, 0.0);
121
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
122
+ let v = residual_value(base + i, skip_base + i{% if hasBias %}, i{% endif %});
123
  let d = v - vec4<f32>(shift);
124
  acc.x = acc.x + d.x + d.y + d.z + d.w;
125
  acc.y = acc.y + dot(d, d);
 
133
 
134
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
135
  let idx = base + i;
136
+ let residual = residual_value(idx, skip_base + i{% if hasBias %}, i{% endif %});
137
+ {% if writeResidualSum %}
138
+ input_skip_bias_sum[idx] = {{ vecType }}(residual);
139
  {% endif %}
140
  var value = (residual - vec4<f32>(row_mean)) * row_inv * vec4<f32>(gamma[i]);
141
+ {% if hasBeta %}
142
  value = value + vec4<f32>(beta[i]);
143
  {% endif %}
144
+ output[idx] = {{ vecType }}(value);
145
  }
146
  }
build/webgpu/norm-skip-row.wgsl.jinja CHANGED
@@ -47,6 +47,9 @@
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 useSubgroups and not degenerateRow %}
51
  enable subgroups;
52
  {% endif %}
@@ -56,46 +59,6 @@ enable subgroups;
56
  const HIDDEN: u32 = {{ hiddenSize }}u;
57
  {% endif %}
58
  const WG: u32 = {{ workgroupSize }}u;
59
- {% if simplified %}
60
-
61
- var<workgroup> partial: array<f32, WG>;
62
- {% macro wgsl_tree_reduce_f32(name, mode, buffer="partial", wg="WG", trailingBarrier=true) %}
63
- fn {{ name }}(value: f32, tid: u32) -> f32 {
64
- {{ buffer }}[tid] = value;
65
- workgroupBarrier();
66
- // Ceil-halving keeps every lane when the workgroup size is not a power of
67
- // two. For even n this matches the power-of-two tree order; for odd n, lanes
68
- // [0, n-half) fold the upper tail while the middle lane carries forward.
69
- var n: u32 = {{ wg }};
70
- loop {
71
- let half = (n + 1u) / 2u;
72
- if (tid < n - half) {
73
- {% if mode == "max" %}
74
- {{ buffer }}[tid] = max({{ buffer }}[tid], {{ buffer }}[tid + half]);
75
- {% else %}
76
- {{ buffer }}[tid] = {{ buffer }}[tid] + {{ buffer }}[tid + half];
77
- {% endif %}
78
- }
79
- workgroupBarrier();
80
- n = half;
81
- if (n == 1u) {
82
- break;
83
- }
84
- }
85
- // The default trailing barrier makes this helper safe for back-to-back calls: every lane reads
86
- // slot 0 here, so the next call's first store must not run until all lanes have read it.
87
- // `trailingBarrier=false` is safe only when the buffer is never written again before kernel exit.
88
- let reduced = {{ buffer }}[0];
89
- {% if trailingBarrier %}
90
- workgroupBarrier();
91
- {% endif %}
92
- return reduced;
93
- }
94
- {% endmacro %}
95
-
96
- {{ wgsl_tree_reduce_f32("reduce_sum", "add", "partial", "WG") }}
97
- var<workgroup> row_inv: f32;
98
- {% else %}
99
  {% if not degenerateRow %}
100
 
101
  var<workgroup> pair_partial: array<vec2<f32>, WG>;
@@ -125,7 +88,6 @@ fn reduce_pair(value: vec2<f32>, tid: u32) -> vec2<f32> {
125
  }
126
  {% endif %}
127
  {% endif %}
128
- {% endif %}
129
 
130
  {% if not degenerateRow or writeResidualSum %}
131
  fn residual_value(row: u32, d: u32) -> f32 {
@@ -140,47 +102,23 @@ fn residual_value(row: u32, d: u32) -> f32 {
140
 
141
  @compute @workgroup_size(WG, 1, 1)
142
  fn main(
143
- @builtin(workgroup_id) wg: vec3<u32>,
144
- @builtin(num_workgroups) nwg: vec3<u32>{% if not degenerateRow %},
145
  @builtin(local_invocation_id) lid: vec3<u32>{% endif %}{% if useSubgroups and not degenerateRow %},
146
  @builtin(subgroup_invocation_id) sg_lane: u32,
147
  @builtin(subgroup_id) sg_id: u32,
148
  @builtin(num_subgroups) num_sg: u32{% endif %}
149
  ) {
150
- // 2D-folded row index: wg.y carries the high bits past the maxComputeWorkgroupsPerDimension
151
- // workgroup-per-dimension dispatch limit. Reduces to wg.x when nwg.y == 1;
152
  // the row >= params.rows guard drops the over-dispatched tail.
153
- let row = wg.x + wg.y * nwg.x;
154
  if (row >= params.rows) {
155
  return;
156
  }
157
  {% if not degenerateRow %}
158
  let tid = lid.x;
159
  {% endif %}
160
- {% if simplified %}
161
-
162
- // RMS normalization uses one sum-of-squares sweep, without a mean or beta.
163
-
164
- var local_sq = 0.0;
165
- for (var d: u32 = tid; d < HIDDEN; d = d + WG) {
166
- let value = residual_value(row, d);
167
- local_sq = local_sq + value * value;
168
- }
169
- let sq = reduce_sum(local_sq, tid);
170
- if (tid == 0u) {
171
- row_inv = inverseSqrt(sq / f32(HIDDEN) + params.epsilon);
172
- }
173
- workgroupBarrier();
174
-
175
- for (var d: u32 = tid; d < HIDDEN; d = d + WG) {
176
- let index = row * HIDDEN + d;
177
- let residual = residual_value(row, d);
178
- {% if writeResidualSum %}
179
- input_skip_bias_sum[index] = {{ scalar }}(residual);
180
- {% endif %}
181
- output[index] = {{ scalar }}(residual * row_inv * f32(gamma[d]));
182
- }
183
- {% elif degenerateRow %}
184
 
185
  // HIDDEN == 1: the row's mean is its only element, so the centered value and
186
  // the variance are exactly zero and the output reduces to beta. The closed
 
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 %}
 
59
  const HIDDEN: u32 = {{ hiddenSize }}u;
60
  {% endif %}
61
  const WG: u32 = {{ workgroupSize }}u;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  {% if not degenerateRow %}
63
 
64
  var<workgroup> pair_partial: array<vec2<f32>, WG>;
 
88
  }
89
  {% endif %}
90
  {% endif %}
 
91
 
92
  {% if not degenerateRow or writeResidualSum %}
93
  fn residual_value(row: u32, d: u32) -> f32 {
 
102
 
103
  @compute @workgroup_size(WG, 1, 1)
104
  fn main(
105
+ @builtin(workgroup_id) wg: vec3<u32>{% if not degenerateRow %},
 
106
  @builtin(local_invocation_id) lid: vec3<u32>{% endif %}{% if useSubgroups and not degenerateRow %},
107
  @builtin(subgroup_invocation_id) sg_lane: u32,
108
  @builtin(subgroup_id) sg_id: u32,
109
  @builtin(num_subgroups) num_sg: u32{% endif %}
110
  ) {
111
+ // 2D-folded row index: wg.y carries the high bits past the per-axis dispatch fold width.
112
+ // Reduces to wg.x when the dispatch does not fold;
113
  // the row >= params.rows guard drops the over-dispatched tail.
114
+ let row = wg.x + wg.y * {{ DISPATCH_FOLD_WIDTH }}u;
115
  if (row >= params.rows) {
116
  return;
117
  }
118
  {% if not degenerateRow %}
119
  let tid = lid.x;
120
  {% endif %}
121
+ {% if degenerateRow %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  // HIDDEN == 1: the row's mean is its only element, so the centered value and
124
  // the variance are exactly zero and the output reduces to beta. The closed
build/webgpu/test.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "com.microsoft.SkipLayerNormalization",
3
  "fixtureArrays": {
4
  "ort_batch2_bias_flattened_tokens_input_skipT": [0.1, -0.2, 0.3, 1, 0.5, 0.1, 0.4, 1.6, 1.8, -0.3, 0, 1, -0.5, 0.4, 0.8, -0.6],
5
  "ort_batch2_flattened_tokens_input_inputT": [0.8, -0.5, 0, 1, 0.5, 0.2, 0.3, -0.6, 0.8, -0.5, 0, 1, 0.5, 0.2, 0.3, -0.6],
@@ -189,7 +188,7 @@
189
  {
190
  "name": "hidden_size_one_bias_rows65535_dispatch_edge",
191
  "provenance": {
192
- "notes": "Correctness sibling for the low-occupancy hidden=1 benchmark at rows=65535, the maximum single-dimension workgroup count edge."
193
  },
194
  "attrs": { "epsilon": 0.00001 },
195
  "inputs": {
@@ -224,7 +223,7 @@
224
  "skipT": {
225
  "dtype": "float32",
226
  "shape": [1, 4],
227
- "data": { "kind": "values", "values": [-39999.0, -40000.0, -40001.0, -40002.0] }
228
  },
229
  "gammaT": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [1.0, 2.0, -1.0, 0.5] } },
230
  "betaT": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.0, 0.5, -0.25, 1.0] } }
@@ -258,7 +257,7 @@
258
  "provenance": {
259
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
260
  "test": "SkipLayerNormTest.SkipLayerNormBatch1",
261
- "notes": "ORT shape [1, 2, 4] is represented as [2, 4] tokens by this lowered kernel. Epsilon is omitted to exercise the schema default of 1e-12."
262
  },
263
  "inputs": {
264
  "inputT": {
@@ -284,7 +283,7 @@
284
  "provenance": {
285
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
286
  "test": "SkipLayerNormTest.SkipLayerNormBatch2_Bias",
287
- "notes": "ORT shape [2, 2, 4] is represented as [4, 4] tokens by this lowered kernel."
288
  },
289
  "attrs": { "epsilon": 1e-12 },
290
  "inputs": {
@@ -318,7 +317,7 @@
318
  "provenance": {
319
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
320
  "test": "SkipLayerNormTest.SkipLayerNormBatch2",
321
- "notes": "ORT shape [2, 2, 4] is represented as [4, 4] tokens by this lowered kernel."
322
  },
323
  "attrs": { "epsilon": 1e-12 },
324
  "inputs": {
@@ -477,7 +476,7 @@
477
  {
478
  "name": "no_beta_output_only_hidden6_unaligned_row",
479
  "provenance": {
480
- "notes": "Only coverage for the scalar no_beta_output_only_row variant: beta omitted with output as the sole output picks the no-beta output-only pair, and hidden=6 is not a multiple of 4, so the vec4 sibling's vec4Aligned guard is false and the row kernel is selected on every tier."
481
  },
482
  "attrs": { "epsilon": 0.00001 },
483
  "inputs": {
@@ -532,7 +531,7 @@
532
  {
533
  "name": "beta_no_bias_output_only_hidden6_unaligned_row",
534
  "provenance": {
535
- "notes": "Row-kernel arm of beta_no_bias_output_only: hidden=6 fails vec4Aligned, so the scalar sibling is selected on every tier."
536
  },
537
  "attrs": { "epsilon": 0.00001 },
538
  "inputs": {
@@ -701,7 +700,7 @@
701
  {
702
  "name": "f32_hidden768_no_bias_residual",
703
  "provenance": {
704
- "notes": "Compact companion for bench cases skip-layernorm-f32-4096x768 and skip-layernorm-f32-4096x768-hidden768-aligned-sibling, where reduced tiers expose a subgroup fallback gap."
705
  },
706
  "attrs": { "epsilon": 0.00001 },
707
  "inputs": {
@@ -769,7 +768,7 @@
769
  {
770
  "name": "f32_hidden1025_bias_residual",
771
  "provenance": {
772
- "notes": "Compact companion for bench case skip-layernorm-f32-bias-8192x1025-unaligned-twopass-fallback, preserving the odd hidden-size bias path."
773
  },
774
  "attrs": { "epsilon": 0.00001 },
775
  "inputs": {
@@ -911,9 +910,7 @@
911
  },
912
  {
913
  "name": "hidden_size_one_bias_many_rows",
914
- "provenance": {
915
- "notes": "Compact correctness sibling for the hidden-size-one low-occupancy benchmark; many rows with hidden=1 keep the variance-zero bias path honest without using benchmark-scale dimensions."
916
- },
917
  "attrs": { "epsilon": 0.00001 },
918
  "inputs": {
919
  "inputT": {
@@ -934,6 +931,247 @@
934
  "outputT": { "dtype": "float32", "shape": [257, 1], "tolerance": 0.000001 },
935
  "residualT": { "dtype": "float32", "shape": [257, 1], "tolerance": 0.000001 }
936
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
937
  }
938
  ]
939
  }
 
1
  {
 
2
  "fixtureArrays": {
3
  "ort_batch2_bias_flattened_tokens_input_skipT": [0.1, -0.2, 0.3, 1, 0.5, 0.1, 0.4, 1.6, 1.8, -0.3, 0, 1, -0.5, 0.4, 0.8, -0.6],
4
  "ort_batch2_flattened_tokens_input_inputT": [0.8, -0.5, 0, 1, 0.5, 0.2, 0.3, -0.6, 0.8, -0.5, 0, 1, 0.5, 0.2, 0.3, -0.6],
 
188
  {
189
  "name": "hidden_size_one_bias_rows65535_dispatch_edge",
190
  "provenance": {
191
+ "notes": "Hidden size 1 across 65,535 rows exercises the maximum single-dimension workgroup count with one value per normalization row."
192
  },
193
  "attrs": { "epsilon": 0.00001 },
194
  "inputs": {
 
223
  "skipT": {
224
  "dtype": "float32",
225
  "shape": [1, 4],
226
+ "data": { "kind": "values", "values": [-39999.0, -39999.5, -40000.0, -40000.5] }
227
  },
228
  "gammaT": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [1.0, 2.0, -1.0, 0.5] } },
229
  "betaT": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.0, 0.5, -0.25, 1.0] } }
 
257
  "provenance": {
258
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
259
  "test": "SkipLayerNormTest.SkipLayerNormBatch1",
260
+ "notes": "This package flattens ORT shape [1, 2, 4] to two four-wide token rows. Epsilon is omitted to exercise the schema default of 1e-12."
261
  },
262
  "inputs": {
263
  "inputT": {
 
283
  "provenance": {
284
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
285
  "test": "SkipLayerNormTest.SkipLayerNormBatch2_Bias",
286
+ "notes": "This package flattens ORT shape [2, 2, 4] to four four-wide token rows."
287
  },
288
  "attrs": { "epsilon": 1e-12 },
289
  "inputs": {
 
317
  "provenance": {
318
  "source": "onnxruntime/test/contrib_ops/skiplayernorm_op_test.cc",
319
  "test": "SkipLayerNormTest.SkipLayerNormBatch2",
320
+ "notes": "This package flattens ORT shape [2, 2, 4] to four four-wide token rows."
321
  },
322
  "attrs": { "epsilon": 1e-12 },
323
  "inputs": {
 
476
  {
477
  "name": "no_beta_output_only_hidden6_unaligned_row",
478
  "provenance": {
479
+ "notes": "Beta and optional outputs are omitted, and hidden size 6 is not divisible by four, selecting the scalar no-beta output-only row path on every tier."
480
  },
481
  "attrs": { "epsilon": 0.00001 },
482
  "inputs": {
 
531
  {
532
  "name": "beta_no_bias_output_only_hidden6_unaligned_row",
533
  "provenance": {
534
+ "notes": "Beta is present, bias and optional outputs are omitted, and hidden size 6 selects the scalar output-only row path on every tier."
535
  },
536
  "attrs": { "epsilon": 0.00001 },
537
  "inputs": {
 
700
  {
701
  "name": "f32_hidden768_no_bias_residual",
702
  "provenance": {
703
+ "notes": "A compact hidden-size-768 residual normalization exercises the subgroup route and its reduced-tier fallback without bias."
704
  },
705
  "attrs": { "epsilon": 0.00001 },
706
  "inputs": {
 
768
  {
769
  "name": "f32_hidden1025_bias_residual",
770
  "provenance": {
771
+ "notes": "A compact hidden-size-1025 normalization exercises the unaligned two-pass path with bias and residual output."
772
  },
773
  "attrs": { "epsilon": 0.00001 },
774
  "inputs": {
 
910
  },
911
  {
912
  "name": "hidden_size_one_bias_many_rows",
913
+ "provenance": { "notes": "Many hidden-size-one rows exercise the variance-zero bias path at a compact scale." },
 
 
914
  "attrs": { "epsilon": 0.00001 },
915
  "inputs": {
916
  "inputT": {
 
931
  "outputT": { "dtype": "float32", "shape": [257, 1], "tolerance": 0.000001 },
932
  "residualT": { "dtype": "float32", "shape": [257, 1], "tolerance": 0.000001 }
933
  }
934
+ },
935
+ {
936
+ "name": "rank3_no_bias_residual",
937
+ "provenance": {
938
+ "notes": "Rank-3 activation shape carrying the residual output, the form ONNX Runtime's transformer fusion emits when the pre-normalization sum feeds the next block."
939
+ },
940
+ "attrs": { "epsilon": 0.00001 },
941
+ "inputs": {
942
+ "inputT": {
943
+ "dtype": "float32",
944
+ "shape": [1, 4, 768],
945
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.017, "cosStep": 0.031 }
946
+ },
947
+ "skipT": {
948
+ "dtype": "float32",
949
+ "shape": [1, 4, 768],
950
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.011, "cosStep": 0.023 }
951
+ },
952
+ "gammaT": {
953
+ "dtype": "float32",
954
+ "shape": [768],
955
+ "data": { "kind": "fillFloat32", "scale": 0.1, "offset": 1.0, "sinStep": 0.007, "cosStep": 0.041 }
956
+ },
957
+ "betaT": {
958
+ "dtype": "float32",
959
+ "shape": [768],
960
+ "data": { "kind": "fillFloat32", "scale": 0.1, "sinStep": 0.019, "cosStep": 0.013 }
961
+ }
962
+ },
963
+ "outputs": {
964
+ "outputT": { "dtype": "float32", "shape": [1, 4, 768], "tolerance": 0.0002 },
965
+ "residualT": { "dtype": "float32", "shape": [1, 4, 768], "tolerance": 0.000002 }
966
+ }
967
+ },
968
+ {
969
+ "name": "rank3_beta_no_bias_output_only_hidden6_unaligned_row",
970
+ "provenance": {
971
+ "notes": "Rank-3 at a hidden size that is not a multiple of four, so the scalar row route serves it."
972
+ },
973
+ "attrs": { "epsilon": 0.00001 },
974
+ "inputs": {
975
+ "inputT": {
976
+ "dtype": "float32",
977
+ "shape": [1, 2, 6],
978
+ "data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.37 }
979
+ },
980
+ "skipT": {
981
+ "dtype": "float32",
982
+ "shape": [1, 2, 6],
983
+ "data": { "kind": "fillFloat32", "sinStep": 0.23, "cosStep": 0.43 }
984
+ },
985
+ "gammaT": {
986
+ "dtype": "float32",
987
+ "shape": [6],
988
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.2 }
989
+ },
990
+ "betaT": {
991
+ "dtype": "float32",
992
+ "shape": [6],
993
+ "data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.1 }
994
+ }
995
+ },
996
+ "outputs": { "outputT": { "dtype": "float32", "shape": [1, 2, 6], "tolerance": 0.00002 } }
997
+ },
998
+ {
999
+ "name": "f16_rank3_beta_bias_output_only",
1000
+ "provenance": {
1001
+ "notes": "Half-precision beta and bias at a rank-3 activation shape, the ordinary on-device inference form."
1002
+ },
1003
+ "requires": { "features": ["shader-f16"] },
1004
+ "attrs": { "epsilon": 0.00001 },
1005
+ "inputs": {
1006
+ "inputT": {
1007
+ "dtype": "float16",
1008
+ "shape": [1, 3, 8],
1009
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1010
+ },
1011
+ "skipT": {
1012
+ "dtype": "float16",
1013
+ "shape": [1, 3, 8],
1014
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
1015
+ },
1016
+ "gammaT": {
1017
+ "dtype": "float16",
1018
+ "shape": [8],
1019
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.2 }
1020
+ },
1021
+ "betaT": {
1022
+ "dtype": "float16",
1023
+ "shape": [8],
1024
+ "data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.1 }
1025
+ },
1026
+ "biasT": {
1027
+ "dtype": "float16",
1028
+ "shape": [8],
1029
+ "data": { "kind": "fillFloat32", "sinStep": 0.05, "cosStep": 0.47, "scale": 0.3 }
1030
+ }
1031
+ },
1032
+ "outputs": { "outputT": { "dtype": "float16", "shape": [1, 3, 8], "tolerance": 0.01 } }
1033
+ },
1034
+ {
1035
+ "name": "f16_beta_bias_output_only_hidden6_unaligned_row",
1036
+ "provenance": { "notes": "Half precision at an unaligned hidden size, which the scalar row route serves." },
1037
+ "requires": { "features": ["shader-f16"] },
1038
+ "attrs": { "epsilon": 0.00001 },
1039
+ "inputs": {
1040
+ "inputT": {
1041
+ "dtype": "float16",
1042
+ "shape": [2, 6],
1043
+ "data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.37 }
1044
+ },
1045
+ "skipT": {
1046
+ "dtype": "float16",
1047
+ "shape": [2, 6],
1048
+ "data": { "kind": "fillFloat32", "sinStep": 0.23, "cosStep": 0.43 }
1049
+ },
1050
+ "gammaT": {
1051
+ "dtype": "float16",
1052
+ "shape": [6],
1053
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.2 }
1054
+ },
1055
+ "betaT": {
1056
+ "dtype": "float16",
1057
+ "shape": [6],
1058
+ "data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.1 }
1059
+ },
1060
+ "biasT": {
1061
+ "dtype": "float16",
1062
+ "shape": [6],
1063
+ "data": { "kind": "fillFloat32", "sinStep": 0.05, "cosStep": 0.47, "scale": 0.3 }
1064
+ }
1065
+ },
1066
+ "outputs": { "outputT": { "dtype": "float16", "shape": [2, 6], "tolerance": 0.01 } }
1067
+ },
1068
+ {
1069
+ "name": "f16_beta_no_bias_output_only",
1070
+ "provenance": { "notes": "Half precision with beta and no bias." },
1071
+ "requires": { "features": ["shader-f16"] },
1072
+ "attrs": { "epsilon": 0.00001 },
1073
+ "inputs": {
1074
+ "inputT": {
1075
+ "dtype": "float16",
1076
+ "shape": [3, 8],
1077
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1078
+ },
1079
+ "skipT": {
1080
+ "dtype": "float16",
1081
+ "shape": [3, 8],
1082
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
1083
+ },
1084
+ "gammaT": {
1085
+ "dtype": "float16",
1086
+ "shape": [8],
1087
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.2 }
1088
+ },
1089
+ "betaT": {
1090
+ "dtype": "float16",
1091
+ "shape": [8],
1092
+ "data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.1 }
1093
+ }
1094
+ },
1095
+ "outputs": { "outputT": { "dtype": "float16", "shape": [3, 8], "tolerance": 0.01 } }
1096
+ },
1097
+ {
1098
+ "name": "f16_beta_no_bias_output_only_hidden6_unaligned_row",
1099
+ "provenance": { "notes": "Half precision with beta, no bias, at an unaligned hidden size." },
1100
+ "requires": { "features": ["shader-f16"] },
1101
+ "attrs": { "epsilon": 0.00001 },
1102
+ "inputs": {
1103
+ "inputT": {
1104
+ "dtype": "float16",
1105
+ "shape": [2, 6],
1106
+ "data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.37 }
1107
+ },
1108
+ "skipT": {
1109
+ "dtype": "float16",
1110
+ "shape": [2, 6],
1111
+ "data": { "kind": "fillFloat32", "sinStep": 0.23, "cosStep": 0.43 }
1112
+ },
1113
+ "gammaT": {
1114
+ "dtype": "float16",
1115
+ "shape": [6],
1116
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.2 }
1117
+ },
1118
+ "betaT": {
1119
+ "dtype": "float16",
1120
+ "shape": [6],
1121
+ "data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.1 }
1122
+ }
1123
+ },
1124
+ "outputs": { "outputT": { "dtype": "float16", "shape": [2, 6], "tolerance": 0.01 } }
1125
+ },
1126
+ {
1127
+ "name": "f16_no_beta_output_only_hidden6_unaligned_row",
1128
+ "provenance": { "notes": "Half precision with neither beta nor bias, at an unaligned hidden size." },
1129
+ "requires": { "features": ["shader-f16"] },
1130
+ "attrs": { "epsilon": 0.00001 },
1131
+ "inputs": {
1132
+ "inputT": {
1133
+ "dtype": "float16",
1134
+ "shape": [2, 6],
1135
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1136
+ },
1137
+ "skipT": {
1138
+ "dtype": "float16",
1139
+ "shape": [2, 6],
1140
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
1141
+ },
1142
+ "gammaT": {
1143
+ "dtype": "float16",
1144
+ "shape": [6],
1145
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.2 }
1146
+ }
1147
+ },
1148
+ "outputs": { "outputT": { "dtype": "float16", "shape": [2, 6], "tolerance": 0.002 } }
1149
+ },
1150
+ {
1151
+ "name": "f16_no_beta_output_only",
1152
+ "provenance": {
1153
+ "notes": "Half precision with neither beta nor bias at an aligned hidden size, which is the vec4 arm of that pair."
1154
+ },
1155
+ "requires": { "features": ["shader-f16"] },
1156
+ "attrs": { "epsilon": 0.00001 },
1157
+ "inputs": {
1158
+ "inputT": {
1159
+ "dtype": "float16",
1160
+ "shape": [3, 8],
1161
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
1162
+ },
1163
+ "skipT": {
1164
+ "dtype": "float16",
1165
+ "shape": [3, 8],
1166
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
1167
+ },
1168
+ "gammaT": {
1169
+ "dtype": "float16",
1170
+ "shape": [8],
1171
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.2 }
1172
+ }
1173
+ },
1174
+ "outputs": { "outputT": { "dtype": "float16", "shape": [3, 8], "tolerance": 0.002 } }
1175
  }
1176
  ]
1177
  }