Xenova HF Staff commited on
Commit
8e0c6a5
·
verified ·
1 Parent(s): 48220c7

sync 91d990483a17

Browse files
README.md CHANGED
@@ -12,21 +12,21 @@ tags:
12
 
13
  ## Description
14
 
15
- Implements ONNX Runtime's legacy RMS normalization for models that serialize `SimplifiedLayerNormalization` in the default ONNX domain: `Y = (X / sqrt(mean(X^2) + epsilon)) * scale`. It shares kernels with [ONNX `RMSNormalization`](https://onnx.ai/onnx/operators/onnx__RMSNormalization.html), but retains scale-before-output-cast ordering and optional `inv_std_var`. See the [compatibility discussion](https://github.com/onnx/onnx/issues/6582#issuecomment-3591862327). Supports float16/float32, float32 statistics, and a nonempty normalization suffix.
16
 
17
  ## Inputs
18
 
19
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
20
  | --- | --- | --- | --- | --- | --- | --- |
21
- | `X` | `x` | `T` | — | — | Input tensor; the mean square is taken over the suffix dimensions starting at `axis`. | required |
22
- | `scale` | `scale` | `V` | — | — | Scale tensor, unidirectionally broadcastable to `X`; output `Y` has this tensor's dtype. | required |
23
 
24
  ## Outputs
25
 
26
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
27
  | --- | --- | --- | --- | --- | --- | --- |
28
- | `Y` | `y` | `V` | same as `X` | same as `X` | Normalized and scaled output; same shape as `X` and same dtype as `scale`. | required |
29
- | `inv_std_var` | `invStdVar` | `U` | same as `X` | derived; see description | Optional inverse RMS statistic `1 / sqrt(mean(X^2) + epsilon)`; same rank as `X`, with the dimensions from `axis` onward set to one. | optional |
30
 
31
  ## Attributes
32
 
@@ -36,8 +36,8 @@ Default values (overridable per request):
36
  | --- | --- | --- |
37
  | `axis` | `-1` | The first dimension of the normalization suffix; negative values count from the end, so the default `-1` normalizes only the last dimension. |
38
  | `epsilon` | `0.00001` | Small constant added to the mean square before taking the square root to avoid division by zero. |
 
39
  | `stash_type` | `1` | TensorProto element type of `inv_std_var`; this package implements the legacy float32 value `1`. |
40
- | `keep_dims` | `1` | Legacy compatibility attribute accepted and ignored by ONNX Runtime. The supported value `1` records the runtime's fixed behavior: optional statistics retain the input rank with normalized dimensions set to one. |
41
 
42
  ## Type constraints
43
 
@@ -49,7 +49,7 @@ Default values (overridable per request):
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
@@ -60,10 +60,14 @@ Default values (overridable per request):
60
 
61
  ## Use with `@huggingface/kernels`
62
 
63
- The loader derives every required output's shape and logical dtype from the manifest contract and this call.
64
- It then allocates the result tensors automatically.
 
 
 
65
 
66
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
 
67
 
68
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
69
 
 
12
 
13
  ## Description
14
 
15
+ Implements ONNX Runtime's legacy RMS normalization for models that serialize `SimplifiedLayerNormalization` in the default ONNX domain: `Y = (X / sqrt(mean(X^2) + epsilon)) * scale`. Its arithmetic corresponds to [ONNX `RMSNormalization`](https://onnx.ai/onnx/operators/onnx__RMSNormalization.html), while retaining scale-before-output-cast ordering and optional `inv_std_var`. See the [compatibility discussion](https://github.com/onnx/onnx/issues/6582#issuecomment-3591862327). Supports float16/float32, float32 statistics, and a nonempty normalization suffix.
16
 
17
  ## Inputs
18
 
19
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
20
  | --- | --- | --- | --- | --- | --- | --- |
21
+ | `x` | `X` | `T` | — | — | Input tensor; the mean square is taken over the suffix dimensions starting at `axis`. | required |
22
+ | `scale` | | `V` | — | — | Scale tensor, unidirectionally broadcastable to `X`; output `Y` has this tensor's dtype. | required |
23
 
24
  ## Outputs
25
 
26
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
27
  | --- | --- | --- | --- | --- | --- | --- |
28
+ | `y` | `Y` | `V` | same as `x` | same as `x` | Normalized and scaled output; same shape as `X` and same dtype as `scale`. | required |
29
+ | `invStdVar` | `inv_std_var` | `U` | same as `x` | derived | Optional inverse RMS statistic `1 / sqrt(mean(X^2) + epsilon)`; same rank as `X`, with the dimensions from `axis` onward set to one. | optional |
30
 
31
  ## Attributes
32
 
 
36
  | --- | --- | --- |
37
  | `axis` | `-1` | The first dimension of the normalization suffix; negative values count from the end, so the default `-1` normalizes only the last dimension. |
38
  | `epsilon` | `0.00001` | Small constant added to the mean square before taking the square root to avoid division by zero. |
39
+ | `keep_dims` | `1` | Legacy compatibility attribute. Only `1` is supported: optional statistics retain the input rank with normalized dimensions set to one. |
40
  | `stash_type` | `1` | TensorProto element type of `inv_std_var`; this package implements the legacy float32 value `1`. |
 
41
 
42
  ## Type constraints
43
 
 
49
 
50
  ## Files
51
 
52
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, 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
 
60
 
61
  ## Use with `@huggingface/kernels`
62
 
63
+ ```sh
64
+ npm install --save-exact @huggingface/kernels@0.0.1-preview.2
65
+ ```
66
+
67
+ Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
68
 
69
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
70
+ It follows the `v1` branch as fixes land. To pin exact artifact bytes, pass a 40-character commit `revision` instead of `version`.
71
 
72
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
73
 
build/webgpu/bench.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "ai.onnx.SimplifiedLayerNormalization",
3
  "cases": [
4
  {
5
  "name": "simplifiedln-f32-4096x4096",
@@ -61,6 +60,474 @@
61
  }
62
  ]
63
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
  ]
66
  }
 
1
  {
 
2
  "cases": [
3
  {
4
  "name": "simplifiedln-f32-4096x4096",
 
60
  }
61
  ]
62
  }
63
+ },
64
+ {
65
+ "name": "split_f32-1x16384",
66
+ "preset": "stress",
67
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
68
+ "tunables": {},
69
+ "inputs": {
70
+ "x": { "shape": [1, 16384], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
71
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
72
+ },
73
+ "outputs": {
74
+ "y": { "shape": [1, 16384], "dtype": "float32" },
75
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
76
+ },
77
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 131080 }] }
78
+ },
79
+ {
80
+ "name": "split_f32-1x16385",
81
+ "preset": "stress",
82
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
83
+ "tunables": {},
84
+ "inputs": {
85
+ "x": { "shape": [1, 16385], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
86
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
87
+ },
88
+ "outputs": {
89
+ "y": { "shape": [1, 16385], "dtype": "float32" },
90
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
91
+ },
92
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 131088 }] }
93
+ },
94
+ {
95
+ "name": "split_f32-1x32769",
96
+ "preset": "stress",
97
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
98
+ "tunables": {},
99
+ "inputs": {
100
+ "x": { "shape": [1, 32769], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
101
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
102
+ },
103
+ "outputs": {
104
+ "y": { "shape": [1, 32769], "dtype": "float32" },
105
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
106
+ },
107
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 262160 }] }
108
+ },
109
+ {
110
+ "name": "split_f32-1x65536",
111
+ "preset": "stress",
112
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
113
+ "tunables": {},
114
+ "inputs": {
115
+ "x": { "shape": [1, 65536], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
116
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
117
+ },
118
+ "outputs": {
119
+ "y": { "shape": [1, 65536], "dtype": "float32" },
120
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
121
+ },
122
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 524296 }] }
123
+ },
124
+ {
125
+ "name": "split_f32-1x131072",
126
+ "preset": "stress",
127
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
128
+ "tunables": {},
129
+ "inputs": {
130
+ "x": { "shape": [1, 131072], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
131
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
132
+ },
133
+ "outputs": {
134
+ "y": { "shape": [1, 131072], "dtype": "float32" },
135
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
136
+ },
137
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 1048584 }] }
138
+ },
139
+ {
140
+ "name": "split_f32-1x262144",
141
+ "preset": "stress",
142
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
143
+ "tunables": {},
144
+ "inputs": {
145
+ "x": { "shape": [1, 262144], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
146
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
147
+ },
148
+ "outputs": {
149
+ "y": { "shape": [1, 262144], "dtype": "float32" },
150
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
151
+ },
152
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 2097160 }] }
153
+ },
154
+ {
155
+ "name": "split_f32-1x524288",
156
+ "preset": "stress",
157
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
158
+ "tunables": {},
159
+ "inputs": {
160
+ "x": { "shape": [1, 524288], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
161
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
162
+ },
163
+ "outputs": {
164
+ "y": { "shape": [1, 524288], "dtype": "float32" },
165
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
166
+ },
167
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 4194312 }] }
168
+ },
169
+ {
170
+ "name": "split_f32-1x1048576",
171
+ "preset": "stress",
172
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
173
+ "tunables": {},
174
+ "inputs": {
175
+ "x": { "shape": [1, 1048576], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
176
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
177
+ },
178
+ "outputs": {
179
+ "y": { "shape": [1, 1048576], "dtype": "float32" },
180
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
181
+ },
182
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 8388616 }] }
183
+ },
184
+ {
185
+ "name": "split_f32-1x2097152",
186
+ "preset": "stress",
187
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
188
+ "tunables": {},
189
+ "inputs": {
190
+ "x": { "shape": [1, 2097152], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
191
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
192
+ },
193
+ "outputs": {
194
+ "y": { "shape": [1, 2097152], "dtype": "float32" },
195
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
196
+ },
197
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 16777224 }] }
198
+ },
199
+ {
200
+ "name": "split_f32-2x131073",
201
+ "preset": "stress",
202
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
203
+ "tunables": {},
204
+ "inputs": {
205
+ "x": { "shape": [2, 131073], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
206
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
207
+ },
208
+ "outputs": {
209
+ "y": { "shape": [2, 131073], "dtype": "float32" },
210
+ "invStdVar": { "shape": [2, 1], "dtype": "float32" }
211
+ },
212
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 2097180 }] }
213
+ },
214
+ {
215
+ "name": "split_f32-3x524289",
216
+ "preset": "stress",
217
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
218
+ "tunables": {},
219
+ "inputs": {
220
+ "x": { "shape": [3, 524289], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
221
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
222
+ },
223
+ "outputs": {
224
+ "y": { "shape": [3, 524289], "dtype": "float32" },
225
+ "invStdVar": { "shape": [3, 1], "dtype": "float32" }
226
+ },
227
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 12582952 }] }
228
+ },
229
+ {
230
+ "name": "split_f32-4x1048576",
231
+ "preset": "stress",
232
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
233
+ "tunables": {},
234
+ "inputs": {
235
+ "x": { "shape": [4, 1048576], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
236
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
237
+ },
238
+ "outputs": {
239
+ "y": { "shape": [4, 1048576], "dtype": "float32" },
240
+ "invStdVar": { "shape": [4, 1], "dtype": "float32" }
241
+ },
242
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 33554452 }] }
243
+ },
244
+ {
245
+ "name": "split_f32-8x16384",
246
+ "preset": "stress",
247
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
248
+ "tunables": {},
249
+ "inputs": {
250
+ "x": { "shape": [8, 16384], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
251
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
252
+ },
253
+ "outputs": {
254
+ "y": { "shape": [8, 16384], "dtype": "float32" },
255
+ "invStdVar": { "shape": [8, 1], "dtype": "float32" }
256
+ },
257
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 1048612 }] }
258
+ },
259
+ {
260
+ "name": "split_f32-16x65536",
261
+ "preset": "stress",
262
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
263
+ "tunables": {},
264
+ "inputs": {
265
+ "x": { "shape": [16, 65536], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
266
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
267
+ },
268
+ "outputs": {
269
+ "y": { "shape": [16, 65536], "dtype": "float32" },
270
+ "invStdVar": { "shape": [16, 1], "dtype": "float32" }
271
+ },
272
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 8388676 }] }
273
+ },
274
+ {
275
+ "name": "split_f32-32x32769",
276
+ "preset": "stress",
277
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
278
+ "tunables": {},
279
+ "inputs": {
280
+ "x": { "shape": [32, 32769], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
281
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
282
+ },
283
+ "outputs": {
284
+ "y": { "shape": [32, 32769], "dtype": "float32" },
285
+ "invStdVar": { "shape": [32, 1], "dtype": "float32" }
286
+ },
287
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 8388996 }] }
288
+ },
289
+ {
290
+ "name": "split_f32-128x16384",
291
+ "preset": "stress",
292
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
293
+ "tunables": {},
294
+ "inputs": {
295
+ "x": { "shape": [128, 16384], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
296
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
297
+ },
298
+ "outputs": {
299
+ "y": { "shape": [128, 16384], "dtype": "float32" },
300
+ "invStdVar": { "shape": [128, 1], "dtype": "float32" }
301
+ },
302
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 16777732 }] }
303
+ },
304
+ {
305
+ "name": "split_f16-1x16385",
306
+ "preset": "stress",
307
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
308
+ "tunables": {},
309
+ "inputs": {
310
+ "x": { "shape": [1, 16385], "dtype": "float16", "dist": "normal", "seed": 8123, "scale": 0.5 },
311
+ "scale": { "shape": [], "dtype": "float16", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
312
+ },
313
+ "outputs": {
314
+ "y": { "shape": [1, 16385], "dtype": "float16" },
315
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
316
+ },
317
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 65546 }] }
318
+ },
319
+ {
320
+ "name": "split_f16-1x131072",
321
+ "preset": "stress",
322
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
323
+ "tunables": {},
324
+ "inputs": {
325
+ "x": { "shape": [1, 131072], "dtype": "float16", "dist": "normal", "seed": 8123, "scale": 0.5 },
326
+ "scale": { "shape": [], "dtype": "float16", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
327
+ },
328
+ "outputs": {
329
+ "y": { "shape": [1, 131072], "dtype": "float16" },
330
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
331
+ },
332
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 524294 }] }
333
+ },
334
+ {
335
+ "name": "split_f16-1x524288",
336
+ "preset": "stress",
337
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
338
+ "tunables": {},
339
+ "inputs": {
340
+ "x": { "shape": [1, 524288], "dtype": "float16", "dist": "normal", "seed": 8123, "scale": 0.5 },
341
+ "scale": { "shape": [], "dtype": "float16", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
342
+ },
343
+ "outputs": {
344
+ "y": { "shape": [1, 524288], "dtype": "float16" },
345
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
346
+ },
347
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 2097158 }] }
348
+ },
349
+ {
350
+ "name": "split_f16-1x2097152",
351
+ "preset": "stress",
352
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
353
+ "tunables": {},
354
+ "inputs": {
355
+ "x": { "shape": [1, 2097152], "dtype": "float16", "dist": "normal", "seed": 8123, "scale": 0.5 },
356
+ "scale": { "shape": [], "dtype": "float16", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
357
+ },
358
+ "outputs": {
359
+ "y": { "shape": [1, 2097152], "dtype": "float16" },
360
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
361
+ },
362
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 8388614 }] }
363
+ },
364
+ {
365
+ "name": "split_f16-3x524289",
366
+ "preset": "stress",
367
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
368
+ "tunables": {},
369
+ "inputs": {
370
+ "x": { "shape": [3, 524289], "dtype": "float16", "dist": "normal", "seed": 8123, "scale": 0.5 },
371
+ "scale": { "shape": [], "dtype": "float16", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
372
+ },
373
+ "outputs": {
374
+ "y": { "shape": [3, 524289], "dtype": "float16" },
375
+ "invStdVar": { "shape": [3, 1], "dtype": "float32" }
376
+ },
377
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 6291482 }] }
378
+ },
379
+ {
380
+ "name": "split_f16-16x65536",
381
+ "preset": "stress",
382
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
383
+ "tunables": {},
384
+ "inputs": {
385
+ "x": { "shape": [16, 65536], "dtype": "float16", "dist": "normal", "seed": 8123, "scale": 0.5 },
386
+ "scale": { "shape": [], "dtype": "float16", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
387
+ },
388
+ "outputs": {
389
+ "y": { "shape": [16, 65536], "dtype": "float16" },
390
+ "invStdVar": { "shape": [16, 1], "dtype": "float32" }
391
+ },
392
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 4194370 }] }
393
+ },
394
+ {
395
+ "name": "split_f32-f16-2x32769",
396
+ "preset": "stress",
397
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
398
+ "tunables": {},
399
+ "inputs": {
400
+ "x": { "shape": [2, 32769], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
401
+ "scale": { "shape": [], "dtype": "float16", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
402
+ },
403
+ "outputs": {
404
+ "y": { "shape": [2, 32769], "dtype": "float16" },
405
+ "invStdVar": { "shape": [2, 1], "dtype": "float32" }
406
+ },
407
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 393238 }] }
408
+ },
409
+ {
410
+ "name": "split_f16-f32-2x32769",
411
+ "preset": "stress",
412
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
413
+ "tunables": {},
414
+ "inputs": {
415
+ "x": { "shape": [2, 32769], "dtype": "float16", "dist": "normal", "seed": 8123, "scale": 0.5 },
416
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
417
+ },
418
+ "outputs": {
419
+ "y": { "shape": [2, 32769], "dtype": "float32" },
420
+ "invStdVar": { "shape": [2, 1], "dtype": "float32" }
421
+ },
422
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 393240 }] }
423
+ },
424
+ {
425
+ "name": "split_f32-1x16384-split1",
426
+ "preset": "stress",
427
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
428
+ "tunables": { "MAX_SPLITS": 1 },
429
+ "inputs": {
430
+ "x": { "shape": [1, 16384], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
431
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
432
+ },
433
+ "outputs": {
434
+ "y": { "shape": [1, 16384], "dtype": "float32" },
435
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
436
+ },
437
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 131080 }] }
438
+ },
439
+ {
440
+ "name": "split_f32-1x16385-split3",
441
+ "preset": "stress",
442
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
443
+ "tunables": { "MAX_SPLITS": 3 },
444
+ "inputs": {
445
+ "x": { "shape": [1, 16385], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
446
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
447
+ },
448
+ "outputs": {
449
+ "y": { "shape": [1, 16385], "dtype": "float32" },
450
+ "invStdVar": { "shape": [1, 1], "dtype": "float32" }
451
+ },
452
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 131088 }] }
453
+ },
454
+ {
455
+ "name": "split_f32-2x262145-wg64",
456
+ "preset": "stress",
457
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
458
+ "tunables": { "WORKGROUP_SIZE": 64 },
459
+ "inputs": {
460
+ "x": { "shape": [2, 262145], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
461
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
462
+ },
463
+ "outputs": {
464
+ "y": { "shape": [2, 262145], "dtype": "float32" },
465
+ "invStdVar": { "shape": [2, 1], "dtype": "float32" }
466
+ },
467
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 4194332 }] }
468
+ },
469
+ {
470
+ "name": "split_f32-2x262145-wg128",
471
+ "preset": "stress",
472
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
473
+ "tunables": { "WORKGROUP_SIZE": 128 },
474
+ "inputs": {
475
+ "x": { "shape": [2, 262145], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
476
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
477
+ },
478
+ "outputs": {
479
+ "y": { "shape": [2, 262145], "dtype": "float32" },
480
+ "invStdVar": { "shape": [2, 1], "dtype": "float32" }
481
+ },
482
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 4194332 }] }
483
+ },
484
+ {
485
+ "name": "split_f32-1x524288-no-stats",
486
+ "preset": "stress",
487
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
488
+ "tunables": {},
489
+ "inputs": {
490
+ "x": { "shape": [1, 524288], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
491
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
492
+ },
493
+ "outputs": { "y": { "shape": [1, 524288], "dtype": "float32" } },
494
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 4194308 }] }
495
+ },
496
+ {
497
+ "name": "split_f32-1x2097152-no-stats",
498
+ "preset": "stress",
499
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
500
+ "tunables": {},
501
+ "inputs": {
502
+ "x": { "shape": [1, 2097152], "dtype": "float32", "dist": "normal", "seed": 8123, "scale": 0.5 },
503
+ "scale": { "shape": [], "dtype": "float32", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
504
+ },
505
+ "outputs": { "y": { "shape": [1, 2097152], "dtype": "float32" } },
506
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 16777220 }] }
507
+ },
508
+ {
509
+ "name": "split_f16-1x524288-no-stats",
510
+ "preset": "stress",
511
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
512
+ "tunables": {},
513
+ "inputs": {
514
+ "x": { "shape": [1, 524288], "dtype": "float16", "dist": "normal", "seed": 8123, "scale": 0.5 },
515
+ "scale": { "shape": [], "dtype": "float16", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
516
+ },
517
+ "outputs": { "y": { "shape": [1, 524288], "dtype": "float16" } },
518
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 2097154 }] }
519
+ },
520
+ {
521
+ "name": "split_f16-1x2097152-no-stats",
522
+ "preset": "stress",
523
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
524
+ "tunables": {},
525
+ "inputs": {
526
+ "x": { "shape": [1, 2097152], "dtype": "float16", "dist": "normal", "seed": 8123, "scale": 0.5 },
527
+ "scale": { "shape": [], "dtype": "float16", "dist": "uniform", "seed": 8124, "scale": 0.25, "offset": 1 }
528
+ },
529
+ "outputs": { "y": { "shape": [1, 2097152], "dtype": "float16" } },
530
+ "bench": { "metrics": [{ "type": "bandwidth", "value": 8388610 }] }
531
  }
532
  ]
533
  }
build/webgpu/manifest.json CHANGED
@@ -3,57 +3,31 @@
3
  "name": "SimplifiedLayerNormalization",
4
  "conformance": "legacy-default-domain",
5
  "sinceVersion": 1,
6
- "description": "Implements ONNX Runtime's legacy RMS normalization for models that serialize `SimplifiedLayerNormalization` in the default ONNX domain: `Y = (X / sqrt(mean(X^2) + epsilon)) * scale`. It shares kernels with [ONNX `RMSNormalization`](https://onnx.ai/onnx/operators/onnx__RMSNormalization.html), but retains scale-before-output-cast ordering and optional `inv_std_var`. See the [compatibility discussion](https://github.com/onnx/onnx/issues/6582#issuecomment-3591862327). Supports float16/float32, float32 statistics, and a nonempty normalization suffix.",
7
- "inputs": [
8
- {
9
- "role": "X",
10
- "dtype": "T",
11
- "description": "Input tensor; the mean square is taken over the suffix dimensions starting at `axis`."
12
- },
13
- {
14
- "role": "scale",
15
- "dtype": "V",
16
- "description": "Scale tensor, unidirectionally broadcastable to `X`; output `Y` has this tensor's dtype."
17
- }
18
- ],
19
- "outputs": [
20
- {
21
- "role": "Y",
22
- "dtype": "V",
23
- "rank": "ranks.X",
24
- "shape": "shapes.X",
25
- "description": "Normalized and scaled output; same shape as `X` and same dtype as `scale`."
26
- },
27
- {
28
- "role": "inv_std_var",
29
  "dtype": "U",
30
- "rank": "ranks.X",
31
- "shape": "prefix(shapes.X, axisNorm) + fill(1, ranks.X - axisNorm)",
32
  "optional": true,
33
- "description": "Optional inverse RMS statistic `1 / sqrt(mean(X^2) + epsilon)`; same rank as `X`, with the dimensions from `axis` onward set to one."
34
  }
35
- ],
36
- "attributes": { "axis": -1, "epsilon": 0.00001, "stash_type": 1, "keep_dims": 1 },
37
- "attributeDescriptions": {
38
- "axis": "The first dimension of the normalization suffix; negative values count from the end, so the default `-1` normalizes only the last dimension.",
39
- "epsilon": "Small constant added to the mean square before taking the square root to avoid division by zero.",
40
- "stash_type": "TensorProto element type of `inv_std_var`; this package implements the legacy float32 value `1`.",
41
- "keep_dims": "Legacy compatibility attribute accepted and ignored by ONNX Runtime. The supported value `1` records the runtime's fixed behavior: optional statistics retain the input rank with normalized dimensions set to one."
42
  },
43
  "attributeConstraints": { "stash_type": { "values": [1] }, "keep_dims": { "values": [1] } },
44
  "typeConstraints": { "T": ["float32", "float16"], "V": ["float32", "float16"], "U": ["float32"] },
45
- "args": {
46
- "x": { "kind": "tensor", "semantic": "X", "role": "input" },
47
- "scale": { "kind": "tensor", "semantic": "scale", "role": "input" },
48
- "y": { "kind": "tensor", "semantic": "Y", "role": "output" },
49
- "invStdVar": { "kind": "tensor", "semantic": "inv_std_var", "role": "output", "required": false }
50
- },
51
  "tunables": {
52
- "WORKGROUP_SIZE": 256,
53
- "SPLIT_MAX_ROWS": 256,
54
- "SPLIT_MIN_HIDDEN": 16384,
55
- "SPLIT_TARGET_ELEMENTS": 4096,
56
- "MAX_SPLITS": 64
57
  },
58
  "derive": {
59
  "deviceWorkgroupCap": "min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)",
@@ -61,187 +35,44 @@
61
  "reportedNonWave32Adapter": "not wave32Adapter and (has(device.adapterInfo, \"subgroupMinSize\") or has(device.adapterInfo, \"subgroupMaxSize\"))",
62
  "normMaxWorkgroup": "min(tunables.WORKGROUP_SIZE, deviceWorkgroupCap)",
63
  "hasSubgroupId": "device.features.has(\"subgroups\") and device.wgslLanguageFeatures.has(\"subgroup_id\")",
64
- "axisNorm": "attrs.axis if attrs.axis >= 0 else attrs.axis + ranks.X",
65
- "normRows": "outer(shapes.X, axisNorm)",
66
- "normHidden": "dim(shapes.X, axisNorm) * inner(shapes.X, axisNorm)",
67
- "normRowStride": "max(1, min(normRows, device.limits.maxComputeWorkgroupsPerDimension))",
68
  "rowWg": "min(normMaxWorkgroup, pow2ceil(max(1, normHidden)))",
69
- "baseOk": "ranks.X >= 1 and sameShape(shapes.Y, shapes.X) and ranks.scale >= 0 and ranks.scale <= ranks.X and broadcastable(shapes.scale, shapes.X) and attrs.axis + ranks.X >= 0 and attrs.axis < ranks.X and normHidden > 0 and attrs.stash_type == onnxDtypeCode(\"float32\") and f16Ok(dtypes.T) and f16Ok(dtypes.V)",
70
- "lastAxisOk": "baseOk and (attrs.axis == -1 or attrs.axis == ranks.X - 1)",
71
- "suffixAxisOk": "baseOk and ranks.X >= 2 and not (attrs.axis == -1 or attrs.axis == ranks.X - 1)",
72
  "noStats": "not present.invStdVar",
73
- "statsOk": "present.invStdVar and ranks.inv_std_var == ranks.X and sameShape(prefix(shapes.inv_std_var, axisNorm), prefix(shapes.X, axisNorm)) and numel(suffix(shapes.inv_std_var, axisNorm)) == 1",
74
  "sameDtype": "dtypes.T == dtypes.V",
75
  "splitCount": "min(tunables.MAX_SPLITS, pow2ceil(ceilDiv(normHidden, tunables.SPLIT_TARGET_ELEMENTS)))",
76
  "splitScratchBytes": "normRows * splitCount * 4",
77
- "splitFits": "normRows <= tunables.SPLIT_MAX_ROWS and splitCount <= device.limits.maxComputeWorkgroupsPerDimension and splitScratchBytes <= device.limits.maxStorageBufferBindingSize and splitScratchBytes <= device.limits.maxBufferSize"
78
  },
79
- "bindingSets": {
80
- "rows": [
81
- {
82
- "name": "x",
83
- "arg": "x",
84
- "semantic": "X",
85
- "buffer": { "type": "read-only-storage" },
86
- "elementType": "$xElement"
87
- },
88
- {
89
- "name": "scale",
90
- "arg": "scale",
91
- "semantic": "scale",
92
- "buffer": { "type": "read-only-storage" },
93
- "elementType": "$ioElement"
94
- },
95
- { "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$ioElement" },
96
- {
97
- "name": "params",
98
- "semantic": "kernel.params",
99
- "buffer": { "type": "uniform" },
100
- "struct": {
101
- "name": "Params",
102
- "fields": [
103
- { "name": "rows", "type": "u32", "value": "normRows" },
104
- { "name": "rowStride", "type": "u32", "value": "normRowStride" }
105
- ]
106
- }
107
- }
108
- ],
109
- "rowsStats": [
110
- {
111
- "name": "x",
112
- "arg": "x",
113
- "semantic": "X",
114
- "buffer": { "type": "read-only-storage" },
115
- "elementType": "$xElement"
116
- },
117
- {
118
- "name": "scale",
119
- "arg": "scale",
120
- "semantic": "scale",
121
- "buffer": { "type": "read-only-storage" },
122
- "elementType": "$ioElement"
123
- },
124
- { "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$ioElement" },
125
- {
126
- "name": "inv_std_out",
127
- "arg": "invStdVar",
128
- "semantic": "inv_std_var",
129
- "buffer": { "type": "storage" },
130
- "elementType": "f32"
131
- },
132
- {
133
- "name": "params",
134
- "semantic": "kernel.params",
135
- "buffer": { "type": "uniform" },
136
- "struct": {
137
- "name": "Params",
138
- "fields": [
139
- { "name": "rows", "type": "u32", "value": "normRows" },
140
- { "name": "rowStride", "type": "u32", "value": "normRowStride" }
141
- ]
142
- }
143
- }
144
- ],
145
- "splitPartials": [
146
- {
147
- "name": "x",
148
- "arg": "x",
149
- "semantic": "X",
150
- "buffer": { "type": "read-only-storage" },
151
- "elementType": "$xElement"
152
- },
153
- { "name": "partials", "semantic": "partials", "buffer": { "type": "storage" }, "elementType": "f32" },
154
- {
155
- "name": "params",
156
- "semantic": "kernel.params",
157
- "buffer": { "type": "uniform" },
158
- "struct": {
159
- "name": "Params",
160
- "fields": [
161
- { "name": "rows", "type": "u32", "value": "normRows" },
162
- { "name": "rowStride", "type": "u32", "value": "normRowStride" }
163
- ]
164
- }
165
- }
166
- ],
167
- "splitNormalize": [
168
- {
169
- "name": "x",
170
- "arg": "x",
171
- "semantic": "X",
172
- "buffer": { "type": "read-only-storage" },
173
- "elementType": "$xElement"
174
- },
175
- {
176
- "name": "scale",
177
- "arg": "scale",
178
- "semantic": "scale",
179
- "buffer": { "type": "read-only-storage" },
180
- "elementType": "$ioElement"
181
- },
182
- { "name": "partials", "semantic": "partials", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
183
- { "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$ioElement" },
184
- {
185
- "name": "params",
186
- "semantic": "kernel.params",
187
- "buffer": { "type": "uniform" },
188
- "struct": {
189
- "name": "Params",
190
- "fields": [
191
- { "name": "rows", "type": "u32", "value": "normRows" },
192
- { "name": "rowStride", "type": "u32", "value": "normRowStride" }
193
- ]
194
- }
195
- }
196
- ],
197
- "splitNormalizeStats": [
198
- {
199
- "name": "x",
200
- "arg": "x",
201
- "semantic": "X",
202
- "buffer": { "type": "read-only-storage" },
203
- "elementType": "$xElement"
204
- },
205
- {
206
- "name": "scale",
207
- "arg": "scale",
208
- "semantic": "scale",
209
- "buffer": { "type": "read-only-storage" },
210
- "elementType": "$ioElement"
211
- },
212
- { "name": "partials", "semantic": "partials", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
213
- { "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$ioElement" },
214
- {
215
- "name": "inv_std_out",
216
- "arg": "invStdVar",
217
- "semantic": "inv_std_var",
218
- "buffer": { "type": "storage" },
219
- "elementType": "f32"
220
- },
221
- {
222
- "name": "params",
223
- "semantic": "kernel.params",
224
- "buffer": { "type": "uniform" },
225
- "struct": {
226
- "name": "Params",
227
- "fields": [
228
- { "name": "rows", "type": "u32", "value": "normRows" },
229
- { "name": "rowStride", "type": "u32", "value": "normRowStride" }
230
- ]
231
- }
232
- }
233
- ]
234
  },
235
  "variants": [
236
  {
237
  "id": "last_axis",
238
  "priority": 1,
239
  "when": ["lastAxisOk", "noStats"],
240
- "constants": {
241
  "scalar": "dtypes.V",
242
  "xElement": "dtypes.T",
243
  "ioElement": "dtypes.V",
244
- "usesF16": "dtypes.T == \"f16\" or dtypes.V == \"f16\"",
245
  "hiddenSize": "normHidden",
246
  "workgroupSize": "rowWg",
247
  "epsilon": "attrs.epsilon"
@@ -250,19 +81,17 @@
250
  {
251
  "id": "main",
252
  "name": "SimplifiedLayerNormalization.Row",
253
- "source": {
254
- "shader": "rms-normalization.wgsl.jinja",
255
- "inputs": {
256
- "xShape": "shapes.X",
257
- "scaleShape": "shapes.scale",
258
- "xRank": "ranks.X",
259
- "scaleRank": "ranks.scale",
260
- "writeStats": false,
261
- "rmsScaleAfterCast": false
262
- }
263
  },
264
- "bindings": "rows",
265
- "dispatch": { "workgroups": "normRows" }
266
  }
267
  ]
268
  },
@@ -270,11 +99,10 @@
270
  "id": "last_axis_stats",
271
  "priority": 2,
272
  "when": ["lastAxisOk", "statsOk"],
273
- "constants": {
274
  "scalar": "dtypes.V",
275
  "xElement": "dtypes.T",
276
  "ioElement": "dtypes.V",
277
- "usesF16": "dtypes.T == \"f16\" or dtypes.V == \"f16\"",
278
  "hiddenSize": "normHidden",
279
  "workgroupSize": "rowWg",
280
  "epsilon": "attrs.epsilon"
@@ -283,19 +111,17 @@
283
  {
284
  "id": "main",
285
  "name": "SimplifiedLayerNormalization.Row",
286
- "source": {
287
- "shader": "rms-normalization.wgsl.jinja",
288
- "inputs": {
289
- "xShape": "shapes.X",
290
- "scaleShape": "shapes.scale",
291
- "xRank": "ranks.X",
292
- "scaleRank": "ranks.scale",
293
- "writeStats": true,
294
- "rmsScaleAfterCast": false
295
- }
296
  },
297
- "bindings": "rowsStats",
298
- "dispatch": { "workgroups": "normRows" }
299
  }
300
  ]
301
  },
@@ -303,11 +129,10 @@
303
  "id": "suffix_axis",
304
  "priority": 10,
305
  "when": ["suffixAxisOk", "noStats"],
306
- "constants": {
307
  "scalar": "dtypes.V",
308
  "xElement": "dtypes.T",
309
  "ioElement": "dtypes.V",
310
- "usesF16": "dtypes.T == \"f16\" or dtypes.V == \"f16\"",
311
  "hiddenSize": "normHidden",
312
  "workgroupSize": "rowWg",
313
  "epsilon": "attrs.epsilon"
@@ -316,19 +141,17 @@
316
  {
317
  "id": "main",
318
  "name": "SimplifiedLayerNormalization.Row",
319
- "source": {
320
- "shader": "rms-normalization.wgsl.jinja",
321
- "inputs": {
322
- "xShape": "shapes.X",
323
- "scaleShape": "shapes.scale",
324
- "xRank": "ranks.X",
325
- "scaleRank": "ranks.scale",
326
- "writeStats": false,
327
- "rmsScaleAfterCast": false
328
- }
329
  },
330
- "bindings": "rows",
331
- "dispatch": { "workgroups": "normRows" }
332
  }
333
  ]
334
  },
@@ -336,11 +159,10 @@
336
  "id": "suffix_axis_stats",
337
  "priority": 11,
338
  "when": ["suffixAxisOk", "statsOk"],
339
- "constants": {
340
  "scalar": "dtypes.V",
341
  "xElement": "dtypes.T",
342
  "ioElement": "dtypes.V",
343
- "usesF16": "dtypes.T == \"f16\" or dtypes.V == \"f16\"",
344
  "hiddenSize": "normHidden",
345
  "workgroupSize": "rowWg",
346
  "epsilon": "attrs.epsilon"
@@ -349,113 +171,127 @@
349
  {
350
  "id": "main",
351
  "name": "SimplifiedLayerNormalization.Row",
352
- "source": {
353
- "shader": "rms-normalization.wgsl.jinja",
354
- "inputs": {
355
- "xShape": "shapes.X",
356
- "scaleShape": "shapes.scale",
357
- "xRank": "ranks.X",
358
- "scaleRank": "ranks.scale",
359
- "writeStats": true,
360
- "rmsScaleAfterCast": false
361
- }
362
  },
363
- "bindings": "rowsStats",
364
- "dispatch": { "workgroups": "normRows" }
365
  }
366
  ]
367
  },
368
  {
369
  "id": "suffix_axis_splitk",
370
  "priority": 15,
371
- "when": ["baseOk", "ranks.X >= 2", "noStats", "splitFits"],
372
  "demoteWhen": ["reportedNonWave32Adapter", "normHidden < tunables.SPLIT_MIN_HIDDEN"],
373
- "constants": {
374
  "scalar": "dtypes.V",
375
  "xElement": "dtypes.T",
376
  "ioElement": "dtypes.V",
377
- "usesF16": "dtypes.T == \"f16\" or dtypes.V == \"f16\"",
378
  "hiddenSize": "normHidden",
379
  "workgroupSize": "normMaxWorkgroup",
380
  "split": "splitCount",
381
- "epsilon": "attrs.epsilon"
 
382
  },
383
  "intermediates": [{ "id": "partials", "dtype": "float32", "shape": "[normRows * splitCount]" }],
384
  "passes": [
385
  {
386
  "id": "partials",
387
  "name": "SimplifiedLayerNormalization.SplitKPartials",
388
- "source": { "shader": "rms-normalization-splitk-partials.wgsl.jinja", "inputs": {} },
389
- "bindings": "splitPartials",
390
- "dispatch": { "workgroups": "normRows", "z": "splitCount" }
 
 
 
 
391
  },
392
  {
393
  "id": "normalize",
394
  "name": "SimplifiedLayerNormalization.SplitKNormalize",
395
- "source": {
396
- "shader": "rms-normalization-splitk-normalize.wgsl.jinja",
397
- "inputs": {
398
- "xShape": "shapes.X",
399
- "scaleShape": "shapes.scale",
400
- "xRank": "ranks.X",
401
- "scaleRank": "ranks.scale",
402
- "writeStats": false,
403
- "rmsScaleAfterCast": false
404
- }
405
  },
406
- "bindings": "splitNormalize",
407
- "dispatch": { "workgroups": "normRows", "z": "splitCount" }
 
 
 
 
408
  }
409
  ]
410
  },
411
  {
412
  "id": "suffix_axis_splitk_stats",
413
  "priority": 16,
414
- "when": ["baseOk", "ranks.X >= 2", "statsOk", "splitFits"],
415
  "demoteWhen": ["reportedNonWave32Adapter", "normHidden < tunables.SPLIT_MIN_HIDDEN"],
416
- "constants": {
417
  "scalar": "dtypes.V",
418
  "xElement": "dtypes.T",
419
  "ioElement": "dtypes.V",
420
- "usesF16": "dtypes.T == \"f16\" or dtypes.V == \"f16\"",
421
  "hiddenSize": "normHidden",
422
  "workgroupSize": "normMaxWorkgroup",
423
  "split": "splitCount",
424
- "epsilon": "attrs.epsilon"
 
425
  },
426
  "intermediates": [{ "id": "partials", "dtype": "float32", "shape": "[normRows * splitCount]" }],
427
  "passes": [
428
  {
429
  "id": "partials",
430
  "name": "SimplifiedLayerNormalization.SplitKPartials",
431
- "source": { "shader": "rms-normalization-splitk-partials.wgsl.jinja", "inputs": {} },
432
- "bindings": "splitPartials",
433
- "dispatch": { "workgroups": "normRows", "z": "splitCount" }
 
 
 
 
434
  },
435
  {
436
  "id": "normalize",
437
  "name": "SimplifiedLayerNormalization.SplitKNormalize",
438
- "source": {
439
- "shader": "rms-normalization-splitk-normalize.wgsl.jinja",
440
- "inputs": {
441
- "xShape": "shapes.X",
442
- "scaleShape": "shapes.scale",
443
- "xRank": "ranks.X",
444
- "scaleRank": "ranks.scale",
445
- "writeStats": true,
446
- "rmsScaleAfterCast": false
447
- }
448
  },
449
- "bindings": "splitNormalizeStats",
450
- "dispatch": { "workgroups": "normRows", "z": "splitCount" }
 
 
 
 
451
  }
452
  ]
453
  },
454
  {
455
  "id": "last_axis_row_vec4",
456
  "priority": 110,
457
- "when": ["lastAxisOk", "sameDtype", "noStats", "ranks.scale >= 1", "numel(shapes.scale) == dim(shapes.X, -1)", "dim(shapes.scale, -1) == dim(shapes.X, -1)", "dim(shapes.X, -1) % 4 == 0"],
458
- "constants": {
459
  "scalar": "dtypes.T",
460
  "xElement": "\"vec4<\" ~ dtypes.T ~ \">\"",
461
  "ioElement": "\"vec4<\" ~ dtypes.T ~ \">\""
@@ -464,66 +300,62 @@
464
  {
465
  "id": "main",
466
  "name": "SimplifiedLayerNormalization.LastAxisRow",
467
- "source": {
468
- "shader": "norm-row-stats.wgsl.jinja",
469
- "inputs": {
470
- "mode": "\"rms\"",
471
- "vec4": true,
472
- "writeStats": false,
473
- "rmsScaleAfterCast": false,
474
- "scalar": "dtypes.T",
475
- "usesF16": "dtypes.T == \"f16\"",
476
- "hidden": "dim(shapes.X, -1)",
477
- "wg": "min(normMaxWorkgroup, pow2ceil(max(1, dim(shapes.X, -1) / 4)))",
478
- "epsilon": "attrs.epsilon",
479
- "hiddenVec": "dim(shapes.X, -1) / 4",
480
- "vecType": "\"vec4<\" ~ dtypes.T ~ \">\"",
481
- "combineSubgroups": "hasSubgroupId"
482
- }
483
  },
484
- "subgroupCollectivesWidth": "portable",
485
- "bindings": "rows",
486
- "dispatch": { "workgroups": "normRows" }
487
  }
488
  ]
489
  },
490
  {
491
  "id": "last_axis_row",
492
  "priority": 100,
493
- "when": ["lastAxisOk", "sameDtype", "noStats", "ranks.scale >= 1", "numel(shapes.scale) == dim(shapes.X, -1)", "dim(shapes.scale, -1) == dim(shapes.X, -1)"],
494
- "constants": { "scalar": "dtypes.T", "xElement": "dtypes.T", "ioElement": "dtypes.T" },
495
  "passes": [
496
  {
497
  "id": "main",
498
  "name": "SimplifiedLayerNormalization.LastAxisRow",
499
- "source": {
500
- "shader": "norm-row-stats.wgsl.jinja",
501
- "inputs": {
502
- "mode": "\"rms\"",
503
- "vec4": false,
504
- "writeStats": false,
505
- "rmsScaleAfterCast": false,
506
- "scalar": "dtypes.T",
507
- "usesF16": "dtypes.T == \"f16\"",
508
- "hidden": "dim(shapes.X, -1)",
509
- "wg": "min(normMaxWorkgroup, pow2ceil(max(1, dim(shapes.X, -1))))",
510
- "epsilon": "attrs.epsilon",
511
- "hiddenVec": 1,
512
- "vecType": "\"vec4<\" ~ dtypes.T ~ \">\"",
513
- "combineSubgroups": "hasSubgroupId"
514
- }
515
  },
516
- "subgroupCollectivesWidth": "portable",
517
- "bindings": "rows",
518
- "dispatch": { "workgroups": "normRows" }
519
  }
520
  ]
521
  },
522
  {
523
  "id": "last_axis_row_vec4_stats",
524
  "priority": 112,
525
- "when": ["lastAxisOk", "sameDtype", "statsOk", "ranks.scale >= 1", "numel(shapes.scale) == dim(shapes.X, -1)", "dim(shapes.scale, -1) == dim(shapes.X, -1)", "dim(shapes.X, -1) % 4 == 0"],
526
- "constants": {
527
  "scalar": "dtypes.T",
528
  "xElement": "\"vec4<\" ~ dtypes.T ~ \">\"",
529
  "ioElement": "\"vec4<\" ~ dtypes.T ~ \">\""
@@ -532,58 +364,54 @@
532
  {
533
  "id": "main",
534
  "name": "SimplifiedLayerNormalization.LastAxisRow",
535
- "source": {
536
- "shader": "norm-row-stats.wgsl.jinja",
537
- "inputs": {
538
- "mode": "\"rms\"",
539
- "vec4": true,
540
- "writeStats": true,
541
- "rmsScaleAfterCast": false,
542
- "scalar": "dtypes.T",
543
- "usesF16": "dtypes.T == \"f16\"",
544
- "hidden": "dim(shapes.X, -1)",
545
- "wg": "min(normMaxWorkgroup, pow2ceil(max(1, dim(shapes.X, -1) / 4)))",
546
- "epsilon": "attrs.epsilon",
547
- "hiddenVec": "dim(shapes.X, -1) / 4",
548
- "vecType": "\"vec4<\" ~ dtypes.T ~ \">\"",
549
- "combineSubgroups": "hasSubgroupId"
550
- }
551
  },
552
- "subgroupCollectivesWidth": "portable",
553
- "bindings": "rowsStats",
554
- "dispatch": { "workgroups": "normRows" }
555
  }
556
  ]
557
  },
558
  {
559
  "id": "last_axis_row_stats",
560
  "priority": 102,
561
- "when": ["lastAxisOk", "sameDtype", "statsOk", "ranks.scale >= 1", "numel(shapes.scale) == dim(shapes.X, -1)", "dim(shapes.scale, -1) == dim(shapes.X, -1)"],
562
- "constants": { "scalar": "dtypes.T", "xElement": "dtypes.T", "ioElement": "dtypes.T" },
563
  "passes": [
564
  {
565
  "id": "main",
566
  "name": "SimplifiedLayerNormalization.LastAxisRow",
567
- "source": {
568
- "shader": "norm-row-stats.wgsl.jinja",
569
- "inputs": {
570
- "mode": "\"rms\"",
571
- "vec4": false,
572
- "writeStats": true,
573
- "rmsScaleAfterCast": false,
574
- "scalar": "dtypes.T",
575
- "usesF16": "dtypes.T == \"f16\"",
576
- "hidden": "dim(shapes.X, -1)",
577
- "wg": "min(normMaxWorkgroup, pow2ceil(max(1, dim(shapes.X, -1))))",
578
- "epsilon": "attrs.epsilon",
579
- "hiddenVec": 1,
580
- "vecType": "\"vec4<\" ~ dtypes.T ~ \">\"",
581
- "combineSubgroups": "hasSubgroupId"
582
- }
583
  },
584
- "subgroupCollectivesWidth": "portable",
585
- "bindings": "rowsStats",
586
- "dispatch": { "workgroups": "normRows" }
587
  }
588
  ]
589
  }
 
3
  "name": "SimplifiedLayerNormalization",
4
  "conformance": "legacy-default-domain",
5
  "sinceVersion": 1,
6
+ "inputs": { "x": { "onnx": "X", "dtype": "T" }, "scale": { "dtype": "V" } },
7
+ "outputs": {
8
+ "y": { "onnx": "Y", "dtype": "V", "rank": "ranks.x", "shape": "shapes.x" },
9
+ "invStdVar": {
10
+ "onnx": "inv_std_var",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  "dtype": "U",
12
+ "rank": "ranks.x",
 
13
  "optional": true,
14
+ "shape": "prefix(shapes.x, axisNorm) + fill(1, ranks.x - axisNorm)"
15
  }
16
+ },
17
+ "attributes": {
18
+ "axis": { "default": -1 },
19
+ "epsilon": { "default": 0.00001 },
20
+ "stash_type": { "default": 1 },
21
+ "keep_dims": { "default": 1 }
 
22
  },
23
  "attributeConstraints": { "stash_type": { "values": [1] }, "keep_dims": { "values": [1] } },
24
  "typeConstraints": { "T": ["float32", "float16"], "V": ["float32", "float16"], "U": ["float32"] },
 
 
 
 
 
 
25
  "tunables": {
26
+ "WORKGROUP_SIZE": { "default": 256 },
27
+ "SPLIT_MAX_ROWS": { "default": 256 },
28
+ "SPLIT_MIN_HIDDEN": { "default": 16384 },
29
+ "SPLIT_TARGET_ELEMENTS": { "default": 4096 },
30
+ "MAX_SPLITS": { "default": 64 }
31
  },
32
  "derive": {
33
  "deviceWorkgroupCap": "min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)",
 
35
  "reportedNonWave32Adapter": "not wave32Adapter and (has(device.adapterInfo, \"subgroupMinSize\") or has(device.adapterInfo, \"subgroupMaxSize\"))",
36
  "normMaxWorkgroup": "min(tunables.WORKGROUP_SIZE, deviceWorkgroupCap)",
37
  "hasSubgroupId": "device.features.has(\"subgroups\") and device.wgslLanguageFeatures.has(\"subgroup_id\")",
38
+ "axisNorm": "attrs.axis if attrs.axis >= 0 else attrs.axis + ranks.x",
39
+ "normRows": "outer(shapes.x, axisNorm)",
40
+ "normHidden": "dim(shapes.x, axisNorm) * inner(shapes.x, axisNorm)",
41
+ "normRowStride": "max(1, min(normRows, min(device.limits.maxComputeWorkgroupsPerDimension, 65535)))",
42
  "rowWg": "min(normMaxWorkgroup, pow2ceil(max(1, normHidden)))",
43
+ "baseOk": "ranks.x >= 1 and sameShape(shapes.y, shapes.x) and ranks.scale >= 0 and ranks.scale <= ranks.x and broadcastable(shapes.scale, shapes.x) and attrs.axis + ranks.x >= 0 and attrs.axis < ranks.x and normHidden > 0 and attrs.stash_type == onnxDtypeCode(\"float32\") and f16Ok(dtypes.T) and f16Ok(dtypes.V)",
44
+ "lastAxisOk": "baseOk and (attrs.axis == -1 or attrs.axis == ranks.x - 1)",
45
+ "suffixAxisOk": "baseOk and ranks.x >= 2 and not (attrs.axis == -1 or attrs.axis == ranks.x - 1)",
46
  "noStats": "not present.invStdVar",
47
+ "statsOk": "present.invStdVar and ranks.invStdVar == ranks.x and sameShape(prefix(shapes.invStdVar, axisNorm), prefix(shapes.x, axisNorm)) and numel(suffix(shapes.invStdVar, axisNorm)) == 1",
48
  "sameDtype": "dtypes.T == dtypes.V",
49
  "splitCount": "min(tunables.MAX_SPLITS, pow2ceil(ceilDiv(normHidden, tunables.SPLIT_TARGET_ELEMENTS)))",
50
  "splitScratchBytes": "normRows * splitCount * 4",
51
+ "splitFits": "normRows <= tunables.SPLIT_MAX_ROWS and splitCount <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535) and splitScratchBytes <= device.limits.maxStorageBufferBindingSize and splitScratchBytes <= device.limits.maxBufferSize"
52
  },
53
+ "bindings": {
54
+ "x": { "buffer": "read-only-storage", "elementType": "$xElement" },
55
+ "scale": { "buffer": "read-only-storage", "elementType": "$ioElement" },
56
+ "y": { "buffer": "storage", "elementType": "$ioElement" },
57
+ "params": {
58
+ "buffer": "uniform",
59
+ "struct": [
60
+ { "name": "rows", "type": "u32", "value": "normRows" },
61
+ { "name": "rowStride", "type": "u32", "value": "normRowStride" }
62
+ ]
63
+ },
64
+ "inv_std_out": { "arg": "invStdVar", "buffer": "storage", "elementType": "f32" },
65
+ "partials_2": { "name": "partials", "buffer": "read-only-storage", "elementType": "f32" }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  },
67
  "variants": [
68
  {
69
  "id": "last_axis",
70
  "priority": 1,
71
  "when": ["lastAxisOk", "noStats"],
72
+ "derive": {
73
  "scalar": "dtypes.V",
74
  "xElement": "dtypes.T",
75
  "ioElement": "dtypes.V",
 
76
  "hiddenSize": "normHidden",
77
  "workgroupSize": "rowWg",
78
  "epsilon": "attrs.epsilon"
 
81
  {
82
  "id": "main",
83
  "name": "SimplifiedLayerNormalization.Row",
84
+ "shader": "rms-normalization.wgsl.jinja",
85
+ "derive": {
86
+ "xShape": "shapes.x",
87
+ "scaleShape": "shapes.scale",
88
+ "xRank": "ranks.x",
89
+ "scaleRank": "ranks.scale",
90
+ "writeStats": false,
91
+ "rmsScaleAfterCast": false
 
 
92
  },
93
+ "bindings": ["x", "scale", "y", "params"],
94
+ "dispatch": { "x": "min(normRows, 65535)", "y": "ceilDiv(normRows, 65535)", "z": 1 }
95
  }
96
  ]
97
  },
 
99
  "id": "last_axis_stats",
100
  "priority": 2,
101
  "when": ["lastAxisOk", "statsOk"],
102
+ "derive": {
103
  "scalar": "dtypes.V",
104
  "xElement": "dtypes.T",
105
  "ioElement": "dtypes.V",
 
106
  "hiddenSize": "normHidden",
107
  "workgroupSize": "rowWg",
108
  "epsilon": "attrs.epsilon"
 
111
  {
112
  "id": "main",
113
  "name": "SimplifiedLayerNormalization.Row",
114
+ "shader": "rms-normalization.wgsl.jinja",
115
+ "derive": {
116
+ "xShape": "shapes.x",
117
+ "scaleShape": "shapes.scale",
118
+ "xRank": "ranks.x",
119
+ "scaleRank": "ranks.scale",
120
+ "writeStats": true,
121
+ "rmsScaleAfterCast": false
 
 
122
  },
123
+ "bindings": ["x", "scale", "y", "inv_std_out", "params"],
124
+ "dispatch": { "x": "min(normRows, 65535)", "y": "ceilDiv(normRows, 65535)", "z": 1 }
125
  }
126
  ]
127
  },
 
129
  "id": "suffix_axis",
130
  "priority": 10,
131
  "when": ["suffixAxisOk", "noStats"],
132
+ "derive": {
133
  "scalar": "dtypes.V",
134
  "xElement": "dtypes.T",
135
  "ioElement": "dtypes.V",
 
136
  "hiddenSize": "normHidden",
137
  "workgroupSize": "rowWg",
138
  "epsilon": "attrs.epsilon"
 
141
  {
142
  "id": "main",
143
  "name": "SimplifiedLayerNormalization.Row",
144
+ "shader": "rms-normalization.wgsl.jinja",
145
+ "derive": {
146
+ "xShape": "shapes.x",
147
+ "scaleShape": "shapes.scale",
148
+ "xRank": "ranks.x",
149
+ "scaleRank": "ranks.scale",
150
+ "writeStats": false,
151
+ "rmsScaleAfterCast": false
 
 
152
  },
153
+ "bindings": ["x", "scale", "y", "params"],
154
+ "dispatch": { "x": "min(normRows, 65535)", "y": "ceilDiv(normRows, 65535)", "z": 1 }
155
  }
156
  ]
157
  },
 
159
  "id": "suffix_axis_stats",
160
  "priority": 11,
161
  "when": ["suffixAxisOk", "statsOk"],
162
+ "derive": {
163
  "scalar": "dtypes.V",
164
  "xElement": "dtypes.T",
165
  "ioElement": "dtypes.V",
 
166
  "hiddenSize": "normHidden",
167
  "workgroupSize": "rowWg",
168
  "epsilon": "attrs.epsilon"
 
171
  {
172
  "id": "main",
173
  "name": "SimplifiedLayerNormalization.Row",
174
+ "shader": "rms-normalization.wgsl.jinja",
175
+ "derive": {
176
+ "xShape": "shapes.x",
177
+ "scaleShape": "shapes.scale",
178
+ "xRank": "ranks.x",
179
+ "scaleRank": "ranks.scale",
180
+ "writeStats": true,
181
+ "rmsScaleAfterCast": false
 
 
182
  },
183
+ "bindings": ["x", "scale", "y", "inv_std_out", "params"],
184
+ "dispatch": { "x": "min(normRows, 65535)", "y": "ceilDiv(normRows, 65535)", "z": 1 }
185
  }
186
  ]
187
  },
188
  {
189
  "id": "suffix_axis_splitk",
190
  "priority": 15,
191
+ "when": ["baseOk", "ranks.x >= 2", "noStats", "splitFits"],
192
  "demoteWhen": ["reportedNonWave32Adapter", "normHidden < tunables.SPLIT_MIN_HIDDEN"],
193
+ "derive": {
194
  "scalar": "dtypes.V",
195
  "xElement": "dtypes.T",
196
  "ioElement": "dtypes.V",
 
197
  "hiddenSize": "normHidden",
198
  "workgroupSize": "normMaxWorkgroup",
199
  "split": "splitCount",
200
+ "epsilon": "attrs.epsilon",
201
+ "normalizeRows": "normRows"
202
  },
203
  "intermediates": [{ "id": "partials", "dtype": "float32", "shape": "[normRows * splitCount]" }],
204
  "passes": [
205
  {
206
  "id": "partials",
207
  "name": "SimplifiedLayerNormalization.SplitKPartials",
208
+ "shader": "rms-normalization-splitk-partials.wgsl.jinja",
209
+ "bindings": ["x", { "name": "partials", "buffer": "storage", "elementType": "f32" }, "params"],
210
+ "dispatch": {
211
+ "x": "min(normRows, DISPATCH_FOLD_WIDTH)",
212
+ "y": "ceilDiv(normRows, DISPATCH_FOLD_WIDTH)",
213
+ "z": "splitCount"
214
+ }
215
  },
216
  {
217
  "id": "normalize",
218
  "name": "SimplifiedLayerNormalization.SplitKNormalize",
219
+ "shader": "rms-normalization-splitk-normalize.wgsl.jinja",
220
+ "derive": {
221
+ "xShape": "shapes.x",
222
+ "scaleShape": "shapes.scale",
223
+ "xRank": "ranks.x",
224
+ "scaleRank": "ranks.scale",
225
+ "writeStats": false,
226
+ "rmsScaleAfterCast": false,
227
+ "normalizeBlocks": "max(split, min(min(device.limits.maxComputeWorkgroupsPerDimension, 65535), ceilDiv(workgroupSize, max(1, normalizeRows)), ceilDiv(hiddenSize, workgroupSize * 4)))",
228
+ "normalizeChunk": "ceilDiv(hiddenSize, normalizeBlocks)"
229
  },
230
+ "bindings": ["x", "scale", "partials_2", "y", "params"],
231
+ "dispatch": {
232
+ "x": "min(normRows, DISPATCH_FOLD_WIDTH)",
233
+ "y": "ceilDiv(normRows, DISPATCH_FOLD_WIDTH)",
234
+ "z": "normalizeBlocks"
235
+ }
236
  }
237
  ]
238
  },
239
  {
240
  "id": "suffix_axis_splitk_stats",
241
  "priority": 16,
242
+ "when": ["baseOk", "ranks.x >= 2", "statsOk", "splitFits"],
243
  "demoteWhen": ["reportedNonWave32Adapter", "normHidden < tunables.SPLIT_MIN_HIDDEN"],
244
+ "derive": {
245
  "scalar": "dtypes.V",
246
  "xElement": "dtypes.T",
247
  "ioElement": "dtypes.V",
 
248
  "hiddenSize": "normHidden",
249
  "workgroupSize": "normMaxWorkgroup",
250
  "split": "splitCount",
251
+ "epsilon": "attrs.epsilon",
252
+ "normalizeRows": "normRows"
253
  },
254
  "intermediates": [{ "id": "partials", "dtype": "float32", "shape": "[normRows * splitCount]" }],
255
  "passes": [
256
  {
257
  "id": "partials",
258
  "name": "SimplifiedLayerNormalization.SplitKPartials",
259
+ "shader": "rms-normalization-splitk-partials.wgsl.jinja",
260
+ "bindings": ["x", { "name": "partials", "buffer": "storage", "elementType": "f32" }, "params"],
261
+ "dispatch": {
262
+ "x": "min(normRows, DISPATCH_FOLD_WIDTH)",
263
+ "y": "ceilDiv(normRows, DISPATCH_FOLD_WIDTH)",
264
+ "z": "splitCount"
265
+ }
266
  },
267
  {
268
  "id": "normalize",
269
  "name": "SimplifiedLayerNormalization.SplitKNormalize",
270
+ "shader": "rms-normalization-splitk-normalize.wgsl.jinja",
271
+ "derive": {
272
+ "xShape": "shapes.x",
273
+ "scaleShape": "shapes.scale",
274
+ "xRank": "ranks.x",
275
+ "scaleRank": "ranks.scale",
276
+ "writeStats": true,
277
+ "rmsScaleAfterCast": false,
278
+ "normalizeBlocks": "max(split, min(min(device.limits.maxComputeWorkgroupsPerDimension, 65535), ceilDiv(workgroupSize, max(1, normalizeRows)), ceilDiv(hiddenSize, workgroupSize * 4)))",
279
+ "normalizeChunk": "ceilDiv(hiddenSize, normalizeBlocks)"
280
  },
281
+ "bindings": ["x", "scale", "partials_2", "y", "inv_std_out", "params"],
282
+ "dispatch": {
283
+ "x": "min(normRows, DISPATCH_FOLD_WIDTH)",
284
+ "y": "ceilDiv(normRows, DISPATCH_FOLD_WIDTH)",
285
+ "z": "normalizeBlocks"
286
+ }
287
  }
288
  ]
289
  },
290
  {
291
  "id": "last_axis_row_vec4",
292
  "priority": 110,
293
+ "when": ["lastAxisOk", "sameDtype", "noStats", "ranks.scale >= 1", "numel(shapes.scale) == dim(shapes.x, -1)", "dim(shapes.scale, -1) == dim(shapes.x, -1)", "dim(shapes.x, -1) % 4 == 0"],
294
+ "derive": {
295
  "scalar": "dtypes.T",
296
  "xElement": "\"vec4<\" ~ dtypes.T ~ \">\"",
297
  "ioElement": "\"vec4<\" ~ dtypes.T ~ \">\""
 
300
  {
301
  "id": "main",
302
  "name": "SimplifiedLayerNormalization.LastAxisRow",
303
+ "shader": "norm-row-stats.wgsl.jinja",
304
+ "derive": {
305
+ "modeSpec": "\"rms\"",
306
+ "vec4": true,
307
+ "writeStats": false,
308
+ "rmsScaleAfterCast": false,
309
+ "scalar": "dtypes.T",
310
+ "usesF16Spec": "dtypes.T == \"f16\"",
311
+ "hidden": "dim(shapes.x, -1)",
312
+ "wg": "min(normMaxWorkgroup, pow2ceil(max(1, dim(shapes.x, -1) / 4)))",
313
+ "epsilon": "attrs.epsilon",
314
+ "hiddenVec": "dim(shapes.x, -1) / 4",
315
+ "vecType": "\"vec4<\" ~ dtypes.T ~ \">\"",
316
+ "combineSubgroups": "hasSubgroupId"
 
 
317
  },
318
+ "bindings": ["x", "scale", "y", "params"],
319
+ "dispatch": { "x": "min(normRows, 65535)", "y": "ceilDiv(normRows, 65535)", "z": 1 },
320
+ "subgroupCollectivesWidth": "portable"
321
  }
322
  ]
323
  },
324
  {
325
  "id": "last_axis_row",
326
  "priority": 100,
327
+ "when": ["lastAxisOk", "sameDtype", "noStats", "ranks.scale >= 1", "numel(shapes.scale) == dim(shapes.x, -1)", "dim(shapes.scale, -1) == dim(shapes.x, -1)"],
328
+ "derive": { "scalar": "dtypes.T", "xElement": "dtypes.T", "ioElement": "dtypes.T" },
329
  "passes": [
330
  {
331
  "id": "main",
332
  "name": "SimplifiedLayerNormalization.LastAxisRow",
333
+ "shader": "norm-row-stats.wgsl.jinja",
334
+ "derive": {
335
+ "modeSpec": "\"rms\"",
336
+ "vec4": false,
337
+ "writeStats": false,
338
+ "rmsScaleAfterCast": false,
339
+ "scalar": "dtypes.T",
340
+ "usesF16Spec": "dtypes.T == \"f16\"",
341
+ "hidden": "dim(shapes.x, -1)",
342
+ "wg": "min(normMaxWorkgroup, pow2ceil(max(1, dim(shapes.x, -1))))",
343
+ "epsilon": "attrs.epsilon",
344
+ "hiddenVec": 1,
345
+ "vecType": "\"vec4<\" ~ dtypes.T ~ \">\"",
346
+ "combineSubgroups": "hasSubgroupId"
 
 
347
  },
348
+ "bindings": ["x", "scale", "y", "params"],
349
+ "dispatch": { "x": "min(normRows, 65535)", "y": "ceilDiv(normRows, 65535)", "z": 1 },
350
+ "subgroupCollectivesWidth": "portable"
351
  }
352
  ]
353
  },
354
  {
355
  "id": "last_axis_row_vec4_stats",
356
  "priority": 112,
357
+ "when": ["lastAxisOk", "sameDtype", "statsOk", "ranks.scale >= 1", "numel(shapes.scale) == dim(shapes.x, -1)", "dim(shapes.scale, -1) == dim(shapes.x, -1)", "dim(shapes.x, -1) % 4 == 0"],
358
+ "derive": {
359
  "scalar": "dtypes.T",
360
  "xElement": "\"vec4<\" ~ dtypes.T ~ \">\"",
361
  "ioElement": "\"vec4<\" ~ dtypes.T ~ \">\""
 
364
  {
365
  "id": "main",
366
  "name": "SimplifiedLayerNormalization.LastAxisRow",
367
+ "shader": "norm-row-stats.wgsl.jinja",
368
+ "derive": {
369
+ "modeSpec": "\"rms\"",
370
+ "vec4": true,
371
+ "writeStats": true,
372
+ "rmsScaleAfterCast": false,
373
+ "scalar": "dtypes.T",
374
+ "usesF16Spec": "dtypes.T == \"f16\"",
375
+ "hidden": "dim(shapes.x, -1)",
376
+ "wg": "min(normMaxWorkgroup, pow2ceil(max(1, dim(shapes.x, -1) / 4)))",
377
+ "epsilon": "attrs.epsilon",
378
+ "hiddenVec": "dim(shapes.x, -1) / 4",
379
+ "vecType": "\"vec4<\" ~ dtypes.T ~ \">\"",
380
+ "combineSubgroups": "hasSubgroupId"
 
 
381
  },
382
+ "bindings": ["x", "scale", "y", "inv_std_out", "params"],
383
+ "dispatch": { "x": "min(normRows, 65535)", "y": "ceilDiv(normRows, 65535)", "z": 1 },
384
+ "subgroupCollectivesWidth": "portable"
385
  }
386
  ]
387
  },
388
  {
389
  "id": "last_axis_row_stats",
390
  "priority": 102,
391
+ "when": ["lastAxisOk", "sameDtype", "statsOk", "ranks.scale >= 1", "numel(shapes.scale) == dim(shapes.x, -1)", "dim(shapes.scale, -1) == dim(shapes.x, -1)"],
392
+ "derive": { "scalar": "dtypes.T", "xElement": "dtypes.T", "ioElement": "dtypes.T" },
393
  "passes": [
394
  {
395
  "id": "main",
396
  "name": "SimplifiedLayerNormalization.LastAxisRow",
397
+ "shader": "norm-row-stats.wgsl.jinja",
398
+ "derive": {
399
+ "modeSpec": "\"rms\"",
400
+ "vec4": false,
401
+ "writeStats": true,
402
+ "rmsScaleAfterCast": false,
403
+ "scalar": "dtypes.T",
404
+ "usesF16Spec": "dtypes.T == \"f16\"",
405
+ "hidden": "dim(shapes.x, -1)",
406
+ "wg": "min(normMaxWorkgroup, pow2ceil(max(1, dim(shapes.x, -1))))",
407
+ "epsilon": "attrs.epsilon",
408
+ "hiddenVec": 1,
409
+ "vecType": "\"vec4<\" ~ dtypes.T ~ \">\"",
410
+ "combineSubgroups": "hasSubgroupId"
 
 
411
  },
412
+ "bindings": ["x", "scale", "y", "inv_std_out", "params"],
413
+ "dispatch": { "x": "min(normRows, 65535)", "y": "ceilDiv(normRows, 65535)", "z": 1 },
414
+ "subgroupCollectivesWidth": "portable"
415
  }
416
  ]
417
  }
build/webgpu/metadata.json CHANGED
@@ -1,21 +1,35 @@
1
  {
2
  "name": "ai.onnx.SimplifiedLayerNormalization",
3
- "id": "_ai_onnx_simplifiedlayernormalization_webgpu_e7aa570",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
- "bench.json": "pvZ/eyxjfpTLTo48nnQhDaKG61UPA6L0EPXu4QnH7MY=",
11
- "manifest.json": "hfKp3YN8J74f7KzVbFXsOBq5wNbZm2A8QMJ3ww5MAdw=",
12
- "norm-row-stats.wgsl.jinja": "GopNOsand0HoXzNtQnzGdvJKmHbCv96No/7heLcS9VA=",
13
- "rms-normalization-splitk-normalize.wgsl.jinja": "YklXSmW/XGI1M5KVzfayKp0EQ+3iAYHeOnTAMA4UW4c=",
14
- "rms-normalization-splitk-partials.wgsl.jinja": "GbYu7Cj/LLO9y2Rvhw30RJAUAduI0xfN5YS3H/4Z1k8=",
15
- "rms-normalization.wgsl.jinja": "wNOsrtTIc7DmBifozpAm2fZ3iWznPJ04EhFMkOq6GqA=",
16
- "test.json": "ycI7oQ1MKS87yo6QXLI36xLz840eYS69Y/anRQHQkUY="
17
  }
18
  },
19
- "provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
20
- "webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/ai.onnx.SimplifiedLayerNormalization" }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  }
 
1
  {
2
  "name": "ai.onnx.SimplifiedLayerNormalization",
3
+ "id": "_ai_onnx_simplifiedlayernormalization_webgpu_b0bbd51",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
+ "bench.json": "oL4NDZsKfggbFJ8moDoDY5cYbkZb/dnRCxB7mA3YuW0=",
11
+ "manifest.json": "M3zOOpjNYbDBPlApZytNSUFrdixB+kGxE4X9xKY7yzk=",
12
+ "norm-row-stats.wgsl.jinja": "eRBO50QnNhvyqRW/Wdw6rzfJRgVlRT0P6oWVqcDPf5w=",
13
+ "rms-normalization-splitk-normalize.wgsl.jinja": "vqx3jngJ7c+zkmcD3Nc7mt4Fm77XXDmtrQt9ULWgHKE=",
14
+ "rms-normalization-splitk-partials.wgsl.jinja": "Vs4HNsa9ZbLPsW/ZOunRg64qFmbg7WfJ/uE6gqALmSQ=",
15
+ "rms-normalization.wgsl.jinja": "tRDNHNbkHoidOuTQwnH3Jx0msfP74Px5ukRNF9Hh8fw=",
16
+ "test.json": "PYhuNCaFTpBU8GJFS/LzpdoBKLbT0praPXzHhs7rg50="
17
  }
18
  },
19
+ "provenance": { "kernel": { "sha": "91d990483a174128daf7673f3f37a7c890493ae1", "dirty": false } },
20
+ "webgpu": {
21
+ "manifestSpec": "2.0",
22
+ "variants": {
23
+ "last_axis": ["rms-normalization.wgsl.jinja"],
24
+ "last_axis_stats": ["rms-normalization.wgsl.jinja"],
25
+ "suffix_axis": ["rms-normalization.wgsl.jinja"],
26
+ "suffix_axis_stats": ["rms-normalization.wgsl.jinja"],
27
+ "suffix_axis_splitk": ["rms-normalization-splitk-normalize.wgsl.jinja", "rms-normalization-splitk-partials.wgsl.jinja"],
28
+ "suffix_axis_splitk_stats": ["rms-normalization-splitk-normalize.wgsl.jinja", "rms-normalization-splitk-partials.wgsl.jinja"],
29
+ "last_axis_row_vec4": ["norm-row-stats.wgsl.jinja"],
30
+ "last_axis_row": ["norm-row-stats.wgsl.jinja"],
31
+ "last_axis_row_vec4_stats": ["norm-row-stats.wgsl.jinja"],
32
+ "last_axis_row_stats": ["norm-row-stats.wgsl.jinja"]
33
+ }
34
+ }
35
  }
build/webgpu/norm-row-stats.wgsl.jinja CHANGED
@@ -1,11 +1,25 @@
1
- {% if source.usesF16 %}
2
  enable f16;
3
  {% endif %}
4
- {% set combineSubgroups = source.combineSubgroups %}
5
- {% set scalarIo = source.scalarIo if source.scalarIo is defined else false %}
6
- {% set writeStats = source.writeStats if source.writeStats is defined else false %}
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  {% set rmsScaleVec = "vec4<f32>(scale[i])" %}
8
  {% set rmsScaleScalar = "f32(scale[i])" %}
 
9
  {% set reduceThreadParameters = ", sg_lane: u32, sg_id: u32, num_sg: u32"
10
  if combineSubgroups else ", tid: u32" %}
11
  {% set reduceThreadArguments = ", sg_lane, sg_id, num_sg"
@@ -24,14 +38,57 @@ enable subgroups;
24
  // tree, then every thread applies the fused normalize + affine write.
25
  //
26
  // RMS mode uses sum_sq / HIDDEN without computing or subtracting a mean.
27
- const HIDDEN: u32 = {{ source.hidden }}u;
28
- {% if source.vec4 %}
29
- const HIDDEN_V: u32 = {{ source.hiddenVec }}u;
 
 
 
 
 
 
 
 
 
30
  {% endif %}
31
- const WG: u32 = {{ source.wg }}u;
32
- const EPSILON: f32 = {{ source.epsilon }};
33
 
 
 
 
 
 
 
 
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  {% if combineSubgroups %}
37
  var<workgroup> sg_partials: array<f32, WG>;
@@ -85,7 +142,14 @@ fn main(
85
  return;
86
  }
87
  let tid = lid.x;
88
- {% if source.vec4 and not scalarIo %}
 
 
 
 
 
 
 
89
  let base = row * HIDDEN_V;
90
  {% else %}
91
  let base = row * HIDDEN;
@@ -93,14 +157,26 @@ fn main(
93
 
94
 
95
  var acc = 0.0;
96
- {% if source.vec4 %}
97
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
 
 
 
 
 
 
98
  let v = vec4<f32>(x[base + i]);
 
99
  acc = acc + dot(v, v);
100
  }
101
  {% else %}
102
  for (var i = tid; i < HIDDEN; i = i + WG) {
 
 
 
 
103
  let v = f32(x[base + i]);
 
104
  acc = acc + v * v;
105
  }
106
  {% endif %}
@@ -114,17 +190,64 @@ fn main(
114
  }
115
  {% endif %}
116
 
117
- {% if source.vec4 %}
 
 
 
118
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
 
 
 
 
 
 
 
119
  let idx = base + i;
120
  let v = vec4<f32>(x[idx]);
121
- y[idx] = {{ source.vecType }}(v * inv * {{ rmsScaleVec }});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  {% else %}
124
  for (var i = tid; i < HIDDEN; i = i + WG) {
125
  let idx = base + i;
 
 
 
126
  let v = f32(x[idx]);
127
- y[idx] = {{ source.scalar }}(v * inv * {{ rmsScaleScalar }});
 
 
 
 
 
128
  }
129
  {% endif %}
130
  }
 
1
+ {% if usesF16Spec %}
2
  enable f16;
3
  {% endif %}
4
+ {% set combineSubgroups = combineSubgroups %}
5
+ {% set scalarIo = scalarIo if scalarIo is defined else false %}
6
+ {% set packedBf16Embedding = packedBf16Embedding if packedBf16Embedding is defined else false %}
7
+ {% set writeStats = writeStats if writeStats is defined else false %}
8
+ {% set rmsWeightOffset = rmsWeightOffset if rmsWeightOffset is defined else false %}
9
+ {% set rmsScaleAfterCast = rmsScaleAfterCast if rmsScaleAfterCast is defined else false %}
10
+ {% set rmsResidualAdd = rmsResidualAdd if rmsResidualAdd is defined else false %}
11
+ {% set rmsChainNorm = rmsChainNorm if rmsChainNorm is defined else false %}
12
+ {% set hiddenPairs = hiddenPairs | default(0) %}
13
+ {% set numRows = numRows | default(0) %}
14
+ {% set epsilon = epsilon | default("0.0") %}
15
+ {% set epsilon2 = epsilon2 | default("0.0") %}
16
+ {% if rmsWeightOffset %}
17
+ {% set rmsScaleVec = "(vec4<f32>(1.0) + vec4<f32>(scale[i]))" %}
18
+ {% set rmsScaleScalar = "(1.0 + f32(scale[i]))" %}
19
+ {% else %}
20
  {% set rmsScaleVec = "vec4<f32>(scale[i])" %}
21
  {% set rmsScaleScalar = "f32(scale[i])" %}
22
+ {% endif %}
23
  {% set reduceThreadParameters = ", sg_lane: u32, sg_id: u32, num_sg: u32"
24
  if combineSubgroups else ", tid: u32" %}
25
  {% set reduceThreadArguments = ", sg_lane, sg_id, num_sg"
 
38
  // tree, then every thread applies the fused normalize + affine write.
39
  //
40
  // RMS mode uses sum_sq / HIDDEN without computing or subtracting a mean.
41
+ const HIDDEN: u32 = {{ hidden }}u;
42
+ {% if vec4 %}
43
+ const HIDDEN_V: u32 = {{ hiddenVec }}u;
44
+ {% endif %}
45
+ {% if packedBf16Embedding %}
46
+ const HIDDEN_PAIRS: u32 = {{ hiddenPairs }}u;
47
+ const NUM_ROWS: u32 = {{ numRows }}u;
48
+ {% endif %}
49
+ const WG: u32 = {{ wg }}u;
50
+ const EPSILON: f32 = {{ epsilon }};
51
+ {% if rmsChainNorm %}
52
+ const EPSILON2: f32 = {{ epsilon2 }};
53
  {% endif %}
 
 
54
 
55
+ {% if packedBf16Embedding %}
56
+ {% if vec4 %}
57
+ fn unpack_bf16_pair(word: u32) -> vec2<f32> {
58
+ let bits = vec2<u32>(word & 0xffffu, word >> 16u);
59
+ return bitcast<vec2<f32>>(bits << vec2<u32>(16u));
60
+ }
61
+ {% endif %}
62
 
63
+ {% if not vec4 %}
64
+ fn embedding_scalar(source_row: u32, hidden: u32) -> f32 {
65
+ if (source_row >= NUM_ROWS) {
66
+ return 0.0;
67
+ }
68
+ let word = x[source_row * HIDDEN_PAIRS + (hidden >> 1u)];
69
+ let bits = select(word & 0xffffu, word >> 16u, (hidden & 1u) != 0u);
70
+ return bitcast<f32>(bits << 16u);
71
+ }
72
+ {% endif %}
73
+
74
+ {% if vec4 %}
75
+ fn embedding_vec4(source_row: u32, hidden_vec: u32) -> vec4<f32> {
76
+ if (source_row >= NUM_ROWS) {
77
+ return vec4<f32>(0.0);
78
+ }
79
+ let base = source_row * HIDDEN_PAIRS + hidden_vec * 2u;
80
+ let low = unpack_bf16_pair(x[base]);
81
+ let high = unpack_bf16_pair(x[base + 1u]);
82
+ return vec4<f32>(low, high);
83
+ }
84
+ {% endif %}
85
+ {% endif %}
86
+
87
+ {% if vec4 and scalarIo %}
88
+ fn load_vec4(index: u32) -> vec4<f32> {
89
+ return vec4<f32>(x[index], x[index + 1u], x[index + 2u], x[index + 3u]);
90
+ }
91
+ {% endif %}
92
 
93
  {% if combineSubgroups %}
94
  var<workgroup> sg_partials: array<f32, WG>;
 
142
  return;
143
  }
144
  let tid = lid.x;
145
+ {% if packedBf16Embedding %}
146
+ let source_row = indices[row];
147
+ {% if vec4 %}
148
+ let base = row * HIDDEN_V;
149
+ {% else %}
150
+ let base = row * HIDDEN;
151
+ {% endif %}
152
+ {% elif vec4 and not scalarIo %}
153
  let base = row * HIDDEN_V;
154
  {% else %}
155
  let base = row * HIDDEN;
 
157
 
158
 
159
  var acc = 0.0;
160
+ {% if vec4 %}
161
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
162
+ {% if packedBf16Embedding %}
163
+ let v = embedding_vec4(source_row, i);
164
+ embedding_out[base + i] = v;
165
+ {% elif scalarIo %}
166
+ let v = load_vec4(base + i * 4u);
167
+ {% else %}
168
  let v = vec4<f32>(x[base + i]);
169
+ {% endif %}
170
  acc = acc + dot(v, v);
171
  }
172
  {% else %}
173
  for (var i = tid; i < HIDDEN; i = i + WG) {
174
+ {% if packedBf16Embedding %}
175
+ let v = embedding_scalar(source_row, i);
176
+ embedding_out[base + i] = v;
177
+ {% else %}
178
  let v = f32(x[base + i]);
179
+ {% endif %}
180
  acc = acc + v * v;
181
  }
182
  {% endif %}
 
190
  }
191
  {% endif %}
192
 
193
+ {% if rmsChainNorm %}
194
+ var acc2 = 0.0;
195
+ {% endif %}
196
+ {% if vec4 %}
197
  for (var i = tid; i < HIDDEN_V; i = i + WG) {
198
+ {% if packedBf16Embedding %}
199
+ let idx = base + i;
200
+ let v = embedding_vec4(source_row, i);
201
+ {% elif scalarIo %}
202
+ let idx = base + i * 4u;
203
+ let v = load_vec4(idx);
204
+ {% else %}
205
  let idx = base + i;
206
  let v = vec4<f32>(x[idx]);
207
+ {% endif %}
208
+ {% if rmsScaleAfterCast %}
209
+ y[idx] = {{ vecType }}(v * inv) * {{ vecType }}({{ rmsScaleVec }});
210
+ {% elif rmsChainNorm %}
211
+ // fma(a, b, 0.0) rounds the weighted product exactly as the decomposed pair's store does,
212
+ // and prevents the compiler from re-contracting it into the residual add.
213
+ let hv = y[idx] + fma(v * inv, {{ rmsScaleVec }}, vec4<f32>(0.0));
214
+ y[idx] = hv;
215
+ acc2 = acc2 + dot(hv, hv);
216
+ {% elif rmsResidualAdd %}
217
+ // See the chained branch: fma(a, b, 0.0) pins the pre-add rounding of the decomposed pair.
218
+ y[idx] = y[idx] + fma(v * inv, {{ rmsScaleVec }}, vec4<f32>(0.0));
219
+ {% else %}
220
+ y[idx] = {{ vecType }}(v * inv * {{ rmsScaleVec }});
221
+ {% endif %}
222
  }
223
+ {% if rmsChainNorm %}
224
+
225
+ // The chained second norm reads the residual row this loop just stored. This
226
+ // barrier completes those stores and any preceding shared-scratch use before
227
+ // the next reduction reuses its scratch; each lane then re-reads only the
228
+ // elements it wrote itself.
229
+ workgroupBarrier();
230
+ let total2 = reduce_scalar(acc2{{ reduceThreadArguments }});
231
+ let inv2 = inverseSqrt(total2 / f32(HIDDEN) + EPSILON2);
232
+ for (var i = tid; i < HIDDEN_V; i = i + WG) {
233
+ let idx = base + i;
234
+ let hv = vec4<f32>(y[idx]);
235
+ normed2[idx] = {{ vecType }}(hv * inv2 * vec4<f32>(scale2[i]));
236
+ }
237
+ {% endif %}
238
  {% else %}
239
  for (var i = tid; i < HIDDEN; i = i + WG) {
240
  let idx = base + i;
241
+ {% if packedBf16Embedding %}
242
+ let v = embedding_scalar(source_row, i);
243
+ {% else %}
244
  let v = f32(x[idx]);
245
+ {% endif %}
246
+ {% if rmsScaleAfterCast %}
247
+ y[idx] = {{ scalar }}(v * inv) * {{ scalar }}({{ rmsScaleScalar }});
248
+ {% else %}
249
+ y[idx] = {{ scalar }}(v * inv * {{ rmsScaleScalar }});
250
+ {% endif %}
251
  }
252
  {% endif %}
253
  }
build/webgpu/rms-normalization-splitk-normalize.wgsl.jinja CHANGED
@@ -1,11 +1,7 @@
1
- // Split-K normalize pass. Each workgroup (row = wg.x, split index = wg.z)
2
- // folds the SPLIT per-row partial sums of squares into the RMS scale, then
3
- // normalizes its HIDDEN/SPLIT slice. SPLIT is small (<=64), so the serial fold
4
- // avoids a third combine pass. Scale offsets follow the suffix-axis broadcast
5
- // contract.
6
- {% if usesF16 %}
7
- enable f16;
8
- {% endif %}
9
  {{ env.wgsl.resourceDeclarations }}
10
 
11
  const HIDDEN: u32 = {{ hiddenSize }}u;
@@ -13,11 +9,11 @@ const EPSILON: f32 = {{ epsilon }};
13
  const WG: u32 = {{ workgroupSize }}u;
14
  const SPLIT: u32 = {{ split }}u;
15
 
16
- {% if source.scaleRank > 0 %}
17
- const X_RANK: u32 = {{ source.xRank }}u;
18
- const SCALE_RANK: u32 = {{ source.scaleRank }}u;
19
- const X_SHAPE: array<u32, {{ source.xRank }}> = array<u32, {{ source.xRank }}>({% for d in source.xShape %}{{ d }}u{% if not loop.last %}, {% endif %}{% endfor %});
20
- const SCALE_SHAPE: array<u32, {{ source.scaleRank }}> = array<u32, {{ source.scaleRank }}>({% for d in source.scaleShape %}{{ d }}u{% if not loop.last %}, {% endif %}{% endfor %});
21
 
22
  fn x_stride(axis: u32) -> u32 {
23
  var stride = 1u;
@@ -36,8 +32,8 @@ fn scale_stride(axis: u32) -> u32 {
36
  }
37
 
38
  {% endif %}
39
- fn scale_offset({% if source.scaleRank > 0 %}out_index: u32{% endif %}) -> u32 {
40
- {% if source.scaleRank == 0 %}
41
  return 0u;
42
  {% else %}
43
  var rem = out_index;
@@ -59,6 +55,8 @@ fn scale_offset({% if source.scaleRank > 0 %}out_index: u32{% endif %}) -> u32 {
59
  }
60
 
61
 
 
 
62
  @compute @workgroup_size(WG, 1, 1)
63
  fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
64
  let row = wg.x + wg.y * params.rowStride;
@@ -68,12 +66,16 @@ fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) lid:
68
  let k = wg.z;
69
  let tid = lid.x;
70
 
71
- var total = 0.0;
72
- for (var i = 0u; i < SPLIT; i = i + 1u) {
73
- total = total + partials[row * SPLIT + i];
 
 
 
74
  }
75
- let inv = inverseSqrt(total / f32(HIDDEN) + EPSILON);
76
- {% if source.writeStats %}
 
77
  // Every split workgroup folds the same partials, so one designated
78
  // workgroup writes the row statistic.
79
  if (k == 0u && tid == 0u) {
@@ -81,7 +83,7 @@ fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) lid:
81
  }
82
 
83
  {% endif %}
84
- let chunk = (HIDDEN + SPLIT - 1u) / SPLIT;
85
  let start = k * chunk;
86
  var end = start + chunk;
87
  if (end > HIDDEN) { end = HIDDEN; }
@@ -91,7 +93,7 @@ fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) lid:
91
  loop {
92
  if (d >= end) { break; }
93
  let index = base + d;
94
- let value = f32(x[index]) * inv * f32(scale[scale_offset({% if source.scaleRank > 0 %}index{% endif %})]);
95
  y[index] = {{ scalar }}(value);
96
  d = d + WG;
97
  }
 
1
+ // Split-K normalize pass. One lane folds the per-row partials in their original
2
+ // order and shares the inverse RMS with its workgroup. Output tiles can outnumber
3
+ // the reduction splits: their independent work does not need additional scratch.
4
+ // Scale offsets follow the suffix-axis broadcast contract.
 
 
 
 
5
  {{ env.wgsl.resourceDeclarations }}
6
 
7
  const HIDDEN: u32 = {{ hiddenSize }}u;
 
9
  const WG: u32 = {{ workgroupSize }}u;
10
  const SPLIT: u32 = {{ split }}u;
11
 
12
+ {% if scaleRank > 0 %}
13
+ const X_RANK: u32 = {{ xRank }}u;
14
+ const SCALE_RANK: u32 = {{ scaleRank }}u;
15
+ const X_SHAPE: array<u32, {{ xRank }}> = array<u32, {{ xRank }}>({% for d in xShape %}{{ d }}u{% if not loop.last %}, {% endif %}{% endfor %});
16
+ const SCALE_SHAPE: array<u32, {{ scaleRank }}> = array<u32, {{ scaleRank }}>({% for d in scaleShape %}{{ d }}u{% if not loop.last %}, {% endif %}{% endfor %});
17
 
18
  fn x_stride(axis: u32) -> u32 {
19
  var stride = 1u;
 
32
  }
33
 
34
  {% endif %}
35
+ fn scale_offset({% if scaleRank > 0 %}out_index: u32{% endif %}) -> u32 {
36
+ {% if scaleRank == 0 %}
37
  return 0u;
38
  {% else %}
39
  var rem = out_index;
 
55
  }
56
 
57
 
58
+ var<workgroup> shared_inv: f32;
59
+
60
  @compute @workgroup_size(WG, 1, 1)
61
  fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
62
  let row = wg.x + wg.y * params.rowStride;
 
66
  let k = wg.z;
67
  let tid = lid.x;
68
 
69
+ if (tid == 0u) {
70
+ var total = 0.0;
71
+ for (var i = 0u; i < SPLIT; i = i + 1u) {
72
+ total = total + partials[row * SPLIT + i];
73
+ }
74
+ shared_inv = inverseSqrt(total / f32(HIDDEN) + EPSILON);
75
  }
76
+ workgroupBarrier();
77
+ let inv = shared_inv;
78
+ {% if writeStats %}
79
  // Every split workgroup folds the same partials, so one designated
80
  // workgroup writes the row statistic.
81
  if (k == 0u && tid == 0u) {
 
83
  }
84
 
85
  {% endif %}
86
+ let chunk = {{ normalizeChunk }}u;
87
  let start = k * chunk;
88
  var end = start + chunk;
89
  if (end > HIDDEN) { end = HIDDEN; }
 
93
  loop {
94
  if (d >= end) { break; }
95
  let index = base + d;
96
+ let value = f32(x[index]) * inv * f32(scale[scale_offset({% if scaleRank > 0 %}index{% endif %})]);
97
  y[index] = {{ scalar }}(value);
98
  d = d + WG;
99
  }
build/webgpu/rms-normalization-splitk-partials.wgsl.jinja CHANGED
@@ -51,9 +51,6 @@
51
  sum-of-squares over its HIDDEN/SPLIT slice and writes one partial to scratch.
52
  The normalize pass folds the SPLIT partials per row. Split-K reassociates the
53
  f32 sum, so this route is not bit-identical to the unsplit reduction. */
54
- {% if usesF16 %}
55
- enable f16;
56
- {% endif %}
57
  {{ env.wgsl.resourceDeclarations }}
58
 
59
  const HIDDEN: u32 = {{ hiddenSize }}u;
 
51
  sum-of-squares over its HIDDEN/SPLIT slice and writes one partial to scratch.
52
  The normalize pass folds the SPLIT partials per row. Split-K reassociates the
53
  f32 sum, so this route is not bit-identical to the unsplit reduction. */
 
 
 
54
  {{ env.wgsl.resourceDeclarations }}
55
 
56
  const HIDDEN: u32 = {{ hiddenSize }}u;
build/webgpu/rms-normalization.wgsl.jinja CHANGED
@@ -1,6 +1,3 @@
1
- {% if usesF16 %}
2
- enable f16;
3
- {% endif %}
4
  {{ env.wgsl.resourceDeclarations }}
5
 
6
  const HIDDEN: u32 = {{ hiddenSize }}u;
@@ -9,11 +6,11 @@ const WG: u32 = {{ workgroupSize }}u;
9
 
10
  var<workgroup> partial: array<f32, WG>;
11
 
12
- {% if source.scaleRank > 0 %}
13
- const X_RANK: u32 = {{ source.xRank }}u;
14
- const SCALE_RANK: u32 = {{ source.scaleRank }}u;
15
- const X_SHAPE: array<u32, {{ source.xRank }}> = array<u32, {{ source.xRank }}>({% for d in source.xShape %}{{ d }}u{% if not loop.last %}, {% endif %}{% endfor %});
16
- const SCALE_SHAPE: array<u32, {{ source.scaleRank }}> = array<u32, {{ source.scaleRank }}>({% for d in source.scaleShape %}{{ d }}u{% if not loop.last %}, {% endif %}{% endfor %});
17
 
18
  fn x_stride(axis: u32) -> u32 {
19
  var stride = 1u;
@@ -32,8 +29,8 @@ fn scale_stride(axis: u32) -> u32 {
32
  }
33
 
34
  {% endif %}
35
- fn scale_offset({% if source.scaleRank > 0 %}out_index: u32{% endif %}) -> u32 {
36
- {% if source.scaleRank == 0 %}
37
  return 0u;
38
  {% else %}
39
  var rem = out_index;
@@ -133,7 +130,7 @@ fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) lid:
133
  local_sq = local_sq + value * value;
134
  }
135
  let inv = inverseSqrt(reduce_sum(local_sq, tid) / f32(HIDDEN) + EPSILON);
136
- {% if source.writeStats %}
137
  if (tid == 0u) {
138
  inv_std_out[row] = inv;
139
  }
@@ -141,7 +138,7 @@ fn main(@builtin(workgroup_id) wg: vec3<u32>, @builtin(local_invocation_id) lid:
141
  {% endif %}
142
  for (var d = tid; d < HIDDEN; d = d + WG) {
143
  let index = base + d;
144
- let value = f32(x[index]) * inv * f32(scale[scale_offset({% if source.scaleRank > 0 %}index{% endif %})]);
145
  y[base + d] = {{ scalar }}(value);
146
  }
147
  }
 
 
 
 
1
  {{ env.wgsl.resourceDeclarations }}
2
 
3
  const HIDDEN: u32 = {{ hiddenSize }}u;
 
6
 
7
  var<workgroup> partial: array<f32, WG>;
8
 
9
+ {% if scaleRank > 0 %}
10
+ const X_RANK: u32 = {{ xRank }}u;
11
+ const SCALE_RANK: u32 = {{ scaleRank }}u;
12
+ const X_SHAPE: array<u32, {{ xRank }}> = array<u32, {{ xRank }}>({% for d in xShape %}{{ d }}u{% if not loop.last %}, {% endif %}{% endfor %});
13
+ const SCALE_SHAPE: array<u32, {{ scaleRank }}> = array<u32, {{ scaleRank }}>({% for d in scaleShape %}{{ d }}u{% if not loop.last %}, {% endif %}{% endfor %});
14
 
15
  fn x_stride(axis: u32) -> u32 {
16
  var stride = 1u;
 
29
  }
30
 
31
  {% endif %}
32
+ fn scale_offset({% if scaleRank > 0 %}out_index: u32{% endif %}) -> u32 {
33
+ {% if scaleRank == 0 %}
34
  return 0u;
35
  {% else %}
36
  var rem = out_index;
 
130
  local_sq = local_sq + value * value;
131
  }
132
  let inv = inverseSqrt(reduce_sum(local_sq, tid) / f32(HIDDEN) + EPSILON);
133
+ {% if writeStats %}
134
  if (tid == 0u) {
135
  inv_std_out[row] = inv;
136
  }
 
138
  {% endif %}
139
  for (var d = tid; d < HIDDEN; d = d + WG) {
140
  let index = base + d;
141
+ let value = f32(x[index]) * inv * f32(scale[scale_offset({% if scaleRank > 0 %}index{% endif %})]);
142
  y[base + d] = {{ scalar }}(value);
143
  }
144
  }
build/webgpu/test.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "ai.onnx.SimplifiedLayerNormalization",
3
  "fixtureArrays": {
4
  "f16_scalar_cast_x": [-1.1103515625, 2.982421875, 1.248046875, -1.8544921875],
5
  "f16_scalar_cast_scale": [2.015625],
@@ -259,7 +258,7 @@
259
  "provenance": {
260
  "source": "onnxruntime/core/providers/cpu/nn/layer_norm_impl.cc",
261
  "test": "SimplifiedLayerNormalization scalar-scale cast boundary",
262
- "notes": "A scalar scale forces the generic shared template and pins the same legacy cast ordering independently of the optimized row path."
263
  },
264
  "requires": { "features": ["shader-f16"] },
265
  "attrs": { "epsilon": 0.00001, "axis": -1 },
@@ -383,6 +382,718 @@
383
  "y": { "dtype": "float32", "shape": [0, 4], "tolerance": 0.000002 },
384
  "invStdVar": { "dtype": "float32", "shape": [0, 1], "tolerance": 0.00001 }
385
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
  }
387
  ]
388
  }
 
1
  {
 
2
  "fixtureArrays": {
3
  "f16_scalar_cast_x": [-1.1103515625, 2.982421875, 1.248046875, -1.8544921875],
4
  "f16_scalar_cast_scale": [2.015625],
 
258
  "provenance": {
259
  "source": "onnxruntime/core/providers/cpu/nn/layer_norm_impl.cc",
260
  "test": "SimplifiedLayerNormalization scalar-scale cast boundary",
261
+ "notes": "A scalar scale selects the generic path and requires multiplication before the final float16 cast, independently of optimized row handling."
262
  },
263
  "requires": { "features": ["shader-f16"] },
264
  "attrs": { "epsilon": 0.00001, "axis": -1 },
 
382
  "y": { "dtype": "float32", "shape": [0, 4], "tolerance": 0.000002 },
383
  "invStdVar": { "dtype": "float32", "shape": [0, 1], "tolerance": 0.00001 }
384
  }
385
+ },
386
+ {
387
+ "name": "split_f32-1x16384",
388
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
389
+ "tunables": {},
390
+ "inputs": {
391
+ "x": {
392
+ "dtype": "float32",
393
+ "shape": [1, 16384],
394
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
395
+ },
396
+ "scale": {
397
+ "dtype": "float32",
398
+ "shape": [],
399
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
400
+ }
401
+ },
402
+ "outputs": {
403
+ "y": { "shape": [1, 16384], "dtype": "float32", "tolerance": 0.00001 },
404
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
405
+ }
406
+ },
407
+ {
408
+ "name": "split_f32-1x16385",
409
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
410
+ "tunables": {},
411
+ "inputs": {
412
+ "x": {
413
+ "dtype": "float32",
414
+ "shape": [1, 16385],
415
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
416
+ },
417
+ "scale": {
418
+ "dtype": "float32",
419
+ "shape": [],
420
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
421
+ }
422
+ },
423
+ "outputs": {
424
+ "y": { "shape": [1, 16385], "dtype": "float32", "tolerance": 0.00001 },
425
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
426
+ }
427
+ },
428
+ {
429
+ "name": "split_f32-1x32769",
430
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
431
+ "tunables": {},
432
+ "inputs": {
433
+ "x": {
434
+ "dtype": "float32",
435
+ "shape": [1, 32769],
436
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
437
+ },
438
+ "scale": {
439
+ "dtype": "float32",
440
+ "shape": [],
441
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
442
+ }
443
+ },
444
+ "outputs": {
445
+ "y": { "shape": [1, 32769], "dtype": "float32", "tolerance": 0.00001 },
446
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
447
+ }
448
+ },
449
+ {
450
+ "name": "split_f32-1x65536",
451
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
452
+ "tunables": {},
453
+ "inputs": {
454
+ "x": {
455
+ "dtype": "float32",
456
+ "shape": [1, 65536],
457
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
458
+ },
459
+ "scale": {
460
+ "dtype": "float32",
461
+ "shape": [],
462
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
463
+ }
464
+ },
465
+ "outputs": {
466
+ "y": { "shape": [1, 65536], "dtype": "float32", "tolerance": 0.00001 },
467
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
468
+ }
469
+ },
470
+ {
471
+ "name": "split_f32-1x131072",
472
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
473
+ "tunables": {},
474
+ "inputs": {
475
+ "x": {
476
+ "dtype": "float32",
477
+ "shape": [1, 131072],
478
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
479
+ },
480
+ "scale": {
481
+ "dtype": "float32",
482
+ "shape": [],
483
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
484
+ }
485
+ },
486
+ "outputs": {
487
+ "y": { "shape": [1, 131072], "dtype": "float32", "tolerance": 0.00001 },
488
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
489
+ }
490
+ },
491
+ {
492
+ "name": "split_f32-1x262144",
493
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
494
+ "tunables": {},
495
+ "inputs": {
496
+ "x": {
497
+ "dtype": "float32",
498
+ "shape": [1, 262144],
499
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
500
+ },
501
+ "scale": {
502
+ "dtype": "float32",
503
+ "shape": [],
504
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
505
+ }
506
+ },
507
+ "outputs": {
508
+ "y": { "shape": [1, 262144], "dtype": "float32", "tolerance": 0.00001 },
509
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
510
+ }
511
+ },
512
+ {
513
+ "name": "split_f32-1x524288",
514
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
515
+ "tunables": {},
516
+ "inputs": {
517
+ "x": {
518
+ "dtype": "float32",
519
+ "shape": [1, 524288],
520
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
521
+ },
522
+ "scale": {
523
+ "dtype": "float32",
524
+ "shape": [],
525
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
526
+ }
527
+ },
528
+ "outputs": {
529
+ "y": { "shape": [1, 524288], "dtype": "float32", "tolerance": 0.00001 },
530
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
531
+ }
532
+ },
533
+ {
534
+ "name": "split_f32-1x1048576",
535
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
536
+ "tunables": {},
537
+ "inputs": {
538
+ "x": {
539
+ "dtype": "float32",
540
+ "shape": [1, 1048576],
541
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
542
+ },
543
+ "scale": {
544
+ "dtype": "float32",
545
+ "shape": [],
546
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
547
+ }
548
+ },
549
+ "outputs": {
550
+ "y": { "shape": [1, 1048576], "dtype": "float32", "tolerance": 0.00001 },
551
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
552
+ }
553
+ },
554
+ {
555
+ "name": "split_f32-1x2097152",
556
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
557
+ "tunables": {},
558
+ "inputs": {
559
+ "x": {
560
+ "dtype": "float32",
561
+ "shape": [1, 2097152],
562
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
563
+ },
564
+ "scale": {
565
+ "dtype": "float32",
566
+ "shape": [],
567
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
568
+ }
569
+ },
570
+ "outputs": {
571
+ "y": { "shape": [1, 2097152], "dtype": "float32", "tolerance": 0.00001 },
572
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
573
+ }
574
+ },
575
+ {
576
+ "name": "split_f32-2x131073",
577
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
578
+ "tunables": {},
579
+ "inputs": {
580
+ "x": {
581
+ "dtype": "float32",
582
+ "shape": [2, 131073],
583
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
584
+ },
585
+ "scale": {
586
+ "dtype": "float32",
587
+ "shape": [],
588
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
589
+ }
590
+ },
591
+ "outputs": {
592
+ "y": { "shape": [2, 131073], "dtype": "float32", "tolerance": 0.00001 },
593
+ "invStdVar": { "shape": [2, 1], "dtype": "float32", "tolerance": 0.00001 }
594
+ }
595
+ },
596
+ {
597
+ "name": "split_f32-3x524289",
598
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
599
+ "tunables": {},
600
+ "inputs": {
601
+ "x": {
602
+ "dtype": "float32",
603
+ "shape": [3, 524289],
604
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
605
+ },
606
+ "scale": {
607
+ "dtype": "float32",
608
+ "shape": [],
609
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
610
+ }
611
+ },
612
+ "outputs": {
613
+ "y": { "shape": [3, 524289], "dtype": "float32", "tolerance": 0.00001 },
614
+ "invStdVar": { "shape": [3, 1], "dtype": "float32", "tolerance": 0.00001 }
615
+ }
616
+ },
617
+ {
618
+ "name": "split_f32-4x1048576",
619
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
620
+ "tunables": {},
621
+ "inputs": {
622
+ "x": {
623
+ "dtype": "float32",
624
+ "shape": [4, 1048576],
625
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
626
+ },
627
+ "scale": {
628
+ "dtype": "float32",
629
+ "shape": [],
630
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
631
+ }
632
+ },
633
+ "outputs": {
634
+ "y": { "shape": [4, 1048576], "dtype": "float32", "tolerance": 0.00001 },
635
+ "invStdVar": { "shape": [4, 1], "dtype": "float32", "tolerance": 0.00001 }
636
+ }
637
+ },
638
+ {
639
+ "name": "split_f32-8x16384",
640
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
641
+ "tunables": {},
642
+ "inputs": {
643
+ "x": {
644
+ "dtype": "float32",
645
+ "shape": [8, 16384],
646
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
647
+ },
648
+ "scale": {
649
+ "dtype": "float32",
650
+ "shape": [],
651
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
652
+ }
653
+ },
654
+ "outputs": {
655
+ "y": { "shape": [8, 16384], "dtype": "float32", "tolerance": 0.00001 },
656
+ "invStdVar": { "shape": [8, 1], "dtype": "float32", "tolerance": 0.00001 }
657
+ }
658
+ },
659
+ {
660
+ "name": "split_f32-16x65536",
661
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
662
+ "tunables": {},
663
+ "inputs": {
664
+ "x": {
665
+ "dtype": "float32",
666
+ "shape": [16, 65536],
667
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
668
+ },
669
+ "scale": {
670
+ "dtype": "float32",
671
+ "shape": [],
672
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
673
+ }
674
+ },
675
+ "outputs": {
676
+ "y": { "shape": [16, 65536], "dtype": "float32", "tolerance": 0.00001 },
677
+ "invStdVar": { "shape": [16, 1], "dtype": "float32", "tolerance": 0.00001 }
678
+ }
679
+ },
680
+ {
681
+ "name": "split_f32-32x32769",
682
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
683
+ "tunables": {},
684
+ "inputs": {
685
+ "x": {
686
+ "dtype": "float32",
687
+ "shape": [32, 32769],
688
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
689
+ },
690
+ "scale": {
691
+ "dtype": "float32",
692
+ "shape": [],
693
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
694
+ }
695
+ },
696
+ "outputs": {
697
+ "y": { "shape": [32, 32769], "dtype": "float32", "tolerance": 0.00001 },
698
+ "invStdVar": { "shape": [32, 1], "dtype": "float32", "tolerance": 0.00001 }
699
+ }
700
+ },
701
+ {
702
+ "name": "split_f32-128x16384",
703
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
704
+ "tunables": {},
705
+ "inputs": {
706
+ "x": {
707
+ "dtype": "float32",
708
+ "shape": [128, 16384],
709
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
710
+ },
711
+ "scale": {
712
+ "dtype": "float32",
713
+ "shape": [],
714
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
715
+ }
716
+ },
717
+ "outputs": {
718
+ "y": { "shape": [128, 16384], "dtype": "float32", "tolerance": 0.00001 },
719
+ "invStdVar": { "shape": [128, 1], "dtype": "float32", "tolerance": 0.00001 }
720
+ }
721
+ },
722
+ {
723
+ "name": "split_f16-1x16385",
724
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
725
+ "tunables": {},
726
+ "inputs": {
727
+ "x": {
728
+ "dtype": "float16",
729
+ "shape": [1, 16385],
730
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
731
+ },
732
+ "scale": {
733
+ "dtype": "float16",
734
+ "shape": [],
735
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
736
+ }
737
+ },
738
+ "outputs": {
739
+ "y": { "shape": [1, 16385], "dtype": "float16", "tolerance": 0.01 },
740
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
741
+ }
742
+ },
743
+ {
744
+ "name": "split_f16-1x131072",
745
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
746
+ "tunables": {},
747
+ "inputs": {
748
+ "x": {
749
+ "dtype": "float16",
750
+ "shape": [1, 131072],
751
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
752
+ },
753
+ "scale": {
754
+ "dtype": "float16",
755
+ "shape": [],
756
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
757
+ }
758
+ },
759
+ "outputs": {
760
+ "y": { "shape": [1, 131072], "dtype": "float16", "tolerance": 0.01 },
761
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
762
+ }
763
+ },
764
+ {
765
+ "name": "split_f16-1x524288",
766
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
767
+ "tunables": {},
768
+ "inputs": {
769
+ "x": {
770
+ "dtype": "float16",
771
+ "shape": [1, 524288],
772
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
773
+ },
774
+ "scale": {
775
+ "dtype": "float16",
776
+ "shape": [],
777
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
778
+ }
779
+ },
780
+ "outputs": {
781
+ "y": { "shape": [1, 524288], "dtype": "float16", "tolerance": 0.01 },
782
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
783
+ }
784
+ },
785
+ {
786
+ "name": "split_f16-1x2097152",
787
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
788
+ "tunables": {},
789
+ "inputs": {
790
+ "x": {
791
+ "dtype": "float16",
792
+ "shape": [1, 2097152],
793
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
794
+ },
795
+ "scale": {
796
+ "dtype": "float16",
797
+ "shape": [],
798
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
799
+ }
800
+ },
801
+ "outputs": {
802
+ "y": { "shape": [1, 2097152], "dtype": "float16", "tolerance": 0.01 },
803
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
804
+ }
805
+ },
806
+ {
807
+ "name": "split_f16-3x524289",
808
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
809
+ "tunables": {},
810
+ "inputs": {
811
+ "x": {
812
+ "dtype": "float16",
813
+ "shape": [3, 524289],
814
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
815
+ },
816
+ "scale": {
817
+ "dtype": "float16",
818
+ "shape": [],
819
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
820
+ }
821
+ },
822
+ "outputs": {
823
+ "y": { "shape": [3, 524289], "dtype": "float16", "tolerance": 0.01 },
824
+ "invStdVar": { "shape": [3, 1], "dtype": "float32", "tolerance": 0.00001 }
825
+ }
826
+ },
827
+ {
828
+ "name": "split_f16-16x65536",
829
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
830
+ "tunables": {},
831
+ "inputs": {
832
+ "x": {
833
+ "dtype": "float16",
834
+ "shape": [16, 65536],
835
+ "data": { "kind": "fillFloat32", "sinStep": 0.000021, "cosStep": 0.000037, "scale": 0.5 }
836
+ },
837
+ "scale": {
838
+ "dtype": "float16",
839
+ "shape": [],
840
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
841
+ }
842
+ },
843
+ "outputs": {
844
+ "y": { "shape": [16, 65536], "dtype": "float16", "tolerance": 0.01 },
845
+ "invStdVar": { "shape": [16, 1], "dtype": "float32", "tolerance": 0.00001 }
846
+ }
847
+ },
848
+ {
849
+ "name": "split_f32-f16-2x32769",
850
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
851
+ "tunables": {},
852
+ "inputs": {
853
+ "x": {
854
+ "dtype": "float32",
855
+ "shape": [2, 32769],
856
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
857
+ },
858
+ "scale": {
859
+ "dtype": "float16",
860
+ "shape": [],
861
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
862
+ }
863
+ },
864
+ "outputs": {
865
+ "y": { "shape": [2, 32769], "dtype": "float16", "tolerance": 0.01 },
866
+ "invStdVar": { "shape": [2, 1], "dtype": "float32", "tolerance": 0.00001 }
867
+ }
868
+ },
869
+ {
870
+ "name": "split_f16-f32-2x32769",
871
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
872
+ "tunables": {},
873
+ "inputs": {
874
+ "x": {
875
+ "dtype": "float16",
876
+ "shape": [2, 32769],
877
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
878
+ },
879
+ "scale": {
880
+ "dtype": "float32",
881
+ "shape": [],
882
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
883
+ }
884
+ },
885
+ "outputs": {
886
+ "y": { "shape": [2, 32769], "dtype": "float32", "tolerance": 0.00001 },
887
+ "invStdVar": { "shape": [2, 1], "dtype": "float32", "tolerance": 0.00001 }
888
+ }
889
+ },
890
+ {
891
+ "name": "split_f32-1x16384-split1",
892
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
893
+ "tunables": { "MAX_SPLITS": 1 },
894
+ "inputs": {
895
+ "x": {
896
+ "dtype": "float32",
897
+ "shape": [1, 16384],
898
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
899
+ },
900
+ "scale": {
901
+ "dtype": "float32",
902
+ "shape": [],
903
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
904
+ }
905
+ },
906
+ "outputs": {
907
+ "y": { "shape": [1, 16384], "dtype": "float32", "tolerance": 0.00001 },
908
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
909
+ }
910
+ },
911
+ {
912
+ "name": "split_f32-1x16385-split3",
913
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
914
+ "tunables": { "MAX_SPLITS": 3 },
915
+ "inputs": {
916
+ "x": {
917
+ "dtype": "float32",
918
+ "shape": [1, 16385],
919
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
920
+ },
921
+ "scale": {
922
+ "dtype": "float32",
923
+ "shape": [],
924
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
925
+ }
926
+ },
927
+ "outputs": {
928
+ "y": { "shape": [1, 16385], "dtype": "float32", "tolerance": 0.00001 },
929
+ "invStdVar": { "shape": [1, 1], "dtype": "float32", "tolerance": 0.00001 }
930
+ }
931
+ },
932
+ {
933
+ "name": "split_f32-2x262145-wg64",
934
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
935
+ "tunables": { "WORKGROUP_SIZE": 64 },
936
+ "inputs": {
937
+ "x": {
938
+ "dtype": "float32",
939
+ "shape": [2, 262145],
940
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
941
+ },
942
+ "scale": {
943
+ "dtype": "float32",
944
+ "shape": [],
945
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
946
+ }
947
+ },
948
+ "outputs": {
949
+ "y": { "shape": [2, 262145], "dtype": "float32", "tolerance": 0.00001 },
950
+ "invStdVar": { "shape": [2, 1], "dtype": "float32", "tolerance": 0.00001 }
951
+ }
952
+ },
953
+ {
954
+ "name": "split_f32-2x262145-wg128",
955
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
956
+ "tunables": { "WORKGROUP_SIZE": 128 },
957
+ "inputs": {
958
+ "x": {
959
+ "dtype": "float32",
960
+ "shape": [2, 262145],
961
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
962
+ },
963
+ "scale": {
964
+ "dtype": "float32",
965
+ "shape": [],
966
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
967
+ }
968
+ },
969
+ "outputs": {
970
+ "y": { "shape": [2, 262145], "dtype": "float32", "tolerance": 0.00001 },
971
+ "invStdVar": { "shape": [2, 1], "dtype": "float32", "tolerance": 0.00001 }
972
+ }
973
+ },
974
+ {
975
+ "name": "split_f32-1x524288-no-stats",
976
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
977
+ "tunables": {},
978
+ "inputs": {
979
+ "x": {
980
+ "dtype": "float32",
981
+ "shape": [1, 524288],
982
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
983
+ },
984
+ "scale": {
985
+ "dtype": "float32",
986
+ "shape": [],
987
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
988
+ }
989
+ },
990
+ "outputs": { "y": { "shape": [1, 524288], "dtype": "float32", "tolerance": 0.00001 } }
991
+ },
992
+ {
993
+ "name": "split_f32-1x2097152-no-stats",
994
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
995
+ "tunables": {},
996
+ "inputs": {
997
+ "x": {
998
+ "dtype": "float32",
999
+ "shape": [1, 2097152],
1000
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.023, "scale": 0.5, "offset": 0.0 }
1001
+ },
1002
+ "scale": {
1003
+ "dtype": "float32",
1004
+ "shape": [],
1005
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
1006
+ }
1007
+ },
1008
+ "outputs": { "y": { "shape": [1, 2097152], "dtype": "float32", "tolerance": 0.00001 } }
1009
+ },
1010
+ {
1011
+ "name": "split_f16-1x524288-no-stats",
1012
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
1013
+ "tunables": {},
1014
+ "inputs": {
1015
+ "x": {
1016
+ "dtype": "float16",
1017
+ "shape": [1, 524288],
1018
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
1019
+ },
1020
+ "scale": {
1021
+ "dtype": "float16",
1022
+ "shape": [],
1023
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
1024
+ }
1025
+ },
1026
+ "outputs": { "y": { "shape": [1, 524288], "dtype": "float16", "tolerance": 0.01 } }
1027
+ },
1028
+ {
1029
+ "name": "split_f16-1x2097152-no-stats",
1030
+ "attrs": { "axis": -1, "epsilon": 0.000001 },
1031
+ "tunables": {},
1032
+ "inputs": {
1033
+ "x": {
1034
+ "dtype": "float16",
1035
+ "shape": [1, 2097152],
1036
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
1037
+ },
1038
+ "scale": {
1039
+ "dtype": "float16",
1040
+ "shape": [],
1041
+ "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.009, "scale": 0.25, "offset": 1.0 }
1042
+ }
1043
+ },
1044
+ "outputs": { "y": { "shape": [1, 2097152], "dtype": "float16", "tolerance": 0.01 } }
1045
+ },
1046
+ {
1047
+ "name": "split_f32_suffix_broadcast_tail",
1048
+ "attrs": { "axis": 1, "epsilon": 0.000001 },
1049
+ "inputs": {
1050
+ "x": {
1051
+ "dtype": "float32",
1052
+ "shape": [3, 17, 4097],
1053
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
1054
+ },
1055
+ "scale": {
1056
+ "dtype": "float32",
1057
+ "shape": [1, 17, 1],
1058
+ "data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.09, "scale": 0.25, "offset": 1.0 }
1059
+ }
1060
+ },
1061
+ "outputs": {
1062
+ "y": { "dtype": "float32", "shape": [3, 17, 4097], "tolerance": 0.00001 },
1063
+ "invStdVar": { "dtype": "float32", "shape": [3, 1, 1], "tolerance": 0.00001 }
1064
+ }
1065
+ },
1066
+ {
1067
+ "name": "split_f16_suffix_broadcast_tail",
1068
+ "attrs": { "axis": 1, "epsilon": 0.000001 },
1069
+ "inputs": {
1070
+ "x": {
1071
+ "dtype": "float16",
1072
+ "shape": [3, 17, 4097],
1073
+ "data": { "kind": "cycle", "values": [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0] }
1074
+ },
1075
+ "scale": {
1076
+ "dtype": "float16",
1077
+ "shape": [1, 17, 1],
1078
+ "data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.09, "scale": 0.25, "offset": 1.0 }
1079
+ }
1080
+ },
1081
+ "outputs": {
1082
+ "y": { "dtype": "float16", "shape": [3, 17, 4097], "tolerance": 0.01 },
1083
+ "invStdVar": { "dtype": "float32", "shape": [3, 1, 1], "tolerance": 0.00001 }
1084
+ }
1085
+ },
1086
+ {
1087
+ "name": "split_empty_outer_long_suffix",
1088
+ "attrs": { "axis": 1 },
1089
+ "inputs": {
1090
+ "x": { "dtype": "float32", "shape": [0, 2, 16384], "data": { "kind": "values", "values": [] } },
1091
+ "scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [1.0] } }
1092
+ },
1093
+ "outputs": {
1094
+ "y": { "dtype": "float32", "shape": [0, 2, 16384], "tolerance": 0 },
1095
+ "invStdVar": { "dtype": "float32", "shape": [0, 1, 1], "tolerance": 0 }
1096
+ }
1097
  }
1098
  ]
1099
  }