Xenova HF Staff commited on
Commit
53a7bdc
·
verified ·
1 Parent(s): 0ef25e5

sync 2e7068faf55e

Browse files
README.md CHANGED
@@ -1,3 +1,78 @@
1
  ---
 
2
  license: apache-2.0
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ library_name: kernels
3
  license: apache-2.0
4
+ tags:
5
+ - kernel
6
+ - webgpu
7
+ - wgsl
8
  ---
9
+ # com.microsoft.CausalConvWithState
10
+
11
+ `com.microsoft` · ONNX Runtime contrib operator · contrib since_version 1
12
+
13
+ ## Description
14
+
15
+ Legacy Microsoft contrib form of stateful 1-D causal depthwise convolution. Each channel uses its own `(channels, 1, kernel)` weight over current and past positions, with optional activation and `past_state`/`present_state` tensors for incremental decoding. The contrib-only `state_window` attribute may retain several rollback states. This inference implementation preserves the existing contrib ABI with `ndim = 1`, float16 or float32 tensors, and float32 accumulation; spatial ranks 2 and 3 and bfloat16 are not implemented.
16
+
17
+ See the [ONNX Runtime `CausalConvWithState` contrib-operator spec](https://github.com/microsoft/onnxruntime/blob/main/docs/ContribOperators.md#com.microsoft.CausalConvWithState) for the reference semantics.
18
+
19
+ ## Inputs
20
+
21
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
22
+ | --- | --- | --- | --- | --- | --- | --- |
23
+ | `input` | `inputT` | `T` | `3` | — | Channels-first input tensor with shape `(batch_size, channels, sequence_length)` for the supported 1-D mode. | required |
24
+ | `weight` | `weightT` | `T` | `3` | — | Depthwise convolution kernel with shape `(channels, 1, kernel_size)` for the supported 1-D mode. | required |
25
+ | `bias` | `biasT` | `T` | `1` | — | Optional per-channel bias with shape `(channels,)`. | optional |
26
+ | `past_state` | `pastStateT` | `T` | derived | — | Carry state from the previous step; shape `(batch_size, channels, k_1 - 1)`, or `(W, batch_size, channels, k_1 - 1)` when `state_window = W > 0`, in which case only slot `W - 1` is read. If absent, the left-side padding is zero. | optional |
27
+
28
+ ## Outputs
29
+
30
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
31
+ | --- | --- | --- | --- | --- | --- | --- |
32
+ | `output` | `outputT` | `T` | `3` | same as `input` | Convolution output with the same shape as `input`. | required |
33
+ | `present_state` | `presentStateT` | `T` | derived | derived; see description | Updated carry state; shape `(batch_size, channels, k_1 - 1)`, or `(W, batch_size, channels, k_1 - 1)` when `state_window = W > 0`. Slot `W - 1` holds the last `k - 1` values along the causal axis; slot `j` holds the same for the prefix ending at position `seq_len - W + j`. | required |
34
+
35
+ ## Attributes
36
+
37
+ Default values (overridable per request):
38
+
39
+ | Attribute | Default | Description |
40
+ | --- | --- | --- |
41
+ | `activation` | `"none"` | Activation applied after convolution and bias. Defaults to `none`; `swish` is an alias of SiLU. |
42
+ | `ndim` | `1` | Number of spatial dimensions. This implementation supports the contrib 1D mode (`ndim = 1`). |
43
+ | `state_window` | `0` | Contrib extension selecting the number of rollback state slots to retain, in the range 0 through 8. Defaults to 0. |
44
+
45
+ ## Type constraints
46
+
47
+ | Variable | Allowed dtypes |
48
+ | --- | --- |
49
+ | `T` | `float32`, `float16` |
50
+
51
+ ## Files
52
+
53
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
54
+ - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
55
+ - [`test.json`](build/webgpu/test.json) — correctness cases
56
+ - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
57
+ - [`causal-conv-with-state-tiled.wgsl.jinja`](build/webgpu/causal-conv-with-state-tiled.wgsl.jinja)
58
+ - [`causal-conv-with-state-vec4.wgsl.jinja`](build/webgpu/causal-conv-with-state-vec4.wgsl.jinja)
59
+ - [`causal-conv-with-state.wgsl.jinja`](build/webgpu/causal-conv-with-state.wgsl.jinja)
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
+
70
+ ```js
71
+ import { getKernel } from "@huggingface/kernels";
72
+
73
+ const kernel = await getKernel("webgpu-kernels/com.microsoft.CausalConvWithState", { version: 1 });
74
+ const { outputT, presentStateT } = await kernel({
75
+ inputT: { data: inputTData, shape: [1, 1, 5] },
76
+ weightT: { data: weightTData, shape: [1, 1, 4] },
77
+ });
78
+ ```
build/webgpu/bench.json ADDED
@@ -0,0 +1,402 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "com.microsoft.CausalConvWithState",
3
+ "tunableSpace": { "workgroupSize": [64, 128, 256] },
4
+ "cases": [
5
+ {
6
+ "name": "causal-conv-f32-b2c32t256k4",
7
+ "preset": "smoke",
8
+ "vars": { "batch": 2, "channels": 32, "length": 256, "kernel": 4 },
9
+ "attrs": { "activation": "none" },
10
+ "inputs": {
11
+ "inputT": { "shape": [2, 32, 256], "dtype": "float32", "dist": "normal", "seed": 205, "scale": 0.2 },
12
+ "weightT": { "shape": [32, 1, 4], "dtype": "float32", "dist": "normal", "seed": 206, "scale": 0.1 }
13
+ },
14
+ "outputs": {
15
+ "outputT": { "shape": [2, 32, 256], "dtype": "float32" },
16
+ "presentStateT": { "shape": [2, 32, 3], "dtype": "float32" }
17
+ },
18
+ "bench": {
19
+ "primary": true,
20
+ "metrics": [
21
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 1)" },
22
+ {
23
+ "type": "bandwidth",
24
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
25
+ }
26
+ ]
27
+ }
28
+ },
29
+ {
30
+ "name": "causal-conv-f32-state-bias-silu-b2c32t256k4",
31
+ "preset": "smoke",
32
+ "vars": { "batch": 2, "channels": 32, "length": 256, "kernel": 4 },
33
+ "attrs": { "activation": "silu" },
34
+ "inputs": {
35
+ "inputT": { "shape": [2, 32, 256], "dtype": "float32", "dist": "normal", "seed": 206, "scale": 0.2 },
36
+ "weightT": { "shape": [32, 1, 4], "dtype": "float32", "dist": "normal", "seed": 207, "scale": 0.1 },
37
+ "biasT": { "shape": [32], "dtype": "float32", "dist": "normal", "seed": 208, "scale": 0.05 },
38
+ "pastStateT": { "shape": [2, 32, 3], "dtype": "float32", "dist": "normal", "seed": 209, "scale": 0.2 }
39
+ },
40
+ "outputs": {
41
+ "outputT": { "shape": [2, 32, 256], "dtype": "float32" },
42
+ "presentStateT": { "shape": [2, 32, 3], "dtype": "float32" }
43
+ },
44
+ "bench": {
45
+ "primary": true,
46
+ "metrics": [
47
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 1)" },
48
+ {
49
+ "type": "bandwidth",
50
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
51
+ }
52
+ ]
53
+ }
54
+ },
55
+ {
56
+ "name": "causal-conv-f32-large-kernel-prefill-b2c1024t512k128",
57
+ "preset": "stress",
58
+ "tunableSpace": { "tiledWorkgroupSize": [64, 128, 256] },
59
+ "vars": { "batch": 2, "channels": 1024, "length": 512, "kernel": 128 },
60
+ "attrs": { "activation": "none" },
61
+ "inputs": {
62
+ "inputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "normal", "seed": 301, "scale": 0.2 },
63
+ "weightT": { "shape": [1024, 1, 128], "dtype": "float32", "dist": "normal", "seed": 302, "scale": 0.05 }
64
+ },
65
+ "outputs": {
66
+ "outputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "empty" },
67
+ "presentStateT": { "shape": [2, 1024, 127], "dtype": "float32", "dist": "empty" }
68
+ },
69
+ "bench": {
70
+ "primary": true,
71
+ "metrics": [
72
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 1)" },
73
+ {
74
+ "type": "bandwidth",
75
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
76
+ }
77
+ ]
78
+ }
79
+ },
80
+ {
81
+ "name": "causal-conv-f32-large-kernel127-prefill-b2c1024t512-alignment-pathology",
82
+ "preset": "stress",
83
+ "provenance": {
84
+ "notes": "A realistic odd-width causal kernel adjacent to the K=128 tiled control. K=127 is valid but fails the tiled kernel's K % 4 contract and falls back to the scalar zero-state implementation."
85
+ },
86
+ "vars": { "batch": 2, "channels": 1024, "length": 512, "kernel": 127 },
87
+ "attrs": { "activation": "none" },
88
+ "inputs": {
89
+ "inputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "normal", "seed": 310, "scale": 0.2 },
90
+ "weightT": { "shape": [1024, 1, 127], "dtype": "float32", "dist": "normal", "seed": 311, "scale": 0.05 }
91
+ },
92
+ "outputs": {
93
+ "outputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "empty" },
94
+ "presentStateT": { "shape": [2, 1024, 126], "dtype": "float32", "dist": "empty" }
95
+ },
96
+ "bench": {
97
+ "metrics": [
98
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 1)" },
99
+ {
100
+ "type": "bandwidth",
101
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
102
+ }
103
+ ]
104
+ }
105
+ },
106
+ {
107
+ "name": "causal-conv-f32-bias-large-kernel-prefill-b2c1024t512k128-pathology",
108
+ "preset": "stress",
109
+ "tunableSpace": { "tiledWorkgroupSize": [64, 128, 256] },
110
+ "provenance": {
111
+ "notes": "Regression lock for the historical large-kernel bias cliff: this common per-channel bias path previously excluded the tiled specialization and selected the scalar kernel."
112
+ },
113
+ "vars": { "batch": 2, "channels": 1024, "length": 512, "kernel": 128 },
114
+ "attrs": { "activation": "silu" },
115
+ "inputs": {
116
+ "inputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "normal", "seed": 307, "scale": 0.2 },
117
+ "weightT": { "shape": [1024, 1, 128], "dtype": "float32", "dist": "normal", "seed": 308, "scale": 0.05 },
118
+ "biasT": { "shape": [1024], "dtype": "float32", "dist": "normal", "seed": 309, "scale": 0.05 }
119
+ },
120
+ "outputs": {
121
+ "outputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "empty" },
122
+ "presentStateT": { "shape": [2, 1024, 127], "dtype": "float32", "dist": "empty" }
123
+ },
124
+ "bench": {
125
+ "metrics": [
126
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 1)" },
127
+ {
128
+ "type": "bandwidth",
129
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
130
+ }
131
+ ]
132
+ }
133
+ },
134
+ {
135
+ "name": "causal-conv-f32-state-large-kernel-prefill-b2c1024t512k128-pathology",
136
+ "preset": "stress",
137
+ "tunableSpace": { "tiledWorkgroupSize": [64, 128, 256] },
138
+ "provenance": {
139
+ "notes": "Regression lock for the historical continuation cliff: valid carry state previously excluded the tiled specialization even without bias or activation."
140
+ },
141
+ "vars": { "batch": 2, "channels": 1024, "length": 512, "kernel": 128 },
142
+ "attrs": { "activation": "none" },
143
+ "inputs": {
144
+ "inputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "normal", "seed": 312, "scale": 0.2 },
145
+ "weightT": { "shape": [1024, 1, 128], "dtype": "float32", "dist": "normal", "seed": 313, "scale": 0.05 },
146
+ "pastStateT": { "shape": [2, 1024, 127], "dtype": "float32", "dist": "normal", "seed": 314, "scale": 0.2 }
147
+ },
148
+ "outputs": {
149
+ "outputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "empty" },
150
+ "presentStateT": { "shape": [2, 1024, 127], "dtype": "float32", "dist": "empty" }
151
+ },
152
+ "bench": {
153
+ "metrics": [
154
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 1)" },
155
+ {
156
+ "type": "bandwidth",
157
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
158
+ }
159
+ ]
160
+ }
161
+ },
162
+ {
163
+ "name": "causal-conv-f32-state-bias-large-kernel-prefill-b2c1024t512k128-pathology",
164
+ "preset": "stress",
165
+ "tunableSpace": { "tiledWorkgroupSize": [64, 128, 256] },
166
+ "provenance": {
167
+ "notes": "A realistic chunked continuation and regression lock: valid carry state plus bias previously excluded the tiled specialization and selected the scalar state+bias implementation."
168
+ },
169
+ "vars": { "batch": 2, "channels": 1024, "length": 512, "kernel": 128 },
170
+ "attrs": { "activation": "silu" },
171
+ "inputs": {
172
+ "inputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "normal", "seed": 303, "scale": 0.2 },
173
+ "weightT": { "shape": [1024, 1, 128], "dtype": "float32", "dist": "normal", "seed": 304, "scale": 0.05 },
174
+ "biasT": { "shape": [1024], "dtype": "float32", "dist": "normal", "seed": 305, "scale": 0.05 },
175
+ "pastStateT": { "shape": [2, 1024, 127], "dtype": "float32", "dist": "normal", "seed": 306, "scale": 0.2 }
176
+ },
177
+ "outputs": {
178
+ "outputT": { "shape": [2, 1024, 512], "dtype": "float32", "dist": "empty" },
179
+ "presentStateT": { "shape": [2, 1024, 127], "dtype": "float32", "dist": "empty" }
180
+ },
181
+ "bench": {
182
+ "metrics": [
183
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 1)" },
184
+ {
185
+ "type": "bandwidth",
186
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
187
+ }
188
+ ]
189
+ }
190
+ },
191
+ {
192
+ "name": "causal-conv-f32-huge-numel-fold-b2c4096t4096k4",
193
+ "preset": "stress",
194
+ "vars": { "batch": 2, "channels": 4096, "length": 4096, "kernel": 4 },
195
+ "attrs": { "activation": "none" },
196
+ "inputs": {
197
+ "inputT": { "shape": [2, 4096, 4096], "dtype": "float32", "dist": "normal", "seed": 311, "scale": 0.2 },
198
+ "weightT": { "shape": [4096, 1, 4], "dtype": "float32", "dist": "normal", "seed": 312, "scale": 0.1 }
199
+ },
200
+ "outputs": {
201
+ "outputT": { "shape": [2, 4096, 4096], "dtype": "float32", "dist": "empty" },
202
+ "presentStateT": { "shape": [2, 4096, 3], "dtype": "float32", "dist": "empty" }
203
+ },
204
+ "bench": {
205
+ "primary": true,
206
+ "metrics": [
207
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 1)" },
208
+ {
209
+ "type": "bandwidth",
210
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
211
+ }
212
+ ]
213
+ }
214
+ },
215
+ {
216
+ "name": "nemo-conv-decode-9728",
217
+ "preset": "smoke",
218
+ "attrs": { "activation": "silu" },
219
+ "inputs": {
220
+ "inputT": { "dtype": "float32", "shape": [1, 9728, 1] },
221
+ "weightT": { "dtype": "float32", "shape": [9728, 1, 4] },
222
+ "biasT": { "dtype": "float32", "shape": [9728] },
223
+ "pastStateT": { "dtype": "float32", "shape": [1, 9728, 3] }
224
+ },
225
+ "outputs": {
226
+ "outputT": { "dtype": "float32", "shape": [1, 9728, 1] },
227
+ "presentStateT": { "dtype": "float32", "shape": [1, 9728, 3] }
228
+ },
229
+ "bench": {
230
+ "metrics": [
231
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 1)" },
232
+ {
233
+ "type": "bandwidth",
234
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
235
+ }
236
+ ]
237
+ }
238
+ },
239
+ {
240
+ "name": "causal-conv-qwen3next-decode-b1-c8192-t1-k4",
241
+ "preset": "model",
242
+ "provenance": {
243
+ "notes": "Qwen3-Next class defaults (linear_conv_kernel_dim 4) over the concatenated q/k/v channels of the linear-attention branch (2*16*128 + 32*128 = 8192) at a decode step."
244
+ },
245
+ "vars": { "batch": 1, "channels": 8192, "length": 1, "kernel": 4 },
246
+ "attrs": { "activation": "silu" },
247
+ "inputs": {
248
+ "inputT": { "shape": [1, 8192, 1], "dtype": "float32", "dist": "normal", "seed": 8700, "scale": 0.5 },
249
+ "weightT": { "shape": [8192, 1, 4], "dtype": "float32", "dist": "normal", "seed": 8701, "scale": 0.3 },
250
+ "biasT": { "shape": [8192], "dtype": "float32", "dist": "normal", "seed": 8702, "scale": 0.1 },
251
+ "pastStateT": { "shape": [1, 8192, 3], "dtype": "float32", "dist": "normal", "seed": 8703, "scale": 0.2 }
252
+ },
253
+ "outputs": {
254
+ "outputT": { "shape": [1, 8192, 1], "dtype": "float32" },
255
+ "presentStateT": { "shape": [1, 8192, 3], "dtype": "float32" }
256
+ },
257
+ "bench": {
258
+ "metrics": [
259
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 2)" },
260
+ {
261
+ "type": "bandwidth",
262
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
263
+ }
264
+ ]
265
+ }
266
+ },
267
+ {
268
+ "name": "causal-conv-qwen3next-prefill-b1-c8192-t2048-k4",
269
+ "preset": "model",
270
+ "provenance": { "notes": "Qwen3-Next class defaults over a 2048-token prefill chunk." },
271
+ "vars": { "batch": 1, "channels": 8192, "length": 2048, "kernel": 4 },
272
+ "attrs": { "activation": "silu" },
273
+ "inputs": {
274
+ "inputT": { "shape": [1, 8192, 2048], "dtype": "float32", "dist": "normal", "seed": 8800, "scale": 0.5 },
275
+ "weightT": { "shape": [8192, 1, 4], "dtype": "float32", "dist": "normal", "seed": 8801, "scale": 0.3 },
276
+ "biasT": { "shape": [8192], "dtype": "float32", "dist": "normal", "seed": 8802, "scale": 0.1 },
277
+ "pastStateT": { "shape": [1, 8192, 3], "dtype": "float32", "dist": "normal", "seed": 8803, "scale": 0.2 }
278
+ },
279
+ "outputs": {
280
+ "outputT": { "shape": [1, 8192, 2048], "dtype": "float32" },
281
+ "presentStateT": { "shape": [1, 8192, 3], "dtype": "float32" }
282
+ },
283
+ "bench": {
284
+ "metrics": [
285
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 2)" },
286
+ {
287
+ "type": "bandwidth",
288
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
289
+ }
290
+ ]
291
+ }
292
+ },
293
+ {
294
+ "name": "causal-conv-mamba2-decode-b1-c10240-t1-k4",
295
+ "preset": "model",
296
+ "provenance": {
297
+ "notes": "Mamba2 class defaults (hidden_size 4096, expand 2, n_groups 8, state_size 128, conv_kernel 4): the mixer conv spans 2*4096 + 2*8*128 = 10240 channels."
298
+ },
299
+ "vars": { "batch": 1, "channels": 10240, "length": 1, "kernel": 4 },
300
+ "attrs": { "activation": "silu" },
301
+ "inputs": {
302
+ "inputT": { "shape": [1, 10240, 1], "dtype": "float32", "dist": "normal", "seed": 8900, "scale": 0.5 },
303
+ "weightT": { "shape": [10240, 1, 4], "dtype": "float32", "dist": "normal", "seed": 8901, "scale": 0.3 },
304
+ "biasT": { "shape": [10240], "dtype": "float32", "dist": "normal", "seed": 8902, "scale": 0.1 },
305
+ "pastStateT": { "shape": [1, 10240, 3], "dtype": "float32", "dist": "normal", "seed": 8903, "scale": 0.2 }
306
+ },
307
+ "outputs": {
308
+ "outputT": { "shape": [1, 10240, 1], "dtype": "float32" },
309
+ "presentStateT": { "shape": [1, 10240, 3], "dtype": "float32" }
310
+ },
311
+ "bench": {
312
+ "metrics": [
313
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 2)" },
314
+ {
315
+ "type": "bandwidth",
316
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
317
+ }
318
+ ]
319
+ }
320
+ },
321
+ {
322
+ "name": "causal-conv-mamba2-prefill-b1-c10240-t2048-k4",
323
+ "preset": "model",
324
+ "provenance": { "notes": "Mamba2 class defaults over a 2048-token prefill chunk." },
325
+ "vars": { "batch": 1, "channels": 10240, "length": 2048, "kernel": 4 },
326
+ "attrs": { "activation": "silu" },
327
+ "inputs": {
328
+ "inputT": { "shape": [1, 10240, 2048], "dtype": "float32", "dist": "normal", "seed": 9000, "scale": 0.5 },
329
+ "weightT": { "shape": [10240, 1, 4], "dtype": "float32", "dist": "normal", "seed": 9001, "scale": 0.3 },
330
+ "biasT": { "shape": [10240], "dtype": "float32", "dist": "normal", "seed": 9002, "scale": 0.1 },
331
+ "pastStateT": { "shape": [1, 10240, 3], "dtype": "float32", "dist": "normal", "seed": 9003, "scale": 0.2 }
332
+ },
333
+ "outputs": {
334
+ "outputT": { "shape": [1, 10240, 2048], "dtype": "float32" },
335
+ "presentStateT": { "shape": [1, 10240, 3], "dtype": "float32" }
336
+ },
337
+ "bench": {
338
+ "metrics": [
339
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 2)" },
340
+ {
341
+ "type": "bandwidth",
342
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
343
+ }
344
+ ]
345
+ }
346
+ },
347
+ {
348
+ "name": "causal-conv-lfm2-decode-b1-c2560-t1-k3",
349
+ "preset": "model",
350
+ "provenance": {
351
+ "notes": "LFM2 class defaults (hidden_size 2560, conv_L_cache 3): the short-conv block at a decode step, a kernel one tap narrower than the Mamba family."
352
+ },
353
+ "vars": { "batch": 1, "channels": 2560, "length": 1, "kernel": 3 },
354
+ "attrs": { "activation": "silu" },
355
+ "inputs": {
356
+ "inputT": { "shape": [1, 2560, 1], "dtype": "float32", "dist": "normal", "seed": 9100, "scale": 0.5 },
357
+ "weightT": { "shape": [2560, 1, 3], "dtype": "float32", "dist": "normal", "seed": 9101, "scale": 0.3 },
358
+ "biasT": { "shape": [2560], "dtype": "float32", "dist": "normal", "seed": 9102, "scale": 0.1 },
359
+ "pastStateT": { "shape": [1, 2560, 2], "dtype": "float32", "dist": "normal", "seed": 9103, "scale": 0.2 }
360
+ },
361
+ "outputs": {
362
+ "outputT": { "shape": [1, 2560, 1], "dtype": "float32" },
363
+ "presentStateT": { "shape": [1, 2560, 2], "dtype": "float32" }
364
+ },
365
+ "bench": {
366
+ "metrics": [
367
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 2)" },
368
+ {
369
+ "type": "bandwidth",
370
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
371
+ }
372
+ ]
373
+ }
374
+ },
375
+ {
376
+ "name": "causal-conv-lfm2-prefill-b1-c2560-t2048-k3",
377
+ "preset": "model",
378
+ "provenance": { "notes": "LFM2 class defaults over a 2048-token prefill chunk." },
379
+ "vars": { "batch": 1, "channels": 2560, "length": 2048, "kernel": 3 },
380
+ "attrs": { "activation": "silu" },
381
+ "inputs": {
382
+ "inputT": { "shape": [1, 2560, 2048], "dtype": "float32", "dist": "normal", "seed": 9200, "scale": 0.5 },
383
+ "weightT": { "shape": [2560, 1, 3], "dtype": "float32", "dist": "normal", "seed": 9201, "scale": 0.3 },
384
+ "biasT": { "shape": [2560], "dtype": "float32", "dist": "normal", "seed": 9202, "scale": 0.1 },
385
+ "pastStateT": { "shape": [1, 2560, 2], "dtype": "float32", "dist": "normal", "seed": 9203, "scale": 0.2 }
386
+ },
387
+ "outputs": {
388
+ "outputT": { "shape": [1, 2560, 2048], "dtype": "float32" },
389
+ "presentStateT": { "shape": [1, 2560, 2], "dtype": "float32" }
390
+ },
391
+ "bench": {
392
+ "metrics": [
393
+ { "type": "gflops", "value": "2 * numel(shapes.outputT) * dim(shapes.weightT, 2)" },
394
+ {
395
+ "type": "bandwidth",
396
+ "value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.biasT) + numel(shapes.pastStateT) + numel(shapes.outputT) + numel(shapes.presentStateT)) * 4"
397
+ }
398
+ ]
399
+ }
400
+ }
401
+ ]
402
+ }
build/webgpu/causal-conv-with-state-tiled.wgsl.jinja ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% set pastSlot = "(params.stateWindow - 1u) * params.stateSlotStride + " if hasStateWindow else "" %}
2
+ {% if usesF16 %}
3
+ enable f16;
4
+ {% endif -%}
5
+ {{ env.wgsl.resourceDeclarations }}
6
+
7
+ const WG: u32 = {{ workgroupSize }}u;
8
+ const TILE: u32 = {{ tileSize }}u;
9
+ const OUTPUTS_PER_THREAD: u32 = 8u;
10
+ const KERNEL_SIZE: u32 = {{ kernelSize }}u;
11
+ // The tap loop consumes four weights per iteration. Rounding the weight tile up
12
+ // to a multiple of four and zero-filling the tail lets a kernel of any length
13
+ // use it: the phantom taps contribute nothing. The input tile grows to match,
14
+ // because the last lane reads TILE + KERNEL_PADDED - 2.
15
+ const KERNEL_PADDED: u32 = {{ kernelSizePadded }}u;
16
+ const STATE_LENGTH: u32 = KERNEL_SIZE - 1u;
17
+ const INPUT_TILE_SIZE: u32 = TILE + KERNEL_PADDED - 1u;
18
+
19
+ var<workgroup> input_tile: array<f32, {{ inputTileSize }}>;
20
+ var<workgroup> weight_tile: array<f32, {{ kernelSizePadded }}>;
21
+
22
+ fn activate(value: f32) -> f32 {
23
+ {% if useSilu %}
24
+ return value / (1.0 + exp(-value));
25
+ {% else %}
26
+ return value;
27
+ {% endif %}
28
+ }
29
+
30
+ @compute @workgroup_size(WG, 1, 1)
31
+ fn main(@builtin(local_invocation_id) lid3: vec3<u32>,
32
+ @builtin(workgroup_id) wid: vec3<u32>,
33
+ @builtin(num_workgroups) nwg: vec3<u32>) {
34
+ let lane = lid3.x;
35
+ let tiles_per_row = (params.length + TILE - 1u) / TILE;
36
+ // Recover the logical workgroup index after an oversized grid folds into y.
37
+ let flat_wg = wid.x + wid.y * nwg.x;
38
+ let total_wg = params.batchSize * params.channels * tiles_per_row;
39
+ if (flat_wg >= total_wg) {
40
+ return;
41
+ }
42
+
43
+ let tile_index = flat_wg % tiles_per_row;
44
+ let bc = flat_wg / tiles_per_row;
45
+ let channel = bc % params.channels;
46
+ let tile_start = tile_index * TILE;
47
+
48
+ var i = lane;
49
+ while (i < INPUT_TILE_SIZE) {
50
+ // input_tile[i] is the concatenated state/input sample needed at output
51
+ // tile_start + i and kernel tap zero.
52
+ let virtual_pos = tile_start + i;
53
+ var value = 0.0;
54
+ if (virtual_pos >= STATE_LENGTH) {
55
+ let input_pos = virtual_pos - STATE_LENGTH;
56
+ if (input_pos < params.length) {
57
+ value = f32(input[bc * params.length + input_pos]);
58
+ }
59
+ } else {
60
+ {% if hasState %}
61
+ value = f32(past_state[{{ pastSlot }}bc * STATE_LENGTH + virtual_pos]);
62
+ {% endif %}
63
+ }
64
+ input_tile[i] = value;
65
+ i = i + WG;
66
+ }
67
+
68
+ i = lane;
69
+ while (i < KERNEL_PADDED) {
70
+ var weight_value = 0.0;
71
+ if (i < KERNEL_SIZE) {
72
+ weight_value = f32(weight[channel * KERNEL_SIZE + i]);
73
+ }
74
+ weight_tile[i] = weight_value;
75
+ i = i + WG;
76
+ }
77
+ workgroupBarrier();
78
+
79
+ let pos = tile_start + lane * OUTPUTS_PER_THREAD;
80
+ if (pos < params.length) {
81
+ {% if hasBias %}
82
+ var acc0 = vec4<f32>(f32(bias[channel]));
83
+ var acc1 = acc0;
84
+ {% else %}
85
+ var acc0 = vec4<f32>(0.0);
86
+ var acc1 = vec4<f32>(0.0);
87
+ {% endif %}
88
+ // Each lane computes eight adjacent outputs and reuses a weight across them.
89
+ var k = 0u;
90
+ while (k < KERNEL_PADDED) {
91
+ let w = vec4<f32>(
92
+ weight_tile[k],
93
+ weight_tile[k + 1u],
94
+ weight_tile[k + 2u],
95
+ weight_tile[k + 3u]
96
+ );
97
+ let base0 = lane * OUTPUTS_PER_THREAD + k;
98
+ let base1 = base0 + 4u;
99
+ let x00 = vec4<f32>(input_tile[base0], input_tile[base0 + 1u], input_tile[base0 + 2u], input_tile[base0 + 3u]);
100
+ let x01 = vec4<f32>(input_tile[base0 + 1u], input_tile[base0 + 2u], input_tile[base0 + 3u], input_tile[base0 + 4u]);
101
+ let x02 = vec4<f32>(input_tile[base0 + 2u], input_tile[base0 + 3u], input_tile[base0 + 4u], input_tile[base0 + 5u]);
102
+ let x03 = vec4<f32>(input_tile[base0 + 3u], input_tile[base0 + 4u], input_tile[base0 + 5u], input_tile[base0 + 6u]);
103
+ let x10 = vec4<f32>(input_tile[base1], input_tile[base1 + 1u], input_tile[base1 + 2u], input_tile[base1 + 3u]);
104
+ let x11 = vec4<f32>(input_tile[base1 + 1u], input_tile[base1 + 2u], input_tile[base1 + 3u], input_tile[base1 + 4u]);
105
+ let x12 = vec4<f32>(input_tile[base1 + 2u], input_tile[base1 + 3u], input_tile[base1 + 4u], input_tile[base1 + 5u]);
106
+ let x13 = vec4<f32>(input_tile[base1 + 3u], input_tile[base1 + 4u], input_tile[base1 + 5u], input_tile[base1 + 6u]);
107
+ acc0 = fma(x00, vec4<f32>(w.x), acc0);
108
+ acc0 = fma(x01, vec4<f32>(w.y), acc0);
109
+ acc0 = fma(x02, vec4<f32>(w.z), acc0);
110
+ acc0 = fma(x03, vec4<f32>(w.w), acc0);
111
+ acc1 = fma(x10, vec4<f32>(w.x), acc1);
112
+ acc1 = fma(x11, vec4<f32>(w.y), acc1);
113
+ acc1 = fma(x12, vec4<f32>(w.z), acc1);
114
+ acc1 = fma(x13, vec4<f32>(w.w), acc1);
115
+ k = k + 4u;
116
+ }
117
+ let output_base = bc * params.length + pos;
118
+ output[output_base] = {{ outputScalar }}(activate(acc0.x));
119
+ output[output_base + 1u] = {{ outputScalar }}(activate(acc0.y));
120
+ output[output_base + 2u] = {{ outputScalar }}(activate(acc0.z));
121
+ output[output_base + 3u] = {{ outputScalar }}(activate(acc0.w));
122
+ output[output_base + 4u] = {{ outputScalar }}(activate(acc1.x));
123
+ output[output_base + 5u] = {{ outputScalar }}(activate(acc1.y));
124
+ output[output_base + 6u] = {{ outputScalar }}(activate(acc1.z));
125
+ output[output_base + 7u] = {{ outputScalar }}(activate(acc1.w));
126
+ }
127
+
128
+ // Exactly one tile per (batch, channel) updates the carry state, with all
129
+ // lanes sharing the copy.
130
+ if (tile_index == 0u) {
131
+ {% if hasStateWindow %}
132
+ // Windowed state slot j follows position (length - stateWindow + j), so the
133
+ // final slot is the after-last state. A slot whose prefix
134
+ // ends before position 0 holds no position from this call and stays zero. Lanes stride over
135
+ // the flattened (slot, element) grid so a narrow workgroup still covers every slot.
136
+ var e = lane;
137
+ let state_elems = params.stateWindow * STATE_LENGTH;
138
+ while (e < state_elems) {
139
+ let slot = e / STATE_LENGTH;
140
+ let s = e % STATE_LENGTH;
141
+ var state_value = 0.0;
142
+ if (slot + params.length >= params.stateWindow) {
143
+ let virtual_pos = params.length + slot + 1u - params.stateWindow + s;
144
+ if (virtual_pos >= STATE_LENGTH) {
145
+ let input_pos = virtual_pos - STATE_LENGTH;
146
+ state_value = f32(input[bc * params.length + input_pos]);
147
+ } else {
148
+ {% if hasState %}
149
+ state_value = f32(past_state[{{ pastSlot }}bc * STATE_LENGTH + virtual_pos]);
150
+ {% endif %}
151
+ }
152
+ }
153
+ present_state[slot * params.stateSlotStride + bc * STATE_LENGTH + s] = {{ outputScalar }}(state_value);
154
+ e = e + WG;
155
+ }
156
+ {% else %}
157
+ var s = lane;
158
+ while (s < STATE_LENGTH) {
159
+ let virtual_pos = params.length + s;
160
+ var state_value = 0.0;
161
+ if (virtual_pos >= STATE_LENGTH) {
162
+ let input_pos = virtual_pos - STATE_LENGTH;
163
+ state_value = f32(input[bc * params.length + input_pos]);
164
+ } else {
165
+ {% if hasState %}
166
+ state_value = f32(past_state[bc * STATE_LENGTH + virtual_pos]);
167
+ {% endif %}
168
+ }
169
+ present_state[bc * STATE_LENGTH + s] = {{ outputScalar }}(state_value);
170
+ s = s + WG;
171
+ }
172
+ {% endif %}
173
+ }
174
+ }
build/webgpu/causal-conv-with-state-vec4.wgsl.jinja ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% set pastSlot = "(params.stateWindow - 1u) * params.stateSlotStride + " if hasStateWindow else "" %}
2
+ {% if usesF16 %}
3
+ enable f16;
4
+ {% endif -%}
5
+ {{ env.wgsl.resourceDeclarations }}
6
+
7
+ // Four outputs per invocation for a kernel narrow enough that every tap of a
8
+ // four-wide output lands in this vector or the one before it -- kernel size 2 to
9
+ // 4. The taps are unrolled swizzles of two loaded vectors rather than a
10
+ // runtime-bounded loop.
11
+ const WG: u32 = {{ workgroupSize }}u;
12
+ {% set S = kernelSize - 1 %}
13
+ const STATE_LENGTH: u32 = {{ S }}u;
14
+
15
+ fn activate4(value: vec4<f32>) -> vec4<f32> {
16
+ {% if useSilu %}
17
+ return value / (vec4<f32>(1.0) + exp(-value));
18
+ {% else %}
19
+ return value;
20
+ {% endif %}
21
+ }
22
+
23
+ @compute @workgroup_size(WG, 1, 1)
24
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>,
25
+ @builtin(num_workgroups) nwg: vec3<u32>) {
26
+ let row_vecs = params.length / 4u;
27
+ let work_size = params.batchSize * params.channels * row_vecs;
28
+ // Recover the logical 1D index after an oversized dispatch is folded into y.
29
+ let index = gid.x + gid.y * nwg.x * WG;
30
+ if (index >= work_size) {
31
+ return;
32
+ }
33
+
34
+ let pos4 = index % row_vecs;
35
+ let bc = index / row_vecs;
36
+ let channel = bc % params.channels;
37
+ // Widen on load and narrow on store so every tap and accumulation stays f32,
38
+ // independent of the tensor type.
39
+ let current = vec4<f32>(input[index]);
40
+ var previous = vec4<f32>(0.0);
41
+ if (pos4 != 0u) {
42
+ previous = vec4<f32>(input[index - 1u]);
43
+ {% if hasState %}
44
+ } else {
45
+ // The first vector of a row continues the previous call: its taps come from
46
+ // the carried state, in the same trailing lanes the interior case reads.
47
+ let sb = {{ pastSlot }}bc * STATE_LENGTH;
48
+ previous = vec4<f32>({% for i in range(4 - S) %}0.0, {% endfor %}{% for i in range(S) %}f32(past_state[sb{{ " + " ~ i ~ "u" if i else "" }}]){{ ", " if not loop.last else "" }}{% endfor %});
49
+ {% endif %}
50
+ }
51
+
52
+ {% if kernelSize == 4 %}
53
+ let w = vec4<f32>(weight[channel]);
54
+ {% else %}
55
+ {% for k in range(kernelSize) %}
56
+ let w{{ k }} = f32(weight[channel * {{ kernelSize }}u + {{ k }}u]);
57
+ {% endfor %}
58
+ {% endif %}
59
+ {% for k in range(kernelSize) %}
60
+ {% set wk = ("w." ~ ["x", "y", "z", "w"][k]) if kernelSize == 4 else ("w" ~ k) %}
61
+ {% if loop.first and hasBias %}
62
+ var value = vec4<f32>(f32(bias[channel])) + {{ wk }} * vec4<f32>(
63
+ {%- for j in range(4) %}{{ ("current." ~ ["x", "y", "z", "w"][j - S + k]) if j - S + k >= 0 else ("previous." ~ ["x", "y", "z", "w"][4 + j - S + k]) }}{{ ", " if not loop.last else "" }}{% endfor -%}
64
+ );
65
+ {% elif loop.first %}
66
+ var value = {{ wk }} * vec4<f32>(
67
+ {%- for j in range(4) %}{{ ("current." ~ ["x", "y", "z", "w"][j - S + k]) if j - S + k >= 0 else ("previous." ~ ["x", "y", "z", "w"][4 + j - S + k]) }}{{ ", " if not loop.last else "" }}{% endfor -%}
68
+ );
69
+ {% else %}
70
+ value = value + {{ wk }} * vec4<f32>(
71
+ {%- for j in range(4) %}{{ ("current." ~ ["x", "y", "z", "w"][j - S + k]) if j - S + k >= 0 else ("previous." ~ ["x", "y", "z", "w"][4 + j - S + k]) }}{{ ", " if not loop.last else "" }}{% endfor -%}
72
+ );
73
+ {% endif %}
74
+ {% endfor %}
75
+ output[index] = {{ outputVec4 }}(activate4(value));
76
+
77
+ if (pos4 == 0u) {
78
+ {% if hasStateWindow %}
79
+ // Windowed state: slot j holds the carry state after position (length - stateWindow + j).
80
+ // A slot whose prefix ends before position 0 holds no position from this call and stays
81
+ // zero; a slot that reaches back before position 0 continues the carried state.
82
+ // present_state is scalar-typed here while input is vec4, hence the lane split.
83
+ for (var slot = 0u; slot < params.stateWindow; slot = slot + 1u) {
84
+ let in_window = slot + params.length >= params.stateWindow;
85
+ for (var s = 0u; s < STATE_LENGTH; s = s + 1u) {
86
+ var state_value = 0.0;
87
+ if (in_window) {
88
+ let virtual_pos = params.length + slot + 1u - params.stateWindow + s;
89
+ if (virtual_pos >= STATE_LENGTH) {
90
+ let input_pos = virtual_pos - STATE_LENGTH;
91
+ state_value = f32(input[bc * row_vecs + input_pos / 4u][input_pos % 4u]);
92
+ } else {
93
+ {% if hasState %}
94
+ state_value = f32(past_state[{{ pastSlot }}bc * STATE_LENGTH + virtual_pos]);
95
+ {% endif %}
96
+ }
97
+ }
98
+ present_state[slot * params.stateSlotStride + bc * STATE_LENGTH + s] = {{ outputScalar }}(state_value);
99
+ }
100
+ }
101
+ {% else %}
102
+ let tail = vec4<f32>(input[bc * row_vecs + row_vecs - 1u]);
103
+ let state_base = bc * STATE_LENGTH;
104
+ {% for i in range(S) %}
105
+ present_state[state_base{{ " + " ~ i ~ "u" if i else "" }}] = {{ outputScalar }}(tail.{{ "xyzw"[4 - S + i] }});
106
+ {% endfor %}
107
+ {% endif %}
108
+ }
109
+ }
build/webgpu/causal-conv-with-state.wgsl.jinja ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% set pastSlot = "(params.stateWindow - 1u) * params.stateSlotStride + " if hasStateWindow else "" %}
2
+ {% if usesF16 %}
3
+ enable f16;
4
+ {% endif -%}
5
+ {{ env.wgsl.resourceDeclarations }}
6
+
7
+ const WG: u32 = {{ workgroupSize }}u;
8
+
9
+ fn activate(value: f32) -> f32 {
10
+ {% if useSilu %}
11
+ return value / (1.0 + exp(-value));
12
+ {% else %}
13
+ return value;
14
+ {% endif %}
15
+ }
16
+
17
+ @compute @workgroup_size(WG, 1, 1)
18
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>,
19
+ @builtin(num_workgroups) nwg: vec3<u32>) {
20
+ // length == 0 still writes the present_state carryover. The nonzero grid keeps
21
+ // one state-writing thread per (batch, channel) even when there is no output.
22
+ let len_nz = max(1u, params.length);
23
+ let work_size = params.batchSize * params.channels * len_nz;
24
+ // gid.y carries the high bits past the per-dimension dispatch limit.
25
+ let index = gid.x + gid.y * nwg.x * WG;
26
+ if (index >= work_size) {
27
+ return;
28
+ }
29
+
30
+ let pos = index % len_nz;
31
+ let bc = index / len_nz;
32
+ let batch = bc / params.channels;
33
+ let channel = bc % params.channels;
34
+ let state_length = params.kernelSize - 1u;
35
+
36
+ // Output exists only for real positions. At length zero this thread performs
37
+ // only the present_state carryover below.
38
+ if (pos < params.length) {
39
+ var acc = 0.0;
40
+ {% if hasBias %}
41
+ acc = acc + f32(bias[channel]);
42
+
43
+ {% endif %}
44
+ for (var k: u32 = 0u; k < params.kernelSize; k = k + 1u) {
45
+ var value = 0.0;
46
+ let virtual_pos = pos + k;
47
+ if (virtual_pos >= state_length) {
48
+ let input_pos = virtual_pos - state_length;
49
+ let input_index = (batch * params.channels + channel) * params.length + input_pos;
50
+ value = f32(input[input_index]);
51
+ } else {
52
+ {% if hasState %}
53
+ let state_index = {{ pastSlot }}(batch * params.channels + channel) * state_length + virtual_pos;
54
+ value = f32(past_state[state_index]);
55
+ {% endif %}
56
+ }
57
+ acc = acc + value * f32(weight[channel * params.kernelSize + k]);
58
+ }
59
+ output[index] = {{ outputScalar }}(activate(acc));
60
+ }
61
+
62
+ if (pos == 0u) {
63
+ {% if hasStateWindow %}
64
+ // Windowed state slot j follows position (length - stateWindow + j), so the
65
+ // final slot is the after-last state. A slot whose prefix
66
+ // ends before position 0 holds no position from this call and stays zero.
67
+ for (var slot: u32 = 0u; slot < params.stateWindow; slot = slot + 1u) {
68
+ let in_window = slot + params.length >= params.stateWindow;
69
+ for (var s: u32 = 0u; s < state_length; s = s + 1u) {
70
+ var state_value = 0.0;
71
+ if (in_window) {
72
+ let virtual_pos = params.length + slot + 1u - params.stateWindow + s;
73
+ if (virtual_pos >= state_length) {
74
+ let input_pos = virtual_pos - state_length;
75
+ let input_index = (batch * params.channels + channel) * params.length + input_pos;
76
+ state_value = f32(input[input_index]);
77
+ } else {
78
+ {% if hasState %}
79
+ let state_index = {{ pastSlot }}(batch * params.channels + channel) * state_length + virtual_pos;
80
+ state_value = f32(past_state[state_index]);
81
+ {% endif %}
82
+ }
83
+ }
84
+ present_state[slot * params.stateSlotStride + (batch * params.channels + channel) * state_length + s] = {{ outputScalar }}(state_value);
85
+ }
86
+ }
87
+ {% else %}
88
+ for (var s: u32 = 0u; s < state_length; s = s + 1u) {
89
+ var state_value = 0.0;
90
+ let virtual_pos = params.length + s;
91
+ if (virtual_pos >= state_length) {
92
+ let input_pos = virtual_pos - state_length;
93
+ let input_index = (batch * params.channels + channel) * params.length + input_pos;
94
+ state_value = f32(input[input_index]);
95
+ } else {
96
+ {% if hasState %}
97
+ let state_index = (batch * params.channels + channel) * state_length + virtual_pos;
98
+ state_value = f32(past_state[state_index]);
99
+ {% endif %}
100
+ }
101
+ present_state[(batch * params.channels + channel) * state_length + s] = {{ outputScalar }}(state_value);
102
+ }
103
+ {% endif %}
104
+ }
105
+ }
build/webgpu/manifest.json ADDED
@@ -0,0 +1,1257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "domain": "com.microsoft",
3
+ "name": "CausalConvWithState",
4
+ "sinceVersion": 1,
5
+ "description": "Legacy Microsoft contrib form of stateful 1-D causal depthwise convolution. Each channel uses its own `(channels, 1, kernel)` weight over current and past positions, with optional activation and `past_state`/`present_state` tensors for incremental decoding. The contrib-only `state_window` attribute may retain several rollback states. This inference implementation preserves the existing contrib ABI with `ndim = 1`, float16 or float32 tensors, and float32 accumulation; spatial ranks 2 and 3 and bfloat16 are not implemented.",
6
+ "inputs": [
7
+ {
8
+ "role": "input",
9
+ "dtype": "T",
10
+ "rank": 3,
11
+ "description": "Channels-first input tensor with shape `(batch_size, channels, sequence_length)` for the supported 1-D mode."
12
+ },
13
+ {
14
+ "role": "weight",
15
+ "dtype": "T",
16
+ "rank": 3,
17
+ "description": "Depthwise convolution kernel with shape `(channels, 1, kernel_size)` for the supported 1-D mode."
18
+ },
19
+ {
20
+ "role": "bias",
21
+ "dtype": "T",
22
+ "rank": 1,
23
+ "optional": true,
24
+ "description": "Optional per-channel bias with shape `(channels,)`."
25
+ },
26
+ {
27
+ "role": "past_state",
28
+ "dtype": "T",
29
+ "rank": "3 if attrs.state_window == 0 else 4",
30
+ "optional": true,
31
+ "description": "Carry state from the previous step; shape `(batch_size, channels, k_1 - 1)`, or `(W, batch_size, channels, k_1 - 1)` when `state_window = W > 0`, in which case only slot `W - 1` is read. If absent, the left-side padding is zero."
32
+ }
33
+ ],
34
+ "outputs": [
35
+ {
36
+ "role": "output",
37
+ "dtype": "T",
38
+ "rank": 3,
39
+ "shape": "shapes.input",
40
+ "description": "Convolution output with the same shape as `input`."
41
+ },
42
+ {
43
+ "role": "present_state",
44
+ "dtype": "T",
45
+ "rank": "3 if attrs.state_window == 0 else 4",
46
+ "shape": "[dim(shapes.input, 0), dim(shapes.input, 1), dim(shapes.weight, 2) - 1] if attrs.state_window == 0 else [attrs.state_window, dim(shapes.input, 0), dim(shapes.input, 1), dim(shapes.weight, 2) - 1]",
47
+ "description": "Updated carry state; shape `(batch_size, channels, k_1 - 1)`, or `(W, batch_size, channels, k_1 - 1)` when `state_window = W > 0`. Slot `W - 1` holds the last `k - 1` values along the causal axis; slot `j` holds the same for the prefix ending at position `seq_len - W + j`."
48
+ }
49
+ ],
50
+ "attributes": { "activation": "none", "ndim": 1, "state_window": 0 },
51
+ "attributeConstraints": { "activation": { "values": ["none", "silu", "swish"] }, "ndim": { "values": [1] } },
52
+ "attributeDescriptions": {
53
+ "activation": "Activation applied after convolution and bias. Defaults to `none`; `swish` is an alias of SiLU.",
54
+ "ndim": "Number of spatial dimensions. This implementation supports the contrib 1D mode (`ndim = 1`).",
55
+ "state_window": "Contrib extension selecting the number of rollback state slots to retain, in the range 0 through 8. Defaults to 0."
56
+ },
57
+ "typeConstraints": { "T": ["float32", "float16"] },
58
+ "args": {
59
+ "inputT": { "kind": "tensor", "semantic": "input", "role": "input" },
60
+ "weightT": { "kind": "tensor", "semantic": "weight", "role": "input" },
61
+ "biasT": { "kind": "tensor", "semantic": "bias", "role": "input", "required": false },
62
+ "pastStateT": { "kind": "tensor", "semantic": "past_state", "role": "input", "required": false },
63
+ "outputT": { "kind": "tensor", "semantic": "output", "role": "output" },
64
+ "presentStateT": { "kind": "tensor", "semantic": "present_state", "role": "output" }
65
+ },
66
+ "tunables": { "workgroupSize": 256, "tiledWorkgroupSize": 128 },
67
+ "derive": {
68
+ "stateWindow": "attrs.state_window",
69
+ "windowed": "stateWindow > 0",
70
+ "stateWindowOk": "stateWindow >= 0 and stateWindow <= 8",
71
+ "kernelSize": "dim(shapes.weightT, ranks.weightT - 1)",
72
+ "kernelSizePadded": "ceilDiv(kernelSize, 4) * 4",
73
+ "weightRankOk": "ranks.weightT == 3 and dim(shapes.weightT, 1) == 1",
74
+ "stateLength": "kernelSize - 1",
75
+ "stateSlotStride": "dim(shapes.inputT, 0) * dim(shapes.inputT, 1) * stateLength",
76
+ "windowedLengthOk": "not windowed or dim(shapes.inputT, 2) > 0",
77
+ "presentStateOk": "(ranks.presentStateT == 3 and dim(shapes.presentStateT, 0) == dim(shapes.inputT, 0) and dim(shapes.presentStateT, 1) == dim(shapes.inputT, 1) and dim(shapes.presentStateT, 2) == stateLength) if not windowed else (ranks.presentStateT == 4 and dim(shapes.presentStateT, 0) == stateWindow and dim(shapes.presentStateT, 1) == dim(shapes.inputT, 0) and dim(shapes.presentStateT, 2) == dim(shapes.inputT, 1) and dim(shapes.presentStateT, 3) == stateLength)",
78
+ "pastStateShapeOk": "present.pastStateT and ((ranks.pastStateT == 3 and dim(shapes.pastStateT, 0) == dim(shapes.inputT, 0) and dim(shapes.pastStateT, 1) == dim(shapes.inputT, 1) and dim(shapes.pastStateT, 2) == stateLength) if not windowed else (ranks.pastStateT == 4 and dim(shapes.pastStateT, 0) == stateWindow and dim(shapes.pastStateT, 1) == dim(shapes.inputT, 0) and dim(shapes.pastStateT, 2) == dim(shapes.inputT, 1) and dim(shapes.pastStateT, 3) == stateLength))",
79
+ "commonContract": "ranks.inputT == 3 and weightRankOk and ranks.outputT == 3 and (tensorDtypes.inputT == \"float32\" or tensorDtypes.inputT == \"float16\") and tensorDtypes.weightT == tensorDtypes.inputT and tensorDtypes.outputT == tensorDtypes.inputT and tensorDtypes.presentStateT == tensorDtypes.inputT and f16Ok(dtypes.T) and dim(shapes.inputT, 1) == dim(shapes.weightT, 0) and dim(shapes.outputT, 0) == dim(shapes.inputT, 0) and dim(shapes.outputT, 1) == dim(shapes.inputT, 1) and dim(shapes.outputT, 2) == dim(shapes.inputT, 2) and stateWindowOk and windowedLengthOk and presentStateOk",
80
+ "zeroStateContract": "commonContract and not present.pastStateT and not present.biasT",
81
+ "biasNoStateContract": "commonContract and not present.pastStateT and present.biasT and ranks.biasT == 1 and tensorDtypes.biasT == tensorDtypes.inputT and dim(shapes.biasT, 0) == dim(shapes.inputT, 1)",
82
+ "stateNoBiasContract": "commonContract and present.pastStateT and not present.biasT and tensorDtypes.pastStateT == tensorDtypes.inputT and pastStateShapeOk",
83
+ "stateBiasContract": "commonContract and present.pastStateT and present.biasT and ranks.biasT == 1 and tensorDtypes.pastStateT == tensorDtypes.inputT and tensorDtypes.biasT == tensorDtypes.inputT and pastStateShapeOk and dim(shapes.biasT, 0) == dim(shapes.inputT, 1)"
84
+ },
85
+ "bindingSets": {
86
+ "zeroScalar": [
87
+ {
88
+ "name": "input",
89
+ "arg": "inputT",
90
+ "semantic": "input",
91
+ "buffer": { "type": "read-only-storage" },
92
+ "elementType": "$inputScalar"
93
+ },
94
+ {
95
+ "name": "weight",
96
+ "arg": "weightT",
97
+ "semantic": "weight",
98
+ "buffer": { "type": "read-only-storage" },
99
+ "elementType": "$inputScalar"
100
+ },
101
+ {
102
+ "name": "output",
103
+ "arg": "outputT",
104
+ "semantic": "output",
105
+ "buffer": { "type": "storage" },
106
+ "elementType": "$outputScalar"
107
+ },
108
+ {
109
+ "name": "present_state",
110
+ "arg": "presentStateT",
111
+ "semantic": "present_state",
112
+ "buffer": { "type": "storage" },
113
+ "elementType": "$outputScalar"
114
+ },
115
+ {
116
+ "name": "params",
117
+ "semantic": "kernel.params",
118
+ "buffer": { "type": "uniform" },
119
+ "struct": {
120
+ "name": "Params",
121
+ "fields": [
122
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
123
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
124
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
125
+ { "name": "kernelSize", "type": "u32", "value": "kernelSize" },
126
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
127
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
128
+ ]
129
+ }
130
+ }
131
+ ],
132
+ "zeroVec4": [
133
+ {
134
+ "name": "input",
135
+ "arg": "inputT",
136
+ "semantic": "input",
137
+ "buffer": { "type": "read-only-storage" },
138
+ "elementType": "$inputVec4"
139
+ },
140
+ {
141
+ "name": "weight",
142
+ "arg": "weightT",
143
+ "semantic": "weight",
144
+ "buffer": { "type": "read-only-storage" },
145
+ "elementType": "$weightElem"
146
+ },
147
+ {
148
+ "name": "output",
149
+ "arg": "outputT",
150
+ "semantic": "output",
151
+ "buffer": { "type": "storage" },
152
+ "elementType": "$outputVec4"
153
+ },
154
+ {
155
+ "name": "present_state",
156
+ "arg": "presentStateT",
157
+ "semantic": "present_state",
158
+ "buffer": { "type": "storage" },
159
+ "elementType": "$outputScalar"
160
+ },
161
+ {
162
+ "name": "params",
163
+ "semantic": "kernel.params",
164
+ "buffer": { "type": "uniform" },
165
+ "struct": {
166
+ "name": "Params",
167
+ "fields": [
168
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
169
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
170
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
171
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
172
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
173
+ ]
174
+ }
175
+ }
176
+ ],
177
+ "biasNoState": [
178
+ {
179
+ "name": "input",
180
+ "arg": "inputT",
181
+ "semantic": "input",
182
+ "buffer": { "type": "read-only-storage" },
183
+ "elementType": "$inputScalar"
184
+ },
185
+ {
186
+ "name": "weight",
187
+ "arg": "weightT",
188
+ "semantic": "weight",
189
+ "buffer": { "type": "read-only-storage" },
190
+ "elementType": "$inputScalar"
191
+ },
192
+ {
193
+ "name": "bias",
194
+ "arg": "biasT",
195
+ "semantic": "bias",
196
+ "buffer": { "type": "read-only-storage" },
197
+ "elementType": "$inputScalar"
198
+ },
199
+ {
200
+ "name": "output",
201
+ "arg": "outputT",
202
+ "semantic": "output",
203
+ "buffer": { "type": "storage" },
204
+ "elementType": "$outputScalar"
205
+ },
206
+ {
207
+ "name": "present_state",
208
+ "arg": "presentStateT",
209
+ "semantic": "present_state",
210
+ "buffer": { "type": "storage" },
211
+ "elementType": "$outputScalar"
212
+ },
213
+ {
214
+ "name": "params",
215
+ "semantic": "kernel.params",
216
+ "buffer": { "type": "uniform" },
217
+ "struct": {
218
+ "name": "Params",
219
+ "fields": [
220
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
221
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
222
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
223
+ { "name": "kernelSize", "type": "u32", "value": "kernelSize" },
224
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
225
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
226
+ ]
227
+ }
228
+ }
229
+ ],
230
+ "stateNoBias": [
231
+ {
232
+ "name": "input",
233
+ "arg": "inputT",
234
+ "semantic": "input",
235
+ "buffer": { "type": "read-only-storage" },
236
+ "elementType": "$inputScalar"
237
+ },
238
+ {
239
+ "name": "weight",
240
+ "arg": "weightT",
241
+ "semantic": "weight",
242
+ "buffer": { "type": "read-only-storage" },
243
+ "elementType": "$inputScalar"
244
+ },
245
+ {
246
+ "name": "past_state",
247
+ "arg": "pastStateT",
248
+ "semantic": "past_state",
249
+ "buffer": { "type": "read-only-storage" },
250
+ "elementType": "$inputScalar"
251
+ },
252
+ {
253
+ "name": "output",
254
+ "arg": "outputT",
255
+ "semantic": "output",
256
+ "buffer": { "type": "storage" },
257
+ "elementType": "$outputScalar"
258
+ },
259
+ {
260
+ "name": "present_state",
261
+ "arg": "presentStateT",
262
+ "semantic": "present_state",
263
+ "buffer": { "type": "storage" },
264
+ "elementType": "$outputScalar"
265
+ },
266
+ {
267
+ "name": "params",
268
+ "semantic": "kernel.params",
269
+ "buffer": { "type": "uniform" },
270
+ "struct": {
271
+ "name": "Params",
272
+ "fields": [
273
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
274
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
275
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
276
+ { "name": "kernelSize", "type": "u32", "value": "kernelSize" },
277
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
278
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
279
+ ]
280
+ }
281
+ }
282
+ ],
283
+ "stateBias": [
284
+ {
285
+ "name": "input",
286
+ "arg": "inputT",
287
+ "semantic": "input",
288
+ "buffer": { "type": "read-only-storage" },
289
+ "elementType": "$inputScalar"
290
+ },
291
+ {
292
+ "name": "weight",
293
+ "arg": "weightT",
294
+ "semantic": "weight",
295
+ "buffer": { "type": "read-only-storage" },
296
+ "elementType": "$inputScalar"
297
+ },
298
+ {
299
+ "name": "bias",
300
+ "arg": "biasT",
301
+ "semantic": "bias",
302
+ "buffer": { "type": "read-only-storage" },
303
+ "elementType": "$inputScalar"
304
+ },
305
+ {
306
+ "name": "past_state",
307
+ "arg": "pastStateT",
308
+ "semantic": "past_state",
309
+ "buffer": { "type": "read-only-storage" },
310
+ "elementType": "$inputScalar"
311
+ },
312
+ {
313
+ "name": "output",
314
+ "arg": "outputT",
315
+ "semantic": "output",
316
+ "buffer": { "type": "storage" },
317
+ "elementType": "$outputScalar"
318
+ },
319
+ {
320
+ "name": "present_state",
321
+ "arg": "presentStateT",
322
+ "semantic": "present_state",
323
+ "buffer": { "type": "storage" },
324
+ "elementType": "$outputScalar"
325
+ },
326
+ {
327
+ "name": "params",
328
+ "semantic": "kernel.params",
329
+ "buffer": { "type": "uniform" },
330
+ "struct": {
331
+ "name": "Params",
332
+ "fields": [
333
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
334
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
335
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
336
+ { "name": "kernelSize", "type": "u32", "value": "kernelSize" },
337
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
338
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
339
+ ]
340
+ }
341
+ }
342
+ ],
343
+ "zeroScalarIo": [
344
+ {
345
+ "name": "input",
346
+ "arg": "inputT",
347
+ "semantic": "input",
348
+ "buffer": { "type": "read-only-storage" },
349
+ "elementType": "$inputScalar"
350
+ },
351
+ {
352
+ "name": "weight",
353
+ "arg": "weightT",
354
+ "semantic": "weight",
355
+ "buffer": { "type": "read-only-storage" },
356
+ "elementType": "$inputScalar"
357
+ },
358
+ {
359
+ "name": "output",
360
+ "arg": "outputT",
361
+ "semantic": "output",
362
+ "buffer": { "type": "storage" },
363
+ "elementType": "$outputScalar"
364
+ },
365
+ {
366
+ "name": "present_state",
367
+ "arg": "presentStateT",
368
+ "semantic": "present_state",
369
+ "buffer": { "type": "storage" },
370
+ "elementType": "$outputScalar"
371
+ }
372
+ ],
373
+ "biasNoStateIo": [
374
+ {
375
+ "name": "input",
376
+ "arg": "inputT",
377
+ "semantic": "input",
378
+ "buffer": { "type": "read-only-storage" },
379
+ "elementType": "$inputScalar"
380
+ },
381
+ {
382
+ "name": "weight",
383
+ "arg": "weightT",
384
+ "semantic": "weight",
385
+ "buffer": { "type": "read-only-storage" },
386
+ "elementType": "$inputScalar"
387
+ },
388
+ {
389
+ "name": "bias",
390
+ "arg": "biasT",
391
+ "semantic": "bias",
392
+ "buffer": { "type": "read-only-storage" },
393
+ "elementType": "$inputScalar"
394
+ },
395
+ {
396
+ "name": "output",
397
+ "arg": "outputT",
398
+ "semantic": "output",
399
+ "buffer": { "type": "storage" },
400
+ "elementType": "$outputScalar"
401
+ },
402
+ {
403
+ "name": "present_state",
404
+ "arg": "presentStateT",
405
+ "semantic": "present_state",
406
+ "buffer": { "type": "storage" },
407
+ "elementType": "$outputScalar"
408
+ }
409
+ ],
410
+ "stateNoBiasIo": [
411
+ {
412
+ "name": "input",
413
+ "arg": "inputT",
414
+ "semantic": "input",
415
+ "buffer": { "type": "read-only-storage" },
416
+ "elementType": "$inputScalar"
417
+ },
418
+ {
419
+ "name": "weight",
420
+ "arg": "weightT",
421
+ "semantic": "weight",
422
+ "buffer": { "type": "read-only-storage" },
423
+ "elementType": "$inputScalar"
424
+ },
425
+ {
426
+ "name": "past_state",
427
+ "arg": "pastStateT",
428
+ "semantic": "past_state",
429
+ "buffer": { "type": "read-only-storage" },
430
+ "elementType": "$inputScalar"
431
+ },
432
+ {
433
+ "name": "output",
434
+ "arg": "outputT",
435
+ "semantic": "output",
436
+ "buffer": { "type": "storage" },
437
+ "elementType": "$outputScalar"
438
+ },
439
+ {
440
+ "name": "present_state",
441
+ "arg": "presentStateT",
442
+ "semantic": "present_state",
443
+ "buffer": { "type": "storage" },
444
+ "elementType": "$outputScalar"
445
+ }
446
+ ],
447
+ "stateBiasIo": [
448
+ {
449
+ "name": "input",
450
+ "arg": "inputT",
451
+ "semantic": "input",
452
+ "buffer": { "type": "read-only-storage" },
453
+ "elementType": "$inputScalar"
454
+ },
455
+ {
456
+ "name": "weight",
457
+ "arg": "weightT",
458
+ "semantic": "weight",
459
+ "buffer": { "type": "read-only-storage" },
460
+ "elementType": "$inputScalar"
461
+ },
462
+ {
463
+ "name": "bias",
464
+ "arg": "biasT",
465
+ "semantic": "bias",
466
+ "buffer": { "type": "read-only-storage" },
467
+ "elementType": "$inputScalar"
468
+ },
469
+ {
470
+ "name": "past_state",
471
+ "arg": "pastStateT",
472
+ "semantic": "past_state",
473
+ "buffer": { "type": "read-only-storage" },
474
+ "elementType": "$inputScalar"
475
+ },
476
+ {
477
+ "name": "output",
478
+ "arg": "outputT",
479
+ "semantic": "output",
480
+ "buffer": { "type": "storage" },
481
+ "elementType": "$outputScalar"
482
+ },
483
+ {
484
+ "name": "present_state",
485
+ "arg": "presentStateT",
486
+ "semantic": "present_state",
487
+ "buffer": { "type": "storage" },
488
+ "elementType": "$outputScalar"
489
+ }
490
+ ],
491
+ "zeroTiled": [
492
+ {
493
+ "name": "input",
494
+ "arg": "inputT",
495
+ "semantic": "input",
496
+ "buffer": { "type": "read-only-storage" },
497
+ "elementType": "$inputScalar"
498
+ },
499
+ {
500
+ "name": "weight",
501
+ "arg": "weightT",
502
+ "semantic": "weight",
503
+ "buffer": { "type": "read-only-storage" },
504
+ "elementType": "$inputScalar"
505
+ },
506
+ {
507
+ "name": "output",
508
+ "arg": "outputT",
509
+ "semantic": "output",
510
+ "buffer": { "type": "storage" },
511
+ "elementType": "$outputScalar"
512
+ },
513
+ {
514
+ "name": "present_state",
515
+ "arg": "presentStateT",
516
+ "semantic": "present_state",
517
+ "buffer": { "type": "storage" },
518
+ "elementType": "$outputScalar"
519
+ },
520
+ {
521
+ "name": "params",
522
+ "semantic": "kernel.params",
523
+ "buffer": { "type": "uniform" },
524
+ "struct": {
525
+ "name": "Params",
526
+ "fields": [
527
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
528
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
529
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
530
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
531
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
532
+ ]
533
+ }
534
+ }
535
+ ],
536
+ "biasNoStateTiled": [
537
+ {
538
+ "name": "input",
539
+ "arg": "inputT",
540
+ "semantic": "input",
541
+ "buffer": { "type": "read-only-storage" },
542
+ "elementType": "$inputScalar"
543
+ },
544
+ {
545
+ "name": "weight",
546
+ "arg": "weightT",
547
+ "semantic": "weight",
548
+ "buffer": { "type": "read-only-storage" },
549
+ "elementType": "$inputScalar"
550
+ },
551
+ {
552
+ "name": "bias",
553
+ "arg": "biasT",
554
+ "semantic": "bias",
555
+ "buffer": { "type": "read-only-storage" },
556
+ "elementType": "$inputScalar"
557
+ },
558
+ {
559
+ "name": "output",
560
+ "arg": "outputT",
561
+ "semantic": "output",
562
+ "buffer": { "type": "storage" },
563
+ "elementType": "$outputScalar"
564
+ },
565
+ {
566
+ "name": "present_state",
567
+ "arg": "presentStateT",
568
+ "semantic": "present_state",
569
+ "buffer": { "type": "storage" },
570
+ "elementType": "$outputScalar"
571
+ },
572
+ {
573
+ "name": "params",
574
+ "semantic": "kernel.params",
575
+ "buffer": { "type": "uniform" },
576
+ "struct": {
577
+ "name": "Params",
578
+ "fields": [
579
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
580
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
581
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
582
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
583
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
584
+ ]
585
+ }
586
+ }
587
+ ],
588
+ "stateNoBiasTiled": [
589
+ {
590
+ "name": "input",
591
+ "arg": "inputT",
592
+ "semantic": "input",
593
+ "buffer": { "type": "read-only-storage" },
594
+ "elementType": "$inputScalar"
595
+ },
596
+ {
597
+ "name": "weight",
598
+ "arg": "weightT",
599
+ "semantic": "weight",
600
+ "buffer": { "type": "read-only-storage" },
601
+ "elementType": "$inputScalar"
602
+ },
603
+ {
604
+ "name": "past_state",
605
+ "arg": "pastStateT",
606
+ "semantic": "past_state",
607
+ "buffer": { "type": "read-only-storage" },
608
+ "elementType": "$inputScalar"
609
+ },
610
+ {
611
+ "name": "output",
612
+ "arg": "outputT",
613
+ "semantic": "output",
614
+ "buffer": { "type": "storage" },
615
+ "elementType": "$outputScalar"
616
+ },
617
+ {
618
+ "name": "present_state",
619
+ "arg": "presentStateT",
620
+ "semantic": "present_state",
621
+ "buffer": { "type": "storage" },
622
+ "elementType": "$outputScalar"
623
+ },
624
+ {
625
+ "name": "params",
626
+ "semantic": "kernel.params",
627
+ "buffer": { "type": "uniform" },
628
+ "struct": {
629
+ "name": "Params",
630
+ "fields": [
631
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
632
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
633
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
634
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
635
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
636
+ ]
637
+ }
638
+ }
639
+ ],
640
+ "stateBiasTiled": [
641
+ {
642
+ "name": "input",
643
+ "arg": "inputT",
644
+ "semantic": "input",
645
+ "buffer": { "type": "read-only-storage" },
646
+ "elementType": "$inputScalar"
647
+ },
648
+ {
649
+ "name": "weight",
650
+ "arg": "weightT",
651
+ "semantic": "weight",
652
+ "buffer": { "type": "read-only-storage" },
653
+ "elementType": "$inputScalar"
654
+ },
655
+ {
656
+ "name": "bias",
657
+ "arg": "biasT",
658
+ "semantic": "bias",
659
+ "buffer": { "type": "read-only-storage" },
660
+ "elementType": "$inputScalar"
661
+ },
662
+ {
663
+ "name": "past_state",
664
+ "arg": "pastStateT",
665
+ "semantic": "past_state",
666
+ "buffer": { "type": "read-only-storage" },
667
+ "elementType": "$inputScalar"
668
+ },
669
+ {
670
+ "name": "output",
671
+ "arg": "outputT",
672
+ "semantic": "output",
673
+ "buffer": { "type": "storage" },
674
+ "elementType": "$outputScalar"
675
+ },
676
+ {
677
+ "name": "present_state",
678
+ "arg": "presentStateT",
679
+ "semantic": "present_state",
680
+ "buffer": { "type": "storage" },
681
+ "elementType": "$outputScalar"
682
+ },
683
+ {
684
+ "name": "params",
685
+ "semantic": "kernel.params",
686
+ "buffer": { "type": "uniform" },
687
+ "struct": {
688
+ "name": "Params",
689
+ "fields": [
690
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
691
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
692
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
693
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
694
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
695
+ ]
696
+ }
697
+ }
698
+ ],
699
+ "biasNoStateVec4": [
700
+ {
701
+ "name": "input",
702
+ "arg": "inputT",
703
+ "semantic": "input",
704
+ "buffer": { "type": "read-only-storage" },
705
+ "elementType": "$inputVec4"
706
+ },
707
+ {
708
+ "name": "weight",
709
+ "arg": "weightT",
710
+ "semantic": "weight",
711
+ "buffer": { "type": "read-only-storage" },
712
+ "elementType": "$weightElem"
713
+ },
714
+ {
715
+ "name": "bias",
716
+ "arg": "biasT",
717
+ "semantic": "bias",
718
+ "buffer": { "type": "read-only-storage" },
719
+ "elementType": "$inputScalar"
720
+ },
721
+ {
722
+ "name": "output",
723
+ "arg": "outputT",
724
+ "semantic": "output",
725
+ "buffer": { "type": "storage" },
726
+ "elementType": "$outputVec4"
727
+ },
728
+ {
729
+ "name": "present_state",
730
+ "arg": "presentStateT",
731
+ "semantic": "present_state",
732
+ "buffer": { "type": "storage" },
733
+ "elementType": "$outputScalar"
734
+ },
735
+ {
736
+ "name": "params",
737
+ "semantic": "kernel.params",
738
+ "buffer": { "type": "uniform" },
739
+ "struct": {
740
+ "name": "Params",
741
+ "fields": [
742
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
743
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
744
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
745
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
746
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
747
+ ]
748
+ }
749
+ }
750
+ ],
751
+ "stateNoBiasVec4": [
752
+ {
753
+ "name": "input",
754
+ "arg": "inputT",
755
+ "semantic": "input",
756
+ "buffer": { "type": "read-only-storage" },
757
+ "elementType": "$inputVec4"
758
+ },
759
+ {
760
+ "name": "weight",
761
+ "arg": "weightT",
762
+ "semantic": "weight",
763
+ "buffer": { "type": "read-only-storage" },
764
+ "elementType": "$weightElem"
765
+ },
766
+ {
767
+ "name": "past_state",
768
+ "arg": "pastStateT",
769
+ "semantic": "past_state",
770
+ "buffer": { "type": "read-only-storage" },
771
+ "elementType": "$inputScalar"
772
+ },
773
+ {
774
+ "name": "output",
775
+ "arg": "outputT",
776
+ "semantic": "output",
777
+ "buffer": { "type": "storage" },
778
+ "elementType": "$outputVec4"
779
+ },
780
+ {
781
+ "name": "present_state",
782
+ "arg": "presentStateT",
783
+ "semantic": "present_state",
784
+ "buffer": { "type": "storage" },
785
+ "elementType": "$outputScalar"
786
+ },
787
+ {
788
+ "name": "params",
789
+ "semantic": "kernel.params",
790
+ "buffer": { "type": "uniform" },
791
+ "struct": {
792
+ "name": "Params",
793
+ "fields": [
794
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
795
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
796
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
797
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
798
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
799
+ ]
800
+ }
801
+ }
802
+ ],
803
+ "stateBiasVec4": [
804
+ {
805
+ "name": "input",
806
+ "arg": "inputT",
807
+ "semantic": "input",
808
+ "buffer": { "type": "read-only-storage" },
809
+ "elementType": "$inputVec4"
810
+ },
811
+ {
812
+ "name": "weight",
813
+ "arg": "weightT",
814
+ "semantic": "weight",
815
+ "buffer": { "type": "read-only-storage" },
816
+ "elementType": "$weightElem"
817
+ },
818
+ {
819
+ "name": "bias",
820
+ "arg": "biasT",
821
+ "semantic": "bias",
822
+ "buffer": { "type": "read-only-storage" },
823
+ "elementType": "$inputScalar"
824
+ },
825
+ {
826
+ "name": "past_state",
827
+ "arg": "pastStateT",
828
+ "semantic": "past_state",
829
+ "buffer": { "type": "read-only-storage" },
830
+ "elementType": "$inputScalar"
831
+ },
832
+ {
833
+ "name": "output",
834
+ "arg": "outputT",
835
+ "semantic": "output",
836
+ "buffer": { "type": "storage" },
837
+ "elementType": "$outputVec4"
838
+ },
839
+ {
840
+ "name": "present_state",
841
+ "arg": "presentStateT",
842
+ "semantic": "present_state",
843
+ "buffer": { "type": "storage" },
844
+ "elementType": "$outputScalar"
845
+ },
846
+ {
847
+ "name": "params",
848
+ "semantic": "kernel.params",
849
+ "buffer": { "type": "uniform" },
850
+ "struct": {
851
+ "name": "Params",
852
+ "fields": [
853
+ { "name": "batchSize", "type": "u32", "value": "dim(shapes.inputT, 0)" },
854
+ { "name": "channels", "type": "u32", "value": "dim(shapes.inputT, 1)" },
855
+ { "name": "length", "type": "u32", "value": "dim(shapes.inputT, 2)" },
856
+ { "name": "stateWindow", "type": "u32", "value": "stateWindow" },
857
+ { "name": "stateSlotStride", "type": "u32", "value": "stateSlotStride" }
858
+ ]
859
+ }
860
+ }
861
+ ]
862
+ },
863
+ "variants": [
864
+ {
865
+ "id": "zero_state_vec4",
866
+ "priority": 20,
867
+ "when": ["zeroStateContract", "kernelSize >= 2", "kernelSize <= 4", "dim(shapes.inputT, 2) >= 4", "dim(shapes.inputT, 2) % 4 == 0"],
868
+ "constants": {
869
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
870
+ "workgroupSize": 256,
871
+ "hasStateWindow": "windowed",
872
+ "usesF16": "tensorDtypes.inputT == \"float16\"",
873
+ "inputScalar": "dtypes.T",
874
+ "outputScalar": "dtypes.T",
875
+ "inputVec4": "\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\"",
876
+ "outputVec4": "\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\"",
877
+ "hasBias": false,
878
+ "hasState": false,
879
+ "kernelSize": "kernelSize",
880
+ "kernelSizePadded": "kernelSizePadded",
881
+ "weightElem": "(\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\") if kernelSize == 4 else dtypes.T"
882
+ },
883
+ "passes": [
884
+ {
885
+ "id": "main",
886
+ "name": "CausalConvWithState.Vec4",
887
+ "source": {
888
+ "shader": "causal-conv-with-state-vec4.wgsl.jinja",
889
+ "inputs": { "materializeConvBeforeActivation": false }
890
+ },
891
+ "bindings": "zeroVec4",
892
+ "dispatch": {
893
+ "threads": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * (dim(shapes.outputT, 2) / 4)",
894
+ "workgroupSize": "constants.workgroupSize"
895
+ }
896
+ }
897
+ ]
898
+ },
899
+ {
900
+ "id": "state_bias_vec4",
901
+ "priority": 20,
902
+ "when": ["stateBiasContract", "kernelSize >= 2", "kernelSize <= 4", "dim(shapes.inputT, 2) >= 4", "dim(shapes.inputT, 2) % 4 == 0"],
903
+ "constants": {
904
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
905
+ "workgroupSize": 256,
906
+ "hasStateWindow": "windowed",
907
+ "usesF16": "tensorDtypes.inputT == \"float16\"",
908
+ "inputScalar": "dtypes.T",
909
+ "outputScalar": "dtypes.T",
910
+ "inputVec4": "\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\"",
911
+ "outputVec4": "\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\"",
912
+ "hasBias": true,
913
+ "hasState": true,
914
+ "kernelSize": "kernelSize",
915
+ "kernelSizePadded": "kernelSizePadded",
916
+ "weightElem": "(\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\") if kernelSize == 4 else dtypes.T"
917
+ },
918
+ "passes": [
919
+ {
920
+ "id": "main",
921
+ "name": "CausalConvWithState.Vec4",
922
+ "source": {
923
+ "shader": "causal-conv-with-state-vec4.wgsl.jinja",
924
+ "inputs": { "materializeConvBeforeActivation": false }
925
+ },
926
+ "bindings": "stateBiasVec4",
927
+ "dispatch": {
928
+ "threads": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * (dim(shapes.outputT, 2) / 4)",
929
+ "workgroupSize": "constants.workgroupSize"
930
+ }
931
+ }
932
+ ]
933
+ },
934
+ {
935
+ "id": "bias_no_state_vec4",
936
+ "priority": 20,
937
+ "when": ["biasNoStateContract", "kernelSize >= 2", "kernelSize <= 4", "dim(shapes.inputT, 2) >= 4", "dim(shapes.inputT, 2) % 4 == 0"],
938
+ "constants": {
939
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
940
+ "workgroupSize": 256,
941
+ "hasStateWindow": "windowed",
942
+ "usesF16": "tensorDtypes.inputT == \"float16\"",
943
+ "inputScalar": "dtypes.T",
944
+ "outputScalar": "dtypes.T",
945
+ "inputVec4": "\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\"",
946
+ "outputVec4": "\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\"",
947
+ "hasBias": true,
948
+ "hasState": false,
949
+ "kernelSize": "kernelSize",
950
+ "kernelSizePadded": "kernelSizePadded",
951
+ "weightElem": "(\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\") if kernelSize == 4 else dtypes.T"
952
+ },
953
+ "passes": [
954
+ {
955
+ "id": "main",
956
+ "name": "CausalConvWithState.Vec4",
957
+ "source": {
958
+ "shader": "causal-conv-with-state-vec4.wgsl.jinja",
959
+ "inputs": { "materializeConvBeforeActivation": false }
960
+ },
961
+ "bindings": "biasNoStateVec4",
962
+ "dispatch": {
963
+ "threads": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * (dim(shapes.outputT, 2) / 4)",
964
+ "workgroupSize": "constants.workgroupSize"
965
+ }
966
+ }
967
+ ]
968
+ },
969
+ {
970
+ "id": "state_no_bias_vec4",
971
+ "priority": 20,
972
+ "when": ["stateNoBiasContract", "kernelSize >= 2", "kernelSize <= 4", "dim(shapes.inputT, 2) >= 4", "dim(shapes.inputT, 2) % 4 == 0"],
973
+ "constants": {
974
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
975
+ "workgroupSize": 256,
976
+ "hasStateWindow": "windowed",
977
+ "usesF16": "tensorDtypes.inputT == \"float16\"",
978
+ "inputScalar": "dtypes.T",
979
+ "outputScalar": "dtypes.T",
980
+ "inputVec4": "\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\"",
981
+ "outputVec4": "\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\"",
982
+ "hasBias": false,
983
+ "hasState": true,
984
+ "kernelSize": "kernelSize",
985
+ "kernelSizePadded": "kernelSizePadded",
986
+ "weightElem": "(\"vec4<f16>\" if tensorDtypes.inputT == \"float16\" else \"vec4<f32>\") if kernelSize == 4 else dtypes.T"
987
+ },
988
+ "passes": [
989
+ {
990
+ "id": "main",
991
+ "name": "CausalConvWithState.Vec4",
992
+ "source": {
993
+ "shader": "causal-conv-with-state-vec4.wgsl.jinja",
994
+ "inputs": { "materializeConvBeforeActivation": false }
995
+ },
996
+ "bindings": "stateNoBiasVec4",
997
+ "dispatch": {
998
+ "threads": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * (dim(shapes.outputT, 2) / 4)",
999
+ "workgroupSize": "constants.workgroupSize"
1000
+ }
1001
+ }
1002
+ ]
1003
+ },
1004
+ {
1005
+ "id": "zero_state_tiled_large_kernel",
1006
+ "priority": 10,
1007
+ "when": ["zeroStateContract", "kernelSize >= 32", "dim(shapes.inputT, 2) >= 256", "dim(shapes.inputT, 2) % 8 == 0", "tunables.tiledWorkgroupSize >= 1", "floor(tunables.tiledWorkgroupSize) == tunables.tiledWorkgroupSize", "tunables.tiledWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.tiledWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "(tunables.tiledWorkgroupSize * 8 + 2 * kernelSizePadded - 1) * 4 <= device.limits.maxComputeWorkgroupStorageSize"],
1008
+ "constants": {
1009
+ "hasBias": false,
1010
+ "hasState": false,
1011
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
1012
+ "inputScalar": "dtypes.T",
1013
+ "outputScalar": "dtypes.T",
1014
+ "workgroupSize": "tunables.tiledWorkgroupSize",
1015
+ "tileSize": "tunables.tiledWorkgroupSize * 8",
1016
+ "kernelSize": "kernelSize",
1017
+ "kernelSizePadded": "kernelSizePadded",
1018
+ "inputTileSize": "tunables.tiledWorkgroupSize * 8 + kernelSizePadded - 1",
1019
+ "hasStateWindow": "windowed",
1020
+ "usesF16": "tensorDtypes.inputT == \"float16\""
1021
+ },
1022
+ "passes": [
1023
+ {
1024
+ "id": "main",
1025
+ "name": "CausalConvWithState.TiledLargeKernel",
1026
+ "source": {
1027
+ "shader": "causal-conv-with-state-tiled.wgsl.jinja",
1028
+ "inputs": { "materializeConvBeforeActivation": false }
1029
+ },
1030
+ "bindings": "zeroTiled",
1031
+ "dispatch": {
1032
+ "workgroups": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * ceilDiv(dim(shapes.outputT, 2), constants.tileSize)"
1033
+ }
1034
+ }
1035
+ ]
1036
+ },
1037
+ {
1038
+ "id": "state_bias_tiled_large_kernel",
1039
+ "priority": 10,
1040
+ "when": ["stateBiasContract", "kernelSize >= 32", "dim(shapes.inputT, 2) >= 256", "dim(shapes.inputT, 2) % 8 == 0", "tunables.tiledWorkgroupSize >= 1", "floor(tunables.tiledWorkgroupSize) == tunables.tiledWorkgroupSize", "tunables.tiledWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.tiledWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "(tunables.tiledWorkgroupSize * 8 + 2 * kernelSizePadded - 1) * 4 <= device.limits.maxComputeWorkgroupStorageSize"],
1041
+ "constants": {
1042
+ "hasBias": true,
1043
+ "hasState": true,
1044
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
1045
+ "inputScalar": "dtypes.T",
1046
+ "outputScalar": "dtypes.T",
1047
+ "workgroupSize": "tunables.tiledWorkgroupSize",
1048
+ "tileSize": "tunables.tiledWorkgroupSize * 8",
1049
+ "kernelSize": "kernelSize",
1050
+ "kernelSizePadded": "kernelSizePadded",
1051
+ "inputTileSize": "tunables.tiledWorkgroupSize * 8 + kernelSizePadded - 1",
1052
+ "hasStateWindow": "windowed",
1053
+ "usesF16": "tensorDtypes.inputT == \"float16\""
1054
+ },
1055
+ "passes": [
1056
+ {
1057
+ "id": "main",
1058
+ "name": "CausalConvWithState.TiledLargeKernel",
1059
+ "source": {
1060
+ "shader": "causal-conv-with-state-tiled.wgsl.jinja",
1061
+ "inputs": { "materializeConvBeforeActivation": false }
1062
+ },
1063
+ "bindings": "stateBiasTiled",
1064
+ "dispatch": {
1065
+ "workgroups": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * ceilDiv(dim(shapes.outputT, 2), constants.tileSize)"
1066
+ }
1067
+ }
1068
+ ]
1069
+ },
1070
+ {
1071
+ "id": "bias_no_state_tiled_large_kernel",
1072
+ "priority": 10,
1073
+ "when": ["biasNoStateContract", "kernelSize >= 32", "dim(shapes.inputT, 2) >= 256", "dim(shapes.inputT, 2) % 8 == 0", "tunables.tiledWorkgroupSize >= 1", "floor(tunables.tiledWorkgroupSize) == tunables.tiledWorkgroupSize", "tunables.tiledWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.tiledWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "(tunables.tiledWorkgroupSize * 8 + 2 * kernelSizePadded - 1) * 4 <= device.limits.maxComputeWorkgroupStorageSize"],
1074
+ "constants": {
1075
+ "hasBias": true,
1076
+ "hasState": false,
1077
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
1078
+ "inputScalar": "dtypes.T",
1079
+ "outputScalar": "dtypes.T",
1080
+ "workgroupSize": "tunables.tiledWorkgroupSize",
1081
+ "tileSize": "tunables.tiledWorkgroupSize * 8",
1082
+ "kernelSize": "kernelSize",
1083
+ "kernelSizePadded": "kernelSizePadded",
1084
+ "inputTileSize": "tunables.tiledWorkgroupSize * 8 + kernelSizePadded - 1",
1085
+ "hasStateWindow": "windowed",
1086
+ "usesF16": "tensorDtypes.inputT == \"float16\""
1087
+ },
1088
+ "passes": [
1089
+ {
1090
+ "id": "main",
1091
+ "name": "CausalConvWithState.TiledLargeKernel",
1092
+ "source": {
1093
+ "shader": "causal-conv-with-state-tiled.wgsl.jinja",
1094
+ "inputs": { "materializeConvBeforeActivation": false }
1095
+ },
1096
+ "bindings": "biasNoStateTiled",
1097
+ "dispatch": {
1098
+ "workgroups": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * ceilDiv(dim(shapes.outputT, 2), constants.tileSize)"
1099
+ }
1100
+ }
1101
+ ]
1102
+ },
1103
+ {
1104
+ "id": "state_no_bias_tiled_large_kernel",
1105
+ "priority": 10,
1106
+ "when": ["stateNoBiasContract", "kernelSize >= 32", "dim(shapes.inputT, 2) >= 256", "dim(shapes.inputT, 2) % 8 == 0", "tunables.tiledWorkgroupSize >= 1", "floor(tunables.tiledWorkgroupSize) == tunables.tiledWorkgroupSize", "tunables.tiledWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.tiledWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "(tunables.tiledWorkgroupSize * 8 + 2 * kernelSizePadded - 1) * 4 <= device.limits.maxComputeWorkgroupStorageSize"],
1107
+ "constants": {
1108
+ "hasBias": false,
1109
+ "hasState": true,
1110
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
1111
+ "inputScalar": "dtypes.T",
1112
+ "outputScalar": "dtypes.T",
1113
+ "workgroupSize": "tunables.tiledWorkgroupSize",
1114
+ "tileSize": "tunables.tiledWorkgroupSize * 8",
1115
+ "kernelSize": "kernelSize",
1116
+ "kernelSizePadded": "kernelSizePadded",
1117
+ "inputTileSize": "tunables.tiledWorkgroupSize * 8 + kernelSizePadded - 1",
1118
+ "hasStateWindow": "windowed",
1119
+ "usesF16": "tensorDtypes.inputT == \"float16\""
1120
+ },
1121
+ "passes": [
1122
+ {
1123
+ "id": "main",
1124
+ "name": "CausalConvWithState.TiledLargeKernel",
1125
+ "source": {
1126
+ "shader": "causal-conv-with-state-tiled.wgsl.jinja",
1127
+ "inputs": { "materializeConvBeforeActivation": false }
1128
+ },
1129
+ "bindings": "stateNoBiasTiled",
1130
+ "dispatch": {
1131
+ "workgroups": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * ceilDiv(dim(shapes.outputT, 2), constants.tileSize)"
1132
+ }
1133
+ }
1134
+ ]
1135
+ },
1136
+ {
1137
+ "id": "zero_state",
1138
+ "priority": 0,
1139
+ "when": ["zeroStateContract"],
1140
+ "constants": {
1141
+ "hasBias": false,
1142
+ "hasState": false,
1143
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
1144
+ "inputScalar": "dtypes.T",
1145
+ "outputScalar": "dtypes.T",
1146
+ "workgroupSize": "tunables.workgroupSize",
1147
+ "hasStateWindow": "windowed",
1148
+ "usesF16": "tensorDtypes.inputT == \"float16\""
1149
+ },
1150
+ "passes": [
1151
+ {
1152
+ "id": "main",
1153
+ "name": "CausalConvWithState",
1154
+ "source": {
1155
+ "shader": "causal-conv-with-state.wgsl.jinja",
1156
+ "inputs": { "materializeConvBeforeActivation": false }
1157
+ },
1158
+ "bindings": "zeroScalar",
1159
+ "dispatch": {
1160
+ "threads": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * max(1, dim(shapes.outputT, 2))",
1161
+ "workgroupSize": "constants.workgroupSize"
1162
+ }
1163
+ }
1164
+ ]
1165
+ },
1166
+ {
1167
+ "id": "state_bias",
1168
+ "priority": 0,
1169
+ "when": ["stateBiasContract"],
1170
+ "constants": {
1171
+ "hasBias": true,
1172
+ "hasState": true,
1173
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
1174
+ "inputScalar": "dtypes.T",
1175
+ "outputScalar": "dtypes.T",
1176
+ "workgroupSize": "tunables.workgroupSize",
1177
+ "hasStateWindow": "windowed",
1178
+ "usesF16": "tensorDtypes.inputT == \"float16\""
1179
+ },
1180
+ "passes": [
1181
+ {
1182
+ "id": "main",
1183
+ "name": "CausalConvWithState",
1184
+ "source": {
1185
+ "shader": "causal-conv-with-state.wgsl.jinja",
1186
+ "inputs": { "materializeConvBeforeActivation": false }
1187
+ },
1188
+ "bindings": "stateBias",
1189
+ "dispatch": {
1190
+ "threads": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * max(1, dim(shapes.outputT, 2))",
1191
+ "workgroupSize": "constants.workgroupSize"
1192
+ }
1193
+ }
1194
+ ]
1195
+ },
1196
+ {
1197
+ "id": "bias_no_state",
1198
+ "priority": 0,
1199
+ "when": ["biasNoStateContract"],
1200
+ "constants": {
1201
+ "hasBias": true,
1202
+ "hasState": false,
1203
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
1204
+ "inputScalar": "dtypes.T",
1205
+ "outputScalar": "dtypes.T",
1206
+ "workgroupSize": "tunables.workgroupSize",
1207
+ "hasStateWindow": "windowed",
1208
+ "usesF16": "tensorDtypes.inputT == \"float16\""
1209
+ },
1210
+ "passes": [
1211
+ {
1212
+ "id": "main",
1213
+ "name": "CausalConvWithState",
1214
+ "source": {
1215
+ "shader": "causal-conv-with-state.wgsl.jinja",
1216
+ "inputs": { "materializeConvBeforeActivation": false }
1217
+ },
1218
+ "bindings": "biasNoState",
1219
+ "dispatch": {
1220
+ "threads": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * max(1, dim(shapes.outputT, 2))",
1221
+ "workgroupSize": "constants.workgroupSize"
1222
+ }
1223
+ }
1224
+ ]
1225
+ },
1226
+ {
1227
+ "id": "state_no_bias",
1228
+ "priority": 0,
1229
+ "when": ["stateNoBiasContract"],
1230
+ "constants": {
1231
+ "hasBias": false,
1232
+ "hasState": true,
1233
+ "useSilu": "attrs.activation == \"silu\" or attrs.activation == \"swish\"",
1234
+ "inputScalar": "dtypes.T",
1235
+ "outputScalar": "dtypes.T",
1236
+ "workgroupSize": "tunables.workgroupSize",
1237
+ "hasStateWindow": "windowed",
1238
+ "usesF16": "tensorDtypes.inputT == \"float16\""
1239
+ },
1240
+ "passes": [
1241
+ {
1242
+ "id": "main",
1243
+ "name": "CausalConvWithState",
1244
+ "source": {
1245
+ "shader": "causal-conv-with-state.wgsl.jinja",
1246
+ "inputs": { "materializeConvBeforeActivation": false }
1247
+ },
1248
+ "bindings": "stateNoBias",
1249
+ "dispatch": {
1250
+ "threads": "dim(shapes.outputT, 0) * dim(shapes.outputT, 1) * max(1, dim(shapes.outputT, 2))",
1251
+ "workgroupSize": "constants.workgroupSize"
1252
+ }
1253
+ }
1254
+ ]
1255
+ }
1256
+ ]
1257
+ }
build/webgpu/metadata.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "com.microsoft.CausalConvWithState",
3
+ "id": "_com_microsoft_causalconvwithstate_webgpu_9e6e59f",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "backend": { "type": "webgpu" },
7
+ "digest": {
8
+ "algorithm": "sha256",
9
+ "files": {
10
+ "bench.json": "JZU8nd2+4ByxWEyHozqDzF2xGDNwA4gaZ1jk71H/kF0=",
11
+ "causal-conv-with-state-tiled.wgsl.jinja": "3AcQURBK9/4LFE/TCfWxDMIAMsjLIVcfsZ9dK/qlzGk=",
12
+ "causal-conv-with-state-vec4.wgsl.jinja": "jjKAFL4nTGXXrRLF+TyBiJO4fNy0bEF1gK0KfIGeRoc=",
13
+ "causal-conv-with-state.wgsl.jinja": "B03ROsgmw6YXaTQ6373ibBbKyt7lxTBThsR7ThfyXVU=",
14
+ "manifest.json": "sR2aWi0R4vk7io6t9uwLdcVyP8jdQ5PIA0QHMHKQkaU=",
15
+ "test.json": "oC4aXSiNHpXHdk6nE+nXhAZvkGulY8eJOcfiXZ0jXdw="
16
+ }
17
+ },
18
+ "provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
19
+ "webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/com.microsoft.CausalConvWithState" }
20
+ }
build/webgpu/test.json ADDED
@@ -0,0 +1,1283 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "com.microsoft.CausalConvWithState",
3
+ "cases": [
4
+ {
5
+ "name": "ort_kernel1_zero_size_state",
6
+ "provenance": {
7
+ "source": "onnxruntime/test/python/transformers/test_parity_linear_attention_causal_conv.py",
8
+ "test": "TestLinearAttentionCausalConvCPUParity.test_causal_conv_with_state_cpu_kernel_1",
9
+ "notes": "Direct standard rank-3 weight fixture for the ORT kernel=1 zero-size state edge case."
10
+ },
11
+ "attrs": { "activation": "silu" },
12
+ "inputs": {
13
+ "inputT": {
14
+ "dtype": "float32",
15
+ "shape": [2, 4, 5],
16
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
17
+ },
18
+ "weightT": {
19
+ "dtype": "float32",
20
+ "shape": [4, 1, 1],
21
+ "data": { "kind": "values", "values": [0.5, -1.0, 1.5, -0.25] }
22
+ },
23
+ "biasT": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.25, -0.5, 0.75, -1.0] } },
24
+ "pastStateT": { "dtype": "float32", "shape": [2, 4, 0], "data": { "kind": "values", "values": [] } }
25
+ },
26
+ "outputs": {
27
+ "outputT": { "dtype": "float32", "shape": [2, 4, 5], "tolerance": 0.00001 },
28
+ "presentStateT": { "dtype": "float32", "shape": [2, 4, 0], "tolerance": 0 }
29
+ }
30
+ },
31
+ {
32
+ "name": "ort_basic_no_state_no_bias",
33
+ "provenance": {
34
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
35
+ "test": "CausalConvWithStateTest.BasicNoStateNoBias",
36
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
37
+ },
38
+ "attrs": { "activation": "none" },
39
+ "inputs": {
40
+ "inputT": {
41
+ "dtype": "float32",
42
+ "shape": [1, 2, 4],
43
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 0.5, 1.5, 2.5, 3.5] }
44
+ },
45
+ "weightT": {
46
+ "dtype": "float32",
47
+ "shape": [2, 1, 3],
48
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
49
+ }
50
+ },
51
+ "outputs": {
52
+ "outputT": { "dtype": "float32", "shape": [1, 2, 4], "tolerance": 0.00001 },
53
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 2], "tolerance": 0.000001 }
54
+ }
55
+ },
56
+ {
57
+ "name": "ort_silu_with_bias_and_state",
58
+ "provenance": {
59
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
60
+ "test": "CausalConvWithStateTest.SiluActivationWithBiasAndState",
61
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
62
+ },
63
+ "attrs": { "activation": "silu" },
64
+ "inputs": {
65
+ "inputT": {
66
+ "dtype": "float32",
67
+ "shape": [1, 2, 4],
68
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 0.5, 1.5, 2.5, 3.5] }
69
+ },
70
+ "weightT": {
71
+ "dtype": "float32",
72
+ "shape": [2, 1, 3],
73
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
74
+ },
75
+ "biasT": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.1, -0.2] } },
76
+ "pastStateT": {
77
+ "dtype": "float32",
78
+ "shape": [1, 2, 2],
79
+ "data": { "kind": "values", "values": [-1.0, 0.5, 0.3, -0.7] }
80
+ }
81
+ },
82
+ "outputs": {
83
+ "outputT": { "dtype": "float32", "shape": [1, 2, 4], "tolerance": 0.00001 },
84
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 2], "tolerance": 0.000001 }
85
+ }
86
+ },
87
+ {
88
+ "name": "ort_basic_with_bias",
89
+ "provenance": {
90
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
91
+ "test": "CausalConvWithStateTest.BasicWithBias",
92
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
93
+ },
94
+ "attrs": { "activation": "none" },
95
+ "inputs": {
96
+ "inputT": {
97
+ "dtype": "float32",
98
+ "shape": [1, 2, 4],
99
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 0.5, 1.5, 2.5, 3.5] }
100
+ },
101
+ "weightT": {
102
+ "dtype": "float32",
103
+ "shape": [2, 1, 3],
104
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
105
+ },
106
+ "biasT": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.1, -0.2] } }
107
+ },
108
+ "outputs": {
109
+ "outputT": { "dtype": "float32", "shape": [1, 2, 4], "tolerance": 0.00001 },
110
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 2], "tolerance": 0.000001 }
111
+ }
112
+ },
113
+ {
114
+ "name": "ort_basic_with_state",
115
+ "provenance": {
116
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
117
+ "test": "CausalConvWithStateTest.BasicWithState",
118
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
119
+ },
120
+ "attrs": { "activation": "none" },
121
+ "inputs": {
122
+ "inputT": {
123
+ "dtype": "float32",
124
+ "shape": [1, 2, 3],
125
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 0.5, 1.5, 2.5] }
126
+ },
127
+ "weightT": {
128
+ "dtype": "float32",
129
+ "shape": [2, 1, 3],
130
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
131
+ },
132
+ "pastStateT": {
133
+ "dtype": "float32",
134
+ "shape": [1, 2, 2],
135
+ "data": { "kind": "values", "values": [-1.0, 0.5, 0.3, -0.7] }
136
+ }
137
+ },
138
+ "outputs": {
139
+ "outputT": { "dtype": "float32", "shape": [1, 2, 3], "tolerance": 0.00001 },
140
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 2], "tolerance": 0.000001 }
141
+ }
142
+ },
143
+ {
144
+ "name": "ort_with_state_and_bias_none",
145
+ "provenance": {
146
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
147
+ "test": "CausalConvWithStateTest.WithStateAndBias",
148
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
149
+ },
150
+ "attrs": { "activation": "none" },
151
+ "inputs": {
152
+ "inputT": {
153
+ "dtype": "float32",
154
+ "shape": [1, 2, 3],
155
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 0.5, 1.5, 2.5] }
156
+ },
157
+ "weightT": {
158
+ "dtype": "float32",
159
+ "shape": [2, 1, 3],
160
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
161
+ },
162
+ "biasT": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.1, -0.2] } },
163
+ "pastStateT": {
164
+ "dtype": "float32",
165
+ "shape": [1, 2, 2],
166
+ "data": { "kind": "values", "values": [-1.0, 0.5, 0.3, -0.7] }
167
+ }
168
+ },
169
+ "outputs": {
170
+ "outputT": { "dtype": "float32", "shape": [1, 2, 3], "tolerance": 0.00001 },
171
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 2], "tolerance": 0.000001 }
172
+ }
173
+ },
174
+ {
175
+ "name": "ort_silu_no_state",
176
+ "provenance": {
177
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
178
+ "test": "CausalConvWithStateTest.SiluActivationNoState",
179
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
180
+ },
181
+ "attrs": { "activation": "silu" },
182
+ "inputs": {
183
+ "inputT": {
184
+ "dtype": "float32",
185
+ "shape": [1, 2, 4],
186
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 0.5, 1.5, 2.5, 3.5] }
187
+ },
188
+ "weightT": {
189
+ "dtype": "float32",
190
+ "shape": [2, 1, 3],
191
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
192
+ }
193
+ },
194
+ "outputs": {
195
+ "outputT": { "dtype": "float32", "shape": [1, 2, 4], "tolerance": 0.00001 },
196
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 2], "tolerance": 0.000001 }
197
+ }
198
+ },
199
+ {
200
+ "name": "ort_silu_with_state",
201
+ "provenance": {
202
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
203
+ "test": "CausalConvWithStateTest.SiluActivationWithState",
204
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
205
+ },
206
+ "attrs": { "activation": "silu" },
207
+ "inputs": {
208
+ "inputT": {
209
+ "dtype": "float32",
210
+ "shape": [1, 2, 3],
211
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 0.5, 1.5, 2.5] }
212
+ },
213
+ "weightT": {
214
+ "dtype": "float32",
215
+ "shape": [2, 1, 3],
216
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
217
+ },
218
+ "pastStateT": {
219
+ "dtype": "float32",
220
+ "shape": [1, 2, 2],
221
+ "data": { "kind": "values", "values": [-1.0, 0.5, 0.3, -0.7] }
222
+ }
223
+ },
224
+ "outputs": {
225
+ "outputT": { "dtype": "float32", "shape": [1, 2, 3], "tolerance": 0.00001 },
226
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 2], "tolerance": 0.000001 }
227
+ }
228
+ },
229
+ {
230
+ "name": "ort_kernel_size2_state_silu",
231
+ "provenance": {
232
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
233
+ "test": "CausalConvWithStateTest.KernelSize2",
234
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
235
+ },
236
+ "attrs": { "activation": "silu" },
237
+ "inputs": {
238
+ "inputT": {
239
+ "dtype": "float32",
240
+ "shape": [1, 2, 4],
241
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 0.5, 1.5, 2.5, 3.5] }
242
+ },
243
+ "weightT": {
244
+ "dtype": "float32",
245
+ "shape": [2, 1, 2],
246
+ "data": { "kind": "values", "values": [0.3, 0.7, 0.4, 0.6] }
247
+ },
248
+ "pastStateT": { "dtype": "float32", "shape": [1, 2, 1], "data": { "kind": "values", "values": [0.5, -0.3] } }
249
+ },
250
+ "outputs": {
251
+ "outputT": { "dtype": "float32", "shape": [1, 2, 4], "tolerance": 0.00001 },
252
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 1], "tolerance": 0.000001 }
253
+ }
254
+ },
255
+ {
256
+ "name": "ort_kernel_size4_state_none",
257
+ "provenance": {
258
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
259
+ "test": "CausalConvWithStateTest.KernelSize4",
260
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
261
+ },
262
+ "attrs": { "activation": "none" },
263
+ "inputs": {
264
+ "inputT": {
265
+ "dtype": "float32",
266
+ "shape": [1, 1, 5],
267
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0] }
268
+ },
269
+ "weightT": {
270
+ "dtype": "float32",
271
+ "shape": [1, 1, 4],
272
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4] }
273
+ },
274
+ "pastStateT": {
275
+ "dtype": "float32",
276
+ "shape": [1, 1, 3],
277
+ "data": { "kind": "values", "values": [-1.0, 0.0, 0.5] }
278
+ }
279
+ },
280
+ "outputs": {
281
+ "outputT": { "dtype": "float32", "shape": [1, 1, 5], "tolerance": 0.00001 },
282
+ "presentStateT": { "dtype": "float32", "shape": [1, 1, 3], "tolerance": 0.000001 }
283
+ }
284
+ },
285
+ {
286
+ "name": "ort_multi_batch_state_bias_silu",
287
+ "provenance": {
288
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
289
+ "test": "CausalConvWithStateTest.MultiBatch",
290
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
291
+ },
292
+ "attrs": { "activation": "silu" },
293
+ "inputs": {
294
+ "inputT": {
295
+ "dtype": "float32",
296
+ "shape": [2, 2, 3],
297
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 0.5, 1.5, 2.5, -1.0, 0.0, 1.0, 0.2, 0.4, 0.6] }
298
+ },
299
+ "weightT": {
300
+ "dtype": "float32",
301
+ "shape": [2, 1, 3],
302
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
303
+ },
304
+ "biasT": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.1, -0.1] } },
305
+ "pastStateT": {
306
+ "dtype": "float32",
307
+ "shape": [2, 2, 2],
308
+ "data": { "kind": "values", "values": [-0.5, 0.5, 0.3, -0.3, 0.1, -0.1, 0.7, 0.8] }
309
+ }
310
+ },
311
+ "outputs": {
312
+ "outputT": { "dtype": "float32", "shape": [2, 2, 3], "tolerance": 0.00001 },
313
+ "presentStateT": { "dtype": "float32", "shape": [2, 2, 2], "tolerance": 0.000001 }
314
+ }
315
+ },
316
+ {
317
+ "name": "ort_single_token_decode_state_bias_silu",
318
+ "provenance": {
319
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
320
+ "test": "CausalConvWithStateTest.SingleTokenDecode",
321
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
322
+ },
323
+ "attrs": { "activation": "silu" },
324
+ "inputs": {
325
+ "inputT": {
326
+ "dtype": "float32",
327
+ "shape": [1, 4, 1],
328
+ "data": { "kind": "values", "values": [0.5, -0.3, 1.2, 0.8] }
329
+ },
330
+ "weightT": {
331
+ "dtype": "float32",
332
+ "shape": [4, 1, 4],
333
+ "data": {
334
+ "kind": "values",
335
+ "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, -0.1, -0.2, 0.1, 0.2, 0.3, 0.3, 0.3, 0.3]
336
+ }
337
+ },
338
+ "biasT": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.0, 0.1, -0.1, 0.0] } },
339
+ "pastStateT": {
340
+ "dtype": "float32",
341
+ "shape": [1, 4, 3],
342
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, -1.0, 0.0, 1.0, 0.5, 0.5, 0.5, -0.2, 0.4, -0.6] }
343
+ }
344
+ },
345
+ "outputs": {
346
+ "outputT": { "dtype": "float32", "shape": [1, 4, 1], "tolerance": 0.00001 },
347
+ "presentStateT": { "dtype": "float32", "shape": [1, 4, 3], "tolerance": 0.000001 }
348
+ }
349
+ },
350
+ {
351
+ "name": "ort_single_token_decode_multi_batch_silu",
352
+ "provenance": {
353
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
354
+ "test": "CausalConvWithStateTest.SingleTokenDecodeMultiBatch",
355
+ "notes": "Direct ORT depthwise weight shape [D,1,K]."
356
+ },
357
+ "attrs": { "activation": "silu" },
358
+ "inputs": {
359
+ "inputT": {
360
+ "dtype": "float32",
361
+ "shape": [2, 2, 1],
362
+ "data": { "kind": "values", "values": [0.5, -0.3, 1.2, 0.8] }
363
+ },
364
+ "weightT": {
365
+ "dtype": "float32",
366
+ "shape": [2, 1, 3],
367
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
368
+ },
369
+ "pastStateT": {
370
+ "dtype": "float32",
371
+ "shape": [2, 2, 2],
372
+ "data": { "kind": "values", "values": [1.0, 2.0, -1.0, 0.0, 0.5, 0.5, -0.2, 0.4] }
373
+ }
374
+ },
375
+ "outputs": {
376
+ "outputT": { "dtype": "float32", "shape": [2, 2, 1], "tolerance": 0.00001 },
377
+ "presentStateT": { "dtype": "float32", "shape": [2, 2, 2], "tolerance": 0.000001 }
378
+ }
379
+ },
380
+ {
381
+ "name": "zero_state",
382
+ "attrs": { "activation": "none" },
383
+ "inputs": {
384
+ "inputT": {
385
+ "dtype": "float32",
386
+ "shape": [1, 3, 5],
387
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
388
+ },
389
+ "weightT": {
390
+ "dtype": "float32",
391
+ "shape": [3, 1, 3],
392
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
393
+ }
394
+ },
395
+ "outputs": {
396
+ "outputT": { "dtype": "float32", "shape": [1, 3, 5], "tolerance": 0.00001 },
397
+ "presentStateT": { "dtype": "float32", "shape": [1, 3, 2], "tolerance": 0.000001 }
398
+ }
399
+ },
400
+ {
401
+ "name": "scalar_bias_no_state_odd_length",
402
+ "attrs": { "activation": "none" },
403
+ "inputs": {
404
+ "inputT": {
405
+ "dtype": "float32",
406
+ "shape": [1, 3, 5],
407
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
408
+ },
409
+ "weightT": {
410
+ "dtype": "float32",
411
+ "shape": [3, 1, 3],
412
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
413
+ },
414
+ "biasT": {
415
+ "dtype": "float32",
416
+ "shape": [3],
417
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
418
+ }
419
+ },
420
+ "outputs": {
421
+ "outputT": { "dtype": "float32", "shape": [1, 3, 5], "tolerance": 0.00001 },
422
+ "presentStateT": { "dtype": "float32", "shape": [1, 3, 2], "tolerance": 0.000001 }
423
+ },
424
+ "provenance": {
425
+ "notes": "Odd sequence length keeps the bias/no-state scalar fallback covered when the vec4 route is ineligible."
426
+ }
427
+ },
428
+ {
429
+ "name": "state_bias_silu",
430
+ "attrs": { "activation": "silu" },
431
+ "inputs": {
432
+ "inputT": {
433
+ "dtype": "float32",
434
+ "shape": [2, 2, 4],
435
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
436
+ },
437
+ "weightT": {
438
+ "dtype": "float32",
439
+ "shape": [2, 1, 4],
440
+ "data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
441
+ },
442
+ "biasT": {
443
+ "dtype": "float32",
444
+ "shape": [2],
445
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
446
+ },
447
+ "pastStateT": {
448
+ "dtype": "float32",
449
+ "shape": [2, 2, 3],
450
+ "data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.13 }
451
+ }
452
+ },
453
+ "outputs": {
454
+ "outputT": { "dtype": "float32", "shape": [2, 2, 4], "tolerance": 0.00001 },
455
+ "presentStateT": { "dtype": "float32", "shape": [2, 2, 3], "tolerance": 0.000001 }
456
+ }
457
+ },
458
+ {
459
+ "name": "vec4_bias_no_state_silu",
460
+ "attrs": { "activation": "silu" },
461
+ "inputs": {
462
+ "inputT": {
463
+ "dtype": "float32",
464
+ "shape": [2, 2, 4],
465
+ "data": { "kind": "fillFloat32", "sinStep": 0.24, "cosStep": 0.31 }
466
+ },
467
+ "weightT": {
468
+ "dtype": "float32",
469
+ "shape": [2, 1, 4],
470
+ "data": { "kind": "fillFloat32", "sinStep": 0.18, "cosStep": 0.23 }
471
+ },
472
+ "biasT": {
473
+ "dtype": "float32",
474
+ "shape": [2],
475
+ "data": { "kind": "fillFloat32", "sinStep": 0.14, "cosStep": 0.41 }
476
+ }
477
+ },
478
+ "outputs": {
479
+ "outputT": { "dtype": "float32", "shape": [2, 2, 4], "tolerance": 0.00001 },
480
+ "presentStateT": { "dtype": "float32", "shape": [2, 2, 3], "tolerance": 0.000001 }
481
+ },
482
+ "provenance": {
483
+ "notes": "Kernel 4 over a length that divides into vec4 lanes, with a bias and no carried state: the vectorized arm where the first lane's taps are the zero prefix rather than past_state."
484
+ }
485
+ },
486
+ {
487
+ "name": "vec4_state_no_bias_silu",
488
+ "attrs": { "activation": "silu" },
489
+ "inputs": {
490
+ "inputT": {
491
+ "dtype": "float32",
492
+ "shape": [2, 2, 4],
493
+ "data": { "kind": "fillFloat32", "sinStep": 0.28, "cosStep": 0.31 }
494
+ },
495
+ "weightT": {
496
+ "dtype": "float32",
497
+ "shape": [2, 1, 4],
498
+ "data": { "kind": "fillFloat32", "sinStep": 0.22, "cosStep": 0.23 }
499
+ },
500
+ "pastStateT": {
501
+ "dtype": "float32",
502
+ "shape": [2, 2, 3],
503
+ "data": { "kind": "fillFloat32", "sinStep": 0.3, "cosStep": 0.13 }
504
+ }
505
+ },
506
+ "outputs": {
507
+ "outputT": { "dtype": "float32", "shape": [2, 2, 4], "tolerance": 0.00001 },
508
+ "presentStateT": { "dtype": "float32", "shape": [2, 2, 3], "tolerance": 0.000001 }
509
+ },
510
+ "provenance": {
511
+ "notes": "Kernel 4 over a length that divides into vec4 lanes, with carried state and no bias: the vectorized arm that reads past_state into the first lane's taps but adds no bias term."
512
+ }
513
+ },
514
+ {
515
+ "name": "ort_larger_dimensions_state_bias_silu",
516
+ "provenance": {
517
+ "source": "onnxruntime/test/contrib_ops/causal_conv_with_state_op_test.cc",
518
+ "test": "CausalConvWithStateTest.LargerDimensions",
519
+ "notes": "Compact deterministic projection of ORT's larger-dimension state+bias SiLU stress case."
520
+ },
521
+ "attrs": { "activation": "silu" },
522
+ "inputs": {
523
+ "inputT": {
524
+ "dtype": "float32",
525
+ "shape": [2, 8, 16],
526
+ "data": { "kind": "fillFloat32", "scale": 0.4, "sinStep": 0.1, "cosStep": 0.0 }
527
+ },
528
+ "weightT": {
529
+ "dtype": "float32",
530
+ "shape": [8, 1, 4],
531
+ "data": { "kind": "fillFloat32", "scale": 0.5, "sinStep": 0.0, "cosStep": 0.2 }
532
+ },
533
+ "biasT": {
534
+ "dtype": "float32",
535
+ "shape": [8],
536
+ "data": { "kind": "values", "values": [0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07] }
537
+ },
538
+ "pastStateT": {
539
+ "dtype": "float32",
540
+ "shape": [2, 8, 3],
541
+ "data": { "kind": "fillFloat32", "scale": 0.5, "sinStep": 0.3, "cosStep": 0.0 }
542
+ }
543
+ },
544
+ "outputs": {
545
+ "outputT": { "dtype": "float32", "shape": [2, 8, 16], "tolerance": 0.00002 },
546
+ "presentStateT": { "dtype": "float32", "shape": [2, 8, 3], "tolerance": 0.000001 }
547
+ }
548
+ },
549
+ {
550
+ "name": "zero_length_present_state_carryover_dropped",
551
+ "attrs": { "activation": "none" },
552
+ "inputs": {
553
+ "inputT": { "dtype": "float32", "shape": [1, 2, 0], "data": { "kind": "values", "values": [] } },
554
+ "weightT": {
555
+ "dtype": "float32",
556
+ "shape": [2, 1, 3],
557
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }
558
+ },
559
+ "pastStateT": {
560
+ "dtype": "float32",
561
+ "shape": [1, 2, 2],
562
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] }
563
+ }
564
+ },
565
+ "outputs": {
566
+ "outputT": {
567
+ "dtype": "float32",
568
+ "shape": [1, 2, 0],
569
+ "data": { "kind": "values", "values": [] },
570
+ "tolerance": 0
571
+ },
572
+ "presentStateT": {
573
+ "dtype": "float32",
574
+ "shape": [1, 2, 2],
575
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] },
576
+ "tolerance": 0
577
+ }
578
+ }
579
+ },
580
+ {
581
+ "name": "length_shorter_than_state_with_past_silu",
582
+ "attrs": { "activation": "silu" },
583
+ "inputs": {
584
+ "inputT": {
585
+ "dtype": "float32",
586
+ "shape": [1, 2, 2],
587
+ "data": { "kind": "values", "values": [1.0, -2.0, 0.5, 3.0] }
588
+ },
589
+ "weightT": {
590
+ "dtype": "float32",
591
+ "shape": [2, 1, 5],
592
+ "data": { "kind": "values", "values": [0.1, 0.2, 0.3, 0.4, 0.5, -0.1, -0.2, 0.15, 0.25, 0.35] }
593
+ },
594
+ "pastStateT": {
595
+ "dtype": "float32",
596
+ "shape": [1, 2, 4],
597
+ "data": { "kind": "values", "values": [-1.0, 0.5, 0.3, -0.7, 0.2, -0.4, 0.6, -0.8] }
598
+ }
599
+ },
600
+ "outputs": {
601
+ "outputT": { "dtype": "float32", "shape": [1, 2, 2], "tolerance": 0.00001 },
602
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 4], "tolerance": 0.000001 }
603
+ }
604
+ },
605
+ {
606
+ "name": "length_shorter_than_state_no_state_zero_pad",
607
+ "attrs": { "activation": "none" },
608
+ "inputs": {
609
+ "inputT": {
610
+ "dtype": "float32",
611
+ "shape": [1, 2, 2],
612
+ "data": { "kind": "values", "values": [2.0, -1.0, 0.5, 4.0] }
613
+ },
614
+ "weightT": {
615
+ "dtype": "float32",
616
+ "shape": [2, 1, 4],
617
+ "data": { "kind": "values", "values": [0.25, 0.5, -0.5, 1.0, 0.1, 0.2, 0.3, 0.4] }
618
+ }
619
+ },
620
+ "outputs": {
621
+ "outputT": { "dtype": "float32", "shape": [1, 2, 2], "tolerance": 0.00001 },
622
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 3], "tolerance": 0.000001 }
623
+ }
624
+ },
625
+ {
626
+ "name": "vec4_zero_state_silu_compact",
627
+ "provenance": {
628
+ "notes": "Compact correctness lock for the aligned K=4 vec4 prefill path, including causal zero padding, SiLU, multi-batch rows, and present-state tails."
629
+ },
630
+ "attrs": { "activation": "silu" },
631
+ "inputs": {
632
+ "inputT": {
633
+ "dtype": "float32",
634
+ "shape": [2, 3, 8],
635
+ "data": { "kind": "fillFloat32", "scale": 0.4, "sinStep": 0.17, "cosStep": 0.31 }
636
+ },
637
+ "weightT": {
638
+ "dtype": "float32",
639
+ "shape": [3, 1, 4],
640
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.11, "cosStep": 0.23 }
641
+ }
642
+ },
643
+ "outputs": {
644
+ "outputT": { "dtype": "float32", "shape": [2, 3, 8], "tolerance": 0.00002 },
645
+ "presentStateT": { "dtype": "float32", "shape": [2, 3, 3], "tolerance": 0.000001 }
646
+ }
647
+ },
648
+ {
649
+ "name": "large_kernel_tiled_zero_state_compact",
650
+ "provenance": {
651
+ "notes": "Compact correctness lock for the workgroup-tiled large-kernel prefill path and its cooperative present-state update."
652
+ },
653
+ "attrs": { "activation": "none" },
654
+ "inputs": {
655
+ "inputT": {
656
+ "dtype": "float32",
657
+ "shape": [1, 2, 256],
658
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
659
+ },
660
+ "weightT": {
661
+ "dtype": "float32",
662
+ "shape": [2, 1, 32],
663
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
664
+ }
665
+ },
666
+ "outputs": {
667
+ "outputT": { "dtype": "float32", "shape": [1, 2, 256], "tolerance": 0.00005 },
668
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 31], "tolerance": 0.000001 }
669
+ }
670
+ },
671
+ {
672
+ "name": "large_kernel_tiled_bias_no_state_compact",
673
+ "provenance": {
674
+ "notes": "Compact correctness lock for the bias-only specialization of the workgroup-tiled large-kernel prefill path."
675
+ },
676
+ "attrs": { "activation": "silu" },
677
+ "inputs": {
678
+ "inputT": {
679
+ "dtype": "float32",
680
+ "shape": [1, 1, 256],
681
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
682
+ },
683
+ "weightT": {
684
+ "dtype": "float32",
685
+ "shape": [1, 1, 32],
686
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
687
+ },
688
+ "biasT": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.125] } }
689
+ },
690
+ "outputs": {
691
+ "outputT": { "dtype": "float32", "shape": [1, 1, 256], "tolerance": 0.00005 },
692
+ "presentStateT": { "dtype": "float32", "shape": [1, 1, 31], "tolerance": 0.000001 }
693
+ }
694
+ },
695
+ {
696
+ "name": "large_kernel_tiled_state_no_bias_compact",
697
+ "provenance": {
698
+ "notes": "Compact correctness lock for the carry-state specialization of the workgroup-tiled large-kernel prefill path."
699
+ },
700
+ "attrs": { "activation": "none" },
701
+ "inputs": {
702
+ "inputT": {
703
+ "dtype": "float32",
704
+ "shape": [1, 1, 256],
705
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
706
+ },
707
+ "weightT": {
708
+ "dtype": "float32",
709
+ "shape": [1, 1, 32],
710
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
711
+ },
712
+ "pastStateT": {
713
+ "dtype": "float32",
714
+ "shape": [1, 1, 31],
715
+ "data": { "kind": "fillFloat32", "scale": 0.15, "sinStep": 0.027, "cosStep": 0.019 }
716
+ }
717
+ },
718
+ "outputs": {
719
+ "outputT": { "dtype": "float32", "shape": [1, 1, 256], "tolerance": 0.00005 },
720
+ "presentStateT": { "dtype": "float32", "shape": [1, 1, 31], "tolerance": 0.000001 }
721
+ }
722
+ },
723
+ {
724
+ "name": "large_kernel_tiled_state_bias_silu_compact",
725
+ "provenance": {
726
+ "notes": "Compact correctness lock for the carry-state, bias, and SiLU specialization used by the production-shape fixture."
727
+ },
728
+ "attrs": { "activation": "silu" },
729
+ "inputs": {
730
+ "inputT": {
731
+ "dtype": "float32",
732
+ "shape": [1, 1, 256],
733
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
734
+ },
735
+ "weightT": {
736
+ "dtype": "float32",
737
+ "shape": [1, 1, 32],
738
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
739
+ },
740
+ "biasT": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [-0.075] } },
741
+ "pastStateT": {
742
+ "dtype": "float32",
743
+ "shape": [1, 1, 31],
744
+ "data": { "kind": "fillFloat32", "scale": 0.15, "sinStep": 0.027, "cosStep": 0.019 }
745
+ }
746
+ },
747
+ "outputs": {
748
+ "outputT": { "dtype": "float32", "shape": [1, 1, 256], "tolerance": 0.00005 },
749
+ "presentStateT": { "dtype": "float32", "shape": [1, 1, 31], "tolerance": 0.000001 }
750
+ }
751
+ },
752
+ {
753
+ "name": "large_kernel_tiled_state_bias_k128_wg64_multitile",
754
+ "provenance": {
755
+ "notes": "Smallest swept workgroup at the production kernel size; length 520 forces a partial second output tile."
756
+ },
757
+ "attrs": { "activation": "silu" },
758
+ "tunables": { "tiledWorkgroupSize": 64 },
759
+ "inputs": {
760
+ "inputT": {
761
+ "dtype": "float32",
762
+ "shape": [1, 1, 520],
763
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
764
+ },
765
+ "weightT": {
766
+ "dtype": "float32",
767
+ "shape": [1, 1, 128],
768
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
769
+ },
770
+ "biasT": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [-0.075] } },
771
+ "pastStateT": {
772
+ "dtype": "float32",
773
+ "shape": [1, 1, 127],
774
+ "data": { "kind": "fillFloat32", "scale": 0.15, "sinStep": 0.027, "cosStep": 0.019 }
775
+ }
776
+ },
777
+ "outputs": {
778
+ "outputT": { "dtype": "float32", "shape": [1, 1, 520], "tolerance": 0.0001 },
779
+ "presentStateT": { "dtype": "float32", "shape": [1, 1, 127], "tolerance": 0.000001 }
780
+ }
781
+ },
782
+ {
783
+ "name": "large_kernel_tiled_state_bias_k128_wg256",
784
+ "provenance": { "notes": "Largest swept workgroup at the production kernel and sequence sizes." },
785
+ "attrs": { "activation": "silu" },
786
+ "tunables": { "tiledWorkgroupSize": 256 },
787
+ "inputs": {
788
+ "inputT": {
789
+ "dtype": "float32",
790
+ "shape": [1, 1, 512],
791
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
792
+ },
793
+ "weightT": {
794
+ "dtype": "float32",
795
+ "shape": [1, 1, 128],
796
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
797
+ },
798
+ "biasT": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [-0.075] } },
799
+ "pastStateT": {
800
+ "dtype": "float32",
801
+ "shape": [1, 1, 127],
802
+ "data": { "kind": "fillFloat32", "scale": 0.15, "sinStep": 0.027, "cosStep": 0.019 }
803
+ }
804
+ },
805
+ "outputs": {
806
+ "outputT": { "dtype": "float32", "shape": [1, 1, 512], "tolerance": 0.0001 },
807
+ "presentStateT": { "dtype": "float32", "shape": [1, 1, 127], "tolerance": 0.000001 }
808
+ }
809
+ },
810
+ {
811
+ "name": "state_window2_pinned",
812
+ "provenance": {
813
+ "notes": "Hand-computed from the ONNX Runtime state_window contract (onnxruntime/core/graph/contrib_ops/bert_defs.cc, the CausalConvWithState schema). Upstream's own state_window cases are CUDA-only and compare against a replayed reference rather than pinned numbers, so the expected values here were worked out by hand instead of ported. Slot 0 is the carry state after position 1 and slot 1 after position 2, so slot 1 repeats what the unwindowed op writes."
814
+ },
815
+ "attrs": { "activation": "none", "state_window": 2 },
816
+ "inputs": {
817
+ "inputT": { "dtype": "float32", "shape": [1, 1, 3], "data": { "kind": "values", "values": [1.0, 2.0, 3.0] } },
818
+ "weightT": {
819
+ "dtype": "float32",
820
+ "shape": [1, 1, 3],
821
+ "data": { "kind": "values", "values": [1.0, 10.0, 100.0] }
822
+ }
823
+ },
824
+ "outputs": {
825
+ "outputT": {
826
+ "dtype": "float32",
827
+ "shape": [1, 1, 3],
828
+ "data": { "kind": "values", "values": [100.0, 210.0, 321.0] },
829
+ "tolerance": 0
830
+ },
831
+ "presentStateT": {
832
+ "dtype": "float32",
833
+ "shape": [2, 1, 1, 2],
834
+ "data": { "kind": "values", "values": [1.0, 2.0, 2.0, 3.0] },
835
+ "tolerance": 0
836
+ }
837
+ }
838
+ },
839
+ {
840
+ "name": "state_window4_longer_than_sequence",
841
+ "provenance": {
842
+ "notes": "Hand-computed from the ONNX Runtime state_window contract (onnxruntime/core/graph/contrib_ops/bert_defs.cc, the CausalConvWithState schema). Upstream's own state_window cases are CUDA-only and compare against a replayed reference rather than pinned numbers, so the expected values here were worked out by hand instead of ported. W exceeds the sequence length, so the leading W - T slots must be zero rather than uninitialized."
843
+ },
844
+ "attrs": { "activation": "none", "state_window": 4 },
845
+ "inputs": {
846
+ "inputT": { "dtype": "float32", "shape": [1, 1, 3], "data": { "kind": "values", "values": [2.0, -1.0, 4.0] } },
847
+ "weightT": {
848
+ "dtype": "float32",
849
+ "shape": [1, 1, 3],
850
+ "data": { "kind": "values", "values": [1.0, 10.0, 100.0] }
851
+ }
852
+ },
853
+ "outputs": {
854
+ "outputT": {
855
+ "dtype": "float32",
856
+ "shape": [1, 1, 3],
857
+ "data": { "kind": "values", "values": [200.0, -80.0, 392.0] },
858
+ "tolerance": 0
859
+ },
860
+ "presentStateT": {
861
+ "dtype": "float32",
862
+ "shape": [4, 1, 1, 2],
863
+ "data": { "kind": "values", "values": [0.0, 0.0, 0.0, 2.0, 2.0, -1.0, -1.0, 4.0] },
864
+ "tolerance": 0
865
+ }
866
+ }
867
+ },
868
+ {
869
+ "name": "state_window2_past_slot_pinned",
870
+ "provenance": {
871
+ "notes": "Hand-computed from the ONNX Runtime state_window contract (onnxruntime/core/graph/contrib_ops/bert_defs.cc, the CausalConvWithState schema). Upstream's own state_window cases are CUDA-only and compare against a replayed reference rather than pinned numbers, so the expected values here were worked out by hand instead of ported. past_state slot 0 is poisoned with large negatives that no correct read touches; only slot W-1 carries the previous call's state."
872
+ },
873
+ "attrs": { "activation": "none", "state_window": 2 },
874
+ "inputs": {
875
+ "inputT": { "dtype": "float32", "shape": [1, 1, 2], "data": { "kind": "values", "values": [1.0, 2.0] } },
876
+ "weightT": {
877
+ "dtype": "float32",
878
+ "shape": [1, 1, 3],
879
+ "data": { "kind": "values", "values": [1.0, 10.0, 100.0] }
880
+ },
881
+ "pastStateT": {
882
+ "dtype": "float32",
883
+ "shape": [2, 1, 1, 2],
884
+ "data": { "kind": "values", "values": [-1000.0, -2000.0, 5.0, 7.0] }
885
+ }
886
+ },
887
+ "outputs": {
888
+ "outputT": {
889
+ "dtype": "float32",
890
+ "shape": [1, 1, 2],
891
+ "data": { "kind": "values", "values": [175.0, 217.0] },
892
+ "tolerance": 0
893
+ },
894
+ "presentStateT": {
895
+ "dtype": "float32",
896
+ "shape": [2, 1, 1, 2],
897
+ "data": { "kind": "values", "values": [7.0, 1.0, 1.0, 2.0] },
898
+ "tolerance": 0
899
+ }
900
+ }
901
+ },
902
+ {
903
+ "name": "vec4_state_window3",
904
+ "provenance": {
905
+ "notes": "Gives the aligned K=4 vec4 prefill path a windowed present_state; its scalar-typed state output has to be gathered lane by lane out of the vec4 input row."
906
+ },
907
+ "attrs": { "activation": "silu", "state_window": 3 },
908
+ "inputs": {
909
+ "inputT": {
910
+ "dtype": "float32",
911
+ "shape": [1, 2, 8],
912
+ "data": { "kind": "fillFloat32", "scale": 0.4, "sinStep": 0.17, "cosStep": 0.31 }
913
+ },
914
+ "weightT": {
915
+ "dtype": "float32",
916
+ "shape": [2, 1, 4],
917
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.11, "cosStep": 0.23 }
918
+ }
919
+ },
920
+ "outputs": {
921
+ "outputT": { "dtype": "float32", "shape": [1, 2, 8], "tolerance": 0.00002 },
922
+ "presentStateT": { "dtype": "float32", "shape": [3, 1, 2, 3], "tolerance": 0.000001 }
923
+ }
924
+ },
925
+ {
926
+ "name": "large_kernel_tiled_zero_state_window2",
927
+ "provenance": {
928
+ "notes": "Windowed present_state on the large-kernel tiled path with no past state; the state-writing tile now strides over a (slot, element) grid instead of a single slot."
929
+ },
930
+ "attrs": { "activation": "none", "state_window": 2 },
931
+ "inputs": {
932
+ "inputT": {
933
+ "dtype": "float32",
934
+ "shape": [1, 1, 256],
935
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
936
+ },
937
+ "weightT": {
938
+ "dtype": "float32",
939
+ "shape": [1, 1, 32],
940
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
941
+ }
942
+ },
943
+ "outputs": {
944
+ "outputT": { "dtype": "float32", "shape": [1, 1, 256], "tolerance": 0.00005 },
945
+ "presentStateT": { "dtype": "float32", "shape": [2, 1, 1, 31], "tolerance": 0.000001 }
946
+ }
947
+ },
948
+ {
949
+ "name": "large_kernel_tiled_bias_no_state_window2",
950
+ "provenance": {
951
+ "notes": "Exercises windowed present-state publication on the large-kernel tiled route when bias is present but past state is absent."
952
+ },
953
+ "attrs": { "activation": "silu", "state_window": 2 },
954
+ "inputs": {
955
+ "inputT": {
956
+ "dtype": "float32",
957
+ "shape": [1, 1, 256],
958
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
959
+ },
960
+ "weightT": {
961
+ "dtype": "float32",
962
+ "shape": [1, 1, 32],
963
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
964
+ },
965
+ "biasT": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [-0.075] } }
966
+ },
967
+ "outputs": {
968
+ "outputT": { "dtype": "float32", "shape": [1, 1, 256], "tolerance": 0.00005 },
969
+ "presentStateT": { "dtype": "float32", "shape": [2, 1, 1, 31], "tolerance": 0.000001 }
970
+ }
971
+ },
972
+ {
973
+ "name": "large_kernel_tiled_state_no_bias_window2",
974
+ "provenance": {
975
+ "notes": "Exercises windowed past-state reads and present-state publication on the large-kernel tiled route without bias."
976
+ },
977
+ "attrs": { "activation": "none", "state_window": 2 },
978
+ "inputs": {
979
+ "inputT": {
980
+ "dtype": "float32",
981
+ "shape": [1, 1, 256],
982
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
983
+ },
984
+ "weightT": {
985
+ "dtype": "float32",
986
+ "shape": [1, 1, 32],
987
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
988
+ },
989
+ "pastStateT": {
990
+ "dtype": "float32",
991
+ "shape": [2, 1, 1, 31],
992
+ "data": { "kind": "fillFloat32", "scale": 0.15, "sinStep": 0.027, "cosStep": 0.019 }
993
+ }
994
+ },
995
+ "outputs": {
996
+ "outputT": { "dtype": "float32", "shape": [1, 1, 256], "tolerance": 0.00005 },
997
+ "presentStateT": { "dtype": "float32", "shape": [2, 1, 1, 31], "tolerance": 0.000001 }
998
+ }
999
+ },
1000
+ {
1001
+ "name": "large_kernel_tiled_state_bias_window2",
1002
+ "provenance": {
1003
+ "notes": "Windowed present_state on the large-kernel tiled path with a windowed past_state and bias; the earliest slot still reaches back into the carried state."
1004
+ },
1005
+ "attrs": { "activation": "silu", "state_window": 2 },
1006
+ "inputs": {
1007
+ "inputT": {
1008
+ "dtype": "float32",
1009
+ "shape": [1, 1, 256],
1010
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
1011
+ },
1012
+ "weightT": {
1013
+ "dtype": "float32",
1014
+ "shape": [1, 1, 32],
1015
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
1016
+ },
1017
+ "biasT": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [-0.075] } },
1018
+ "pastStateT": {
1019
+ "dtype": "float32",
1020
+ "shape": [2, 1, 1, 31],
1021
+ "data": { "kind": "fillFloat32", "scale": 0.15, "sinStep": 0.027, "cosStep": 0.019 }
1022
+ }
1023
+ },
1024
+ "outputs": {
1025
+ "outputT": { "dtype": "float32", "shape": [1, 1, 256], "tolerance": 0.00005 },
1026
+ "presentStateT": { "dtype": "float32", "shape": [2, 1, 1, 31], "tolerance": 0.000001 }
1027
+ }
1028
+ },
1029
+ {
1030
+ "name": "vec4_state_window6_longer_than_sequence",
1031
+ "provenance": {
1032
+ "notes": "W = 6 exceeds the four-position input, so the vec4 path's two leading window slots hold no position from this call and must be zero. Only this variant can reach that branch with a window: the tiled path demands at least 256 positions, which no legal window exceeds."
1033
+ },
1034
+ "attrs": { "activation": "none", "state_window": 6 },
1035
+ "inputs": {
1036
+ "inputT": {
1037
+ "dtype": "float32",
1038
+ "shape": [1, 2, 4],
1039
+ "data": { "kind": "fillFloat32", "scale": 0.6, "sinStep": 0.29, "cosStep": 0.13 }
1040
+ },
1041
+ "weightT": {
1042
+ "dtype": "float32",
1043
+ "shape": [2, 1, 4],
1044
+ "data": { "kind": "fillFloat32", "scale": 0.3, "sinStep": 0.19, "cosStep": 0.37 }
1045
+ }
1046
+ },
1047
+ "outputs": {
1048
+ "outputT": { "dtype": "float32", "shape": [1, 2, 4], "tolerance": 0.00002 },
1049
+ "presentStateT": { "dtype": "float32", "shape": [6, 1, 2, 3], "tolerance": 0.000001 }
1050
+ }
1051
+ },
1052
+ {
1053
+ "name": "vec4_state_window_past_state_prefix",
1054
+ "provenance": {
1055
+ "notes": "A windowed state whose window reaches back further than this call is long, WITH a past state: the early slots carry positions from before this call, so they have to come from past_state rather than from the input row."
1056
+ },
1057
+ "attrs": { "activation": "silu", "state_window": 6 },
1058
+ "inputs": {
1059
+ "inputT": {
1060
+ "dtype": "float32",
1061
+ "shape": [1, 2, 4],
1062
+ "data": { "kind": "fillFloat32", "scale": 0.6, "sinStep": 0.29, "cosStep": 0.13 }
1063
+ },
1064
+ "weightT": {
1065
+ "dtype": "float32",
1066
+ "shape": [2, 1, 4],
1067
+ "data": { "kind": "fillFloat32", "scale": 0.3, "sinStep": 0.19, "cosStep": 0.37 }
1068
+ },
1069
+ "pastStateT": {
1070
+ "dtype": "float32",
1071
+ "shape": [6, 1, 2, 3],
1072
+ "data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.37, "scale": 0.5 }
1073
+ }
1074
+ },
1075
+ "outputs": {
1076
+ "outputT": { "dtype": "float32", "shape": [1, 2, 4], "tolerance": 0.00002 },
1077
+ "presentStateT": { "dtype": "float32", "shape": [6, 1, 2, 3], "tolerance": 0.000001 }
1078
+ }
1079
+ },
1080
+ {
1081
+ "name": "f16_scalar_state_bias_silu",
1082
+ "provenance": {
1083
+ "notes": "float16 tensors on the scalar kernel. ONNX Runtime registers this operator for the whole supported float set; this port pinned float32. Every tap and accumulation still runs in f32 and only the store narrows, which is what the kernel already did for float32."
1084
+ },
1085
+ "attrs": { "activation": "silu" },
1086
+ "inputs": {
1087
+ "inputT": {
1088
+ "dtype": "float16",
1089
+ "shape": [1, 2, 4],
1090
+ "data": { "kind": "fillFloat32", "scale": 0.4, "sinStep": 0.17, "cosStep": 0.31 }
1091
+ },
1092
+ "weightT": {
1093
+ "dtype": "float16",
1094
+ "shape": [2, 1, 3],
1095
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.11, "cosStep": 0.23 }
1096
+ },
1097
+ "biasT": { "dtype": "float16", "shape": [2], "data": { "kind": "values", "values": [0.1, -0.2] } },
1098
+ "pastStateT": {
1099
+ "dtype": "float16",
1100
+ "shape": [1, 2, 2],
1101
+ "data": { "kind": "fillFloat32", "scale": 0.3, "sinStep": 0.29, "cosStep": 0.13 }
1102
+ }
1103
+ },
1104
+ "outputs": {
1105
+ "outputT": { "dtype": "float16", "shape": [1, 2, 4], "tolerance": 0.005 },
1106
+ "presentStateT": { "dtype": "float16", "shape": [1, 2, 2], "tolerance": 0.005 }
1107
+ }
1108
+ },
1109
+ {
1110
+ "name": "f16_k4_vec4_zero_state_silu",
1111
+ "provenance": {
1112
+ "notes": "float16 on the four-tap vectorized kernel, which read the bound element type directly and so was the only one of the three actually pinned to float32."
1113
+ },
1114
+ "attrs": { "activation": "silu" },
1115
+ "inputs": {
1116
+ "inputT": {
1117
+ "dtype": "float16",
1118
+ "shape": [2, 3, 8],
1119
+ "data": { "kind": "fillFloat32", "scale": 0.4, "sinStep": 0.17, "cosStep": 0.31 }
1120
+ },
1121
+ "weightT": {
1122
+ "dtype": "float16",
1123
+ "shape": [3, 1, 4],
1124
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.11, "cosStep": 0.23 }
1125
+ }
1126
+ },
1127
+ "outputs": {
1128
+ "outputT": { "dtype": "float16", "shape": [2, 3, 8], "tolerance": 0.005 },
1129
+ "presentStateT": { "dtype": "float16", "shape": [2, 3, 3], "tolerance": 0.005 }
1130
+ }
1131
+ },
1132
+ {
1133
+ "name": "f16_large_kernel_tiled_state_bias",
1134
+ "provenance": {
1135
+ "notes": "float16 on the tiled large-kernel path, which stages the weight and the virtual input in float32 workgroup memory regardless of the tensor type."
1136
+ },
1137
+ "inputs": {
1138
+ "inputT": {
1139
+ "dtype": "float16",
1140
+ "shape": [1, 1, 256],
1141
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
1142
+ },
1143
+ "weightT": {
1144
+ "dtype": "float16",
1145
+ "shape": [1, 1, 32],
1146
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
1147
+ },
1148
+ "biasT": { "dtype": "float16", "shape": [1], "data": { "kind": "values", "values": [-0.075] } },
1149
+ "pastStateT": {
1150
+ "dtype": "float16",
1151
+ "shape": [1, 1, 31],
1152
+ "data": { "kind": "fillFloat32", "scale": 0.15, "sinStep": 0.027, "cosStep": 0.019 }
1153
+ }
1154
+ },
1155
+ "outputs": {
1156
+ "outputT": { "dtype": "float16", "shape": [1, 1, 256], "tolerance": 0.01 },
1157
+ "presentStateT": { "dtype": "float16", "shape": [1, 1, 31], "tolerance": 0.005 }
1158
+ }
1159
+ },
1160
+ {
1161
+ "name": "weight_rank3_k4_vec4_zero_state",
1162
+ "provenance": {
1163
+ "notes": "A rank-3 weight on the four-tap vectorized kernel, where the kernel extent is read as a vec4 rather than element by element."
1164
+ },
1165
+ "inputs": {
1166
+ "inputT": {
1167
+ "dtype": "float32",
1168
+ "shape": [2, 3, 8],
1169
+ "data": { "kind": "fillFloat32", "scale": 0.4, "sinStep": 0.17, "cosStep": 0.31 }
1170
+ },
1171
+ "weightT": {
1172
+ "dtype": "float32",
1173
+ "shape": [3, 1, 4],
1174
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.11, "cosStep": 0.23 }
1175
+ }
1176
+ },
1177
+ "outputs": {
1178
+ "outputT": { "dtype": "float32", "shape": [2, 3, 8], "tolerance": 0.00002 },
1179
+ "presentStateT": { "dtype": "float32", "shape": [2, 3, 3], "tolerance": 0.000001 }
1180
+ }
1181
+ },
1182
+ {
1183
+ "name": "large_kernel_tiled_unaligned_k33_weight_tile_pad",
1184
+ "provenance": {
1185
+ "notes": "Kernel length 1 mod 4. The tap loop consumes four weights per iteration, so this shape reaches the tiled path only via the zero-padded weight tile; before that it fell to the untiled kernel."
1186
+ },
1187
+ "attrs": { "activation": "none" },
1188
+ "inputs": {
1189
+ "inputT": {
1190
+ "dtype": "float32",
1191
+ "shape": [1, 2, 256],
1192
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
1193
+ },
1194
+ "weightT": {
1195
+ "dtype": "float32",
1196
+ "shape": [2, 1, 33],
1197
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
1198
+ }
1199
+ },
1200
+ "outputs": {
1201
+ "outputT": { "dtype": "float32", "shape": [1, 2, 256], "tolerance": 0.00005 },
1202
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 32], "tolerance": 0.000001 }
1203
+ }
1204
+ },
1205
+ {
1206
+ "name": "large_kernel_tiled_unaligned_k34_weight_tile_pad",
1207
+ "provenance": { "notes": "Kernel length 2 mod 4 -- the other half of the padded-tail arithmetic." },
1208
+ "attrs": { "activation": "none" },
1209
+ "inputs": {
1210
+ "inputT": {
1211
+ "dtype": "float32",
1212
+ "shape": [1, 2, 256],
1213
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
1214
+ },
1215
+ "weightT": {
1216
+ "dtype": "float32",
1217
+ "shape": [2, 1, 34],
1218
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
1219
+ }
1220
+ },
1221
+ "outputs": {
1222
+ "outputT": { "dtype": "float32", "shape": [1, 2, 256], "tolerance": 0.00005 },
1223
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 33], "tolerance": 0.000001 }
1224
+ }
1225
+ },
1226
+ {
1227
+ "name": "large_kernel_tiled_unaligned_k35_bias_weight_tile_pad",
1228
+ "provenance": {
1229
+ "notes": "Kernel length 3 mod 4, the largest pad, with a bias so the padded tail is exercised on the bias arm of the family too."
1230
+ },
1231
+ "attrs": { "activation": "none" },
1232
+ "inputs": {
1233
+ "inputT": {
1234
+ "dtype": "float32",
1235
+ "shape": [1, 2, 256],
1236
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
1237
+ },
1238
+ "weightT": {
1239
+ "dtype": "float32",
1240
+ "shape": [2, 1, 35],
1241
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
1242
+ },
1243
+ "biasT": {
1244
+ "dtype": "float32",
1245
+ "shape": [2],
1246
+ "data": { "kind": "fillFloat32", "scale": 0.1, "sinStep": 0.07, "cosStep": 0.03 }
1247
+ }
1248
+ },
1249
+ "outputs": {
1250
+ "outputT": { "dtype": "float32", "shape": [1, 2, 256], "tolerance": 0.00005 },
1251
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 34], "tolerance": 0.000001 }
1252
+ }
1253
+ },
1254
+ {
1255
+ "name": "large_kernel_tiled_unaligned_k37_state_weight_tile_pad",
1256
+ "provenance": {
1257
+ "notes": "Kernel length 1 mod 4 carrying past state, so the padded weight tile is covered on the stateful arm where STATE_LENGTH stays the true kernel-1."
1258
+ },
1259
+ "attrs": { "activation": "none" },
1260
+ "inputs": {
1261
+ "inputT": {
1262
+ "dtype": "float32",
1263
+ "shape": [1, 2, 256],
1264
+ "data": { "kind": "fillFloat32", "scale": 0.2, "sinStep": 0.013, "cosStep": 0.021 }
1265
+ },
1266
+ "weightT": {
1267
+ "dtype": "float32",
1268
+ "shape": [2, 1, 37],
1269
+ "data": { "kind": "fillFloat32", "scale": 0.05, "sinStep": 0.031, "cosStep": 0.017 }
1270
+ },
1271
+ "pastStateT": {
1272
+ "dtype": "float32",
1273
+ "shape": [1, 2, 36],
1274
+ "data": { "kind": "fillFloat32", "scale": 0.15, "sinStep": 0.011, "cosStep": 0.029 }
1275
+ }
1276
+ },
1277
+ "outputs": {
1278
+ "outputT": { "dtype": "float32", "shape": [1, 2, 256], "tolerance": 0.00005 },
1279
+ "presentStateT": { "dtype": "float32", "shape": [1, 2, 36], "tolerance": 0.000001 }
1280
+ }
1281
+ }
1282
+ ]
1283
+ }