sync 6fdf6301e2bb
Browse files- README.md +23 -8
- build/webgpu/bench.json +329 -10
- build/webgpu/manifest.json +345 -65
- build/webgpu/metadata.json +21 -12
- build/webgpu/test.json +0 -0
- build/webgpu/varlen-causal-conv-stream.wgsl.jinja +12 -9
- build/webgpu/varlen-causal-conv.wgsl.jinja +17 -14
- build/webgpu/varlen-unit-sequence.wgsl.jinja +59 -0
README.md
CHANGED
|
@@ -24,7 +24,7 @@ See the [ONNX Runtime `VarlenCausalConvWithState` contrib-operator spec](https:/
|
|
| 24 |
| `weightT` | `weight` | `T` | same as logical dtype | `3` | — | Depthwise kernel with shape `(channels, 1, kernel_size)`. | required |
|
| 25 |
| `cumulativeSequenceLengthT` | `cumulative_sequence_length` | `M` | `int32` | `1` | — | Exclusive prefix sums with shape `(batch_size + 1)`, starting at 0, ending at `total_tokens`, and strictly increasing so every sequence is non-empty. Sequence `i` owns tokens `[cum[i], cum[i + 1])`. Outputs are unspecified for a malformed schedule. | required |
|
| 26 |
| `biasT` | `bias` | `T` | same as logical dtype | `1` | — | Optional per-channel bias with shape `(channels,)`. In an ONNX graph an omitted bias must still occupy input index 3 as an empty name so `initial_state` stays at index 4. | optional |
|
| 27 |
-
| `initialStateT` | `initial_state` | `T` | same as logical dtype | `3` | — | Required committed carry state with shape `(batch_size, channels, kernel_size - 1)`, holding the raw samples immediately preceding this call. | required |
|
| 28 |
| `captureCountT` | `capture_count` | `M` | `int32` | `1` | — | Optional int32 vector with shape `(batch_size)`. Required exactly when `state_update_capacity` is positive; each value is clamped to `[0, min(state_update_capacity, sequence_length)]`. | optional |
|
| 29 |
|
| 30 |
## Outputs
|
|
@@ -32,7 +32,7 @@ See the [ONNX Runtime `VarlenCausalConvWithState` contrib-operator spec](https:/
|
|
| 32 |
| Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
|
| 33 |
| --- | --- | --- | --- | --- | --- | --- |
|
| 34 |
| `outputT` | `output` | `T` | same as `inputT` | same as `inputT` | Convolution output with the same shape as `input`. | required |
|
| 35 |
-
| `finalStateT` | `final_state` | `T` | `3` | derived | State after each sequence's final token, shape `(batch_size, channels, kernel_size - 1)`. Always fully written. | required |
|
| 36 |
| `stateUpdateT` | `state_update` | `T` | `3` | derived | Optional compact transition values with shape `(batch_size, state_update_capacity, channels)`. Active slots contain the original local input tokens and all other slots are zero. | optional |
|
| 37 |
|
| 38 |
## Attributes
|
|
@@ -42,6 +42,7 @@ Default values (overridable per request):
|
|
| 42 |
| Attribute | Default | Description |
|
| 43 |
| --- | --- | --- |
|
| 44 |
| `activation` | `"none"` | Fused activation applied after convolution and bias. One of `none`, `silu`, or `swish`; the standard default is `none`. |
|
|
|
|
| 45 |
| `state_update_capacity` | `0` | Static number of compact per-request prefix transition values to expose, in `[0, 8]`. The standard default is 0. |
|
| 46 |
|
| 47 |
## Type constraints
|
|
@@ -51,20 +52,34 @@ Default values (overridable per request):
|
|
| 51 |
| `T` | `float32`, `float16` |
|
| 52 |
| `M` | `int32` |
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
## Files
|
| 55 |
|
| 56 |
- [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, provenance)
|
| 57 |
- [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
|
| 58 |
- [`test.json`](build/webgpu/test.json) — correctness cases
|
| 59 |
-
- [`bench.json`](build/webgpu/bench.json) — benchmark
|
| 60 |
- [`varlen-causal-conv-stream.wgsl.jinja`](build/webgpu/varlen-causal-conv-stream.wgsl.jinja)
|
| 61 |
- [`varlen-causal-conv.wgsl.jinja`](build/webgpu/varlen-causal-conv.wgsl.jinja)
|
| 62 |
- [`varlen-state-update.wgsl.jinja`](build/webgpu/varlen-state-update.wgsl.jinja)
|
|
|
|
| 63 |
|
| 64 |
## Use with `@huggingface/kernels`
|
| 65 |
|
| 66 |
```sh
|
| 67 |
-
npm install --save-exact @huggingface/kernels@0.0.1-preview.
|
| 68 |
```
|
| 69 |
|
| 70 |
Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
|
|
@@ -79,9 +94,9 @@ import { getKernel } from "@huggingface/kernels";
|
|
| 79 |
|
| 80 |
const kernel = await getKernel("webgpu-kernels/com.microsoft.VarlenCausalConvWithState", { version: 1 });
|
| 81 |
const { outputT, finalStateT } = await kernel({
|
| 82 |
-
inputT: { data: inputTData, shape: [
|
| 83 |
-
weightT: { data: weightTData, shape: [
|
| 84 |
-
cumulativeSequenceLengthT: { data: cumulativeSequenceLengthTData, shape: [
|
| 85 |
-
initialStateT: { data: initialStateTData, shape: [
|
| 86 |
});
|
| 87 |
```
|
|
|
|
| 24 |
| `weightT` | `weight` | `T` | same as logical dtype | `3` | — | Depthwise kernel with shape `(channels, 1, kernel_size)`. | required |
|
| 25 |
| `cumulativeSequenceLengthT` | `cumulative_sequence_length` | `M` | `int32` | `1` | — | Exclusive prefix sums with shape `(batch_size + 1)`, starting at 0, ending at `total_tokens`, and strictly increasing so every sequence is non-empty. Sequence `i` owns tokens `[cum[i], cum[i + 1])`. Outputs are unspecified for a malformed schedule. | required |
|
| 26 |
| `biasT` | `bias` | `T` | same as logical dtype | `1` | — | Optional per-channel bias with shape `(channels,)`. In an ONNX graph an omitted bias must still occupy input index 3 as an empty name so `initial_state` stays at index 4. | optional |
|
| 27 |
+
| `initialStateT` | `initial_state` | `T` | same as logical dtype | `3` | — | Required committed carry state with shape `(batch_size, channels, (kernel_size - 1) * dilation)`, holding the raw samples immediately preceding this call. | required |
|
| 28 |
| `captureCountT` | `capture_count` | `M` | `int32` | `1` | — | Optional int32 vector with shape `(batch_size)`. Required exactly when `state_update_capacity` is positive; each value is clamped to `[0, min(state_update_capacity, sequence_length)]`. | optional |
|
| 29 |
|
| 30 |
## Outputs
|
|
|
|
| 32 |
| Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
|
| 33 |
| --- | --- | --- | --- | --- | --- | --- |
|
| 34 |
| `outputT` | `output` | `T` | same as `inputT` | same as `inputT` | Convolution output with the same shape as `input`. | required |
|
| 35 |
+
| `finalStateT` | `final_state` | `T` | `3` | derived | State after each sequence's final token, shape `(batch_size, channels, (kernel_size - 1) * dilation)`. Always fully written. | required |
|
| 36 |
| `stateUpdateT` | `state_update` | `T` | `3` | derived | Optional compact transition values with shape `(batch_size, state_update_capacity, channels)`. Active slots contain the original local input tokens and all other slots are zero. | optional |
|
| 37 |
|
| 38 |
## Attributes
|
|
|
|
| 42 |
| Attribute | Default | Description |
|
| 43 |
| --- | --- | --- |
|
| 44 |
| `activation` | `"none"` | Fused activation applied after convolution and bias. One of `none`, `silu`, or `swish`; the standard default is `none`. |
|
| 45 |
+
| `dilation` | `1` | Positive integer spacing between taps; the initial and final states hold (`kernel_size` - 1) * dilation raw samples. |
|
| 46 |
| `state_update_capacity` | `0` | Static number of compact per-request prefix transition values to expose, in `[0, 8]`. The standard default is 0. |
|
| 47 |
|
| 48 |
## Type constraints
|
|
|
|
| 52 |
| `T` | `float32`, `float16` |
|
| 53 |
| `M` | `int32` |
|
| 54 |
|
| 55 |
+
## Implementation variants
|
| 56 |
+
|
| 57 |
+
One implementation is selected per call from the device capabilities, the request shapes and the dtypes; these notes say what each one covers.
|
| 58 |
+
|
| 59 |
+
- `unit_plain` — Direct single-token sequence convolution with contiguous vector state traffic and fused capture writes. Strictly increasing schedules with `total_tokens == batch_size` imply one token per sequence. Channel divisibility selects the vector width; the workgroup respects device limits. Dilated and f16 requests retain their existing paths.
|
| 60 |
+
- `unit_bias` — Direct single-token sequence convolution with contiguous vector state traffic and fused capture writes. Strictly increasing schedules with `total_tokens == batch_size` imply one token per sequence. Channel divisibility selects the vector width; the workgroup respects device limits. Dilated and f16 requests retain their existing paths.
|
| 61 |
+
- `unit_state_update` — Direct single-token sequence convolution with contiguous vector state traffic and fused capture writes. Strictly increasing schedules with `total_tokens == batch_size` imply one token per sequence. Channel divisibility selects the vector width; the workgroup respects device limits. Dilated and f16 requests retain their existing paths.
|
| 62 |
+
- `unit_bias_state_update` — Direct single-token sequence convolution with contiguous vector state traffic and fused capture writes. Strictly increasing schedules with `total_tokens == batch_size` imply one token per sequence. Channel divisibility selects the vector width; the workgroup respects device limits. Dilated and f16 requests retain their existing paths.
|
| 63 |
+
- `capture_copy_state_update_stream` — Copy the capture prefix in contiguous channel vectors while preserving the convolution path and exact zero-fill semantics. The existing copy template operates on vector groups; no extra storage bindings or optional GPU features are needed.
|
| 64 |
+
- `capture_copy_state_update` — Copy the capture prefix in contiguous channel vectors while preserving the convolution path and exact zero-fill semantics. The existing copy template operates on vector groups; no extra storage bindings or optional GPU features are needed.
|
| 65 |
+
- `capture_copy_bias_state_update_stream` — Copy the capture prefix in contiguous channel vectors while preserving the convolution path and exact zero-fill semantics. The existing copy template operates on vector groups; no extra storage bindings or optional GPU features are needed.
|
| 66 |
+
- `capture_copy_bias_state_update` — Copy the capture prefix in contiguous channel vectors while preserving the convolution path and exact zero-fill semantics. The existing copy template operates on vector groups; no extra storage bindings or optional GPU features are needed.
|
| 67 |
+
|
| 68 |
## Files
|
| 69 |
|
| 70 |
- [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, provenance)
|
| 71 |
- [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
|
| 72 |
- [`test.json`](build/webgpu/test.json) — correctness cases
|
| 73 |
+
- [`bench.json`](build/webgpu/bench.json) — benchmark cases
|
| 74 |
- [`varlen-causal-conv-stream.wgsl.jinja`](build/webgpu/varlen-causal-conv-stream.wgsl.jinja)
|
| 75 |
- [`varlen-causal-conv.wgsl.jinja`](build/webgpu/varlen-causal-conv.wgsl.jinja)
|
| 76 |
- [`varlen-state-update.wgsl.jinja`](build/webgpu/varlen-state-update.wgsl.jinja)
|
| 77 |
+
- [`varlen-unit-sequence.wgsl.jinja`](build/webgpu/varlen-unit-sequence.wgsl.jinja)
|
| 78 |
|
| 79 |
## Use with `@huggingface/kernels`
|
| 80 |
|
| 81 |
```sh
|
| 82 |
+
npm install --save-exact @huggingface/kernels@0.0.1-preview.3
|
| 83 |
```
|
| 84 |
|
| 85 |
Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
|
|
|
|
| 94 |
|
| 95 |
const kernel = await getKernel("webgpu-kernels/com.microsoft.VarlenCausalConvWithState", { version: 1 });
|
| 96 |
const { outputT, finalStateT } = await kernel({
|
| 97 |
+
inputT: { data: inputTData, shape: [1, 4] },
|
| 98 |
+
weightT: { data: weightTData, shape: [4, 1, 4] },
|
| 99 |
+
cumulativeSequenceLengthT: { data: cumulativeSequenceLengthTData, shape: [2] },
|
| 100 |
+
initialStateT: { data: initialStateTData, shape: [1, 4, 3] },
|
| 101 |
});
|
| 102 |
```
|
build/webgpu/bench.json
CHANGED
|
@@ -4,6 +4,9 @@
|
|
| 4 |
"streamWorkgroupSize": [64, 128, 256],
|
| 5 |
"streamChunk": [16, 32, 64, 128, 256]
|
| 6 |
},
|
|
|
|
|
|
|
|
|
|
| 7 |
"cases": [
|
| 8 |
{
|
| 9 |
"name": "varlenconv-decode-b32-c4096-k4",
|
|
@@ -27,7 +30,16 @@
|
|
| 27 |
"outputT": { "shape": [32, 4096], "dtype": "float32" },
|
| 28 |
"finalStateT": { "shape": [32, 4096, 3], "dtype": "float32" }
|
| 29 |
},
|
| 30 |
-
"bench": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
"attrs": { "activation": "silu" }
|
| 32 |
},
|
| 33 |
{
|
|
@@ -49,7 +61,16 @@
|
|
| 49 |
"outputT": { "shape": [2048, 4096], "dtype": "float32" },
|
| 50 |
"finalStateT": { "shape": [1, 4096, 3], "dtype": "float32" }
|
| 51 |
},
|
| 52 |
-
"bench": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
"attrs": { "activation": "silu" }
|
| 54 |
},
|
| 55 |
{
|
|
@@ -71,7 +92,16 @@
|
|
| 71 |
"outputT": { "shape": [512, 4096], "dtype": "float32" },
|
| 72 |
"finalStateT": { "shape": [8, 4096, 3], "dtype": "float32" }
|
| 73 |
},
|
| 74 |
-
"bench": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
"attrs": { "activation": "silu" }
|
| 76 |
},
|
| 77 |
{
|
|
@@ -95,10 +125,19 @@
|
|
| 95 |
"finalStateT": { "shape": [6, 2048, 3], "dtype": "float32" },
|
| 96 |
"stateUpdateT": { "dtype": "float32", "shape": [6, 4, 2048] }
|
| 97 |
},
|
| 98 |
-
"bench": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
"attrs": { "activation": "silu", "state_update_capacity": 4 },
|
| 100 |
"provenance": {
|
| 101 |
-
"notes": "
|
| 102 |
}
|
| 103 |
},
|
| 104 |
{
|
|
@@ -122,10 +161,19 @@
|
|
| 122 |
"finalStateT": { "shape": [6, 2048, 3], "dtype": "float32" },
|
| 123 |
"stateUpdateT": { "dtype": "float32", "shape": [6, 4, 2048] }
|
| 124 |
},
|
| 125 |
-
"bench": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
"attrs": { "activation": "silu", "state_update_capacity": 4 },
|
| 127 |
"provenance": {
|
| 128 |
-
"notes": "
|
| 129 |
}
|
| 130 |
},
|
| 131 |
{
|
|
@@ -147,7 +195,16 @@
|
|
| 147 |
"outputT": { "shape": [512, 4096], "dtype": "float32" },
|
| 148 |
"finalStateT": { "shape": [4, 4096, 3], "dtype": "float32" }
|
| 149 |
},
|
| 150 |
-
"bench": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
"attrs": { "activation": "silu" }
|
| 152 |
},
|
| 153 |
{
|
|
@@ -169,7 +226,16 @@
|
|
| 169 |
"outputT": { "shape": [512, 4096], "dtype": "float16" },
|
| 170 |
"finalStateT": { "shape": [8, 4096, 3], "dtype": "float16" }
|
| 171 |
},
|
| 172 |
-
"bench": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
"attrs": { "activation": "silu" }
|
| 174 |
},
|
| 175 |
{
|
|
@@ -191,8 +257,261 @@
|
|
| 191 |
"outputT": { "shape": [512, 4096], "dtype": "float32" },
|
| 192 |
"finalStateT": { "shape": [8, 4096, 2], "dtype": "float32" }
|
| 193 |
},
|
| 194 |
-
"bench": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
"attrs": { "activation": "silu" }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
}
|
| 197 |
]
|
| 198 |
}
|
|
|
|
| 4 |
"streamWorkgroupSize": [64, 128, 256],
|
| 5 |
"streamChunk": [16, 32, 64, 128, 256]
|
| 6 |
},
|
| 7 |
+
"fixtureArrays": {
|
| 8 |
+
"varlenconv-unit-capture-b64-c4096-k4-cap4_input_captureCountT": [2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99, 2, 0, -3, 99]
|
| 9 |
+
},
|
| 10 |
"cases": [
|
| 11 |
{
|
| 12 |
"name": "varlenconv-decode-b32-c4096-k4",
|
|
|
|
| 30 |
"outputT": { "shape": [32, 4096], "dtype": "float32" },
|
| 31 |
"finalStateT": { "shape": [32, 4096, 3], "dtype": "float32" }
|
| 32 |
},
|
| 33 |
+
"bench": {
|
| 34 |
+
"metrics": [
|
| 35 |
+
{
|
| 36 |
+
"type": "bandwidth",
|
| 37 |
+
"name": "Logical tensor traffic",
|
| 38 |
+
"provenance": "logical",
|
| 39 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 40 |
+
}
|
| 41 |
+
]
|
| 42 |
+
},
|
| 43 |
"attrs": { "activation": "silu" }
|
| 44 |
},
|
| 45 |
{
|
|
|
|
| 61 |
"outputT": { "shape": [2048, 4096], "dtype": "float32" },
|
| 62 |
"finalStateT": { "shape": [1, 4096, 3], "dtype": "float32" }
|
| 63 |
},
|
| 64 |
+
"bench": {
|
| 65 |
+
"metrics": [
|
| 66 |
+
{
|
| 67 |
+
"type": "bandwidth",
|
| 68 |
+
"name": "Logical tensor traffic",
|
| 69 |
+
"provenance": "logical",
|
| 70 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 71 |
+
}
|
| 72 |
+
]
|
| 73 |
+
},
|
| 74 |
"attrs": { "activation": "silu" }
|
| 75 |
},
|
| 76 |
{
|
|
|
|
| 92 |
"outputT": { "shape": [512, 4096], "dtype": "float32" },
|
| 93 |
"finalStateT": { "shape": [8, 4096, 3], "dtype": "float32" }
|
| 94 |
},
|
| 95 |
+
"bench": {
|
| 96 |
+
"metrics": [
|
| 97 |
+
{
|
| 98 |
+
"type": "bandwidth",
|
| 99 |
+
"name": "Logical tensor traffic",
|
| 100 |
+
"provenance": "logical",
|
| 101 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 102 |
+
}
|
| 103 |
+
]
|
| 104 |
+
},
|
| 105 |
"attrs": { "activation": "silu" }
|
| 106 |
},
|
| 107 |
{
|
|
|
|
| 125 |
"finalStateT": { "shape": [6, 2048, 3], "dtype": "float32" },
|
| 126 |
"stateUpdateT": { "dtype": "float32", "shape": [6, 4, 2048] }
|
| 127 |
},
|
| 128 |
+
"bench": {
|
| 129 |
+
"metrics": [
|
| 130 |
+
{
|
| 131 |
+
"type": "bandwidth",
|
| 132 |
+
"name": "Logical tensor traffic",
|
| 133 |
+
"provenance": "logical",
|
| 134 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 135 |
+
}
|
| 136 |
+
]
|
| 137 |
+
},
|
| 138 |
"attrs": { "activation": "silu", "state_update_capacity": 4 },
|
| 139 |
"provenance": {
|
| 140 |
+
"notes": "The compact state_update accompanies convolution and captures up to the configured contiguous-prefix capacity."
|
| 141 |
}
|
| 142 |
},
|
| 143 |
{
|
|
|
|
| 161 |
"finalStateT": { "shape": [6, 2048, 3], "dtype": "float32" },
|
| 162 |
"stateUpdateT": { "dtype": "float32", "shape": [6, 4, 2048] }
|
| 163 |
},
|
| 164 |
+
"bench": {
|
| 165 |
+
"metrics": [
|
| 166 |
+
{
|
| 167 |
+
"type": "bandwidth",
|
| 168 |
+
"name": "Logical tensor traffic",
|
| 169 |
+
"provenance": "logical",
|
| 170 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 171 |
+
}
|
| 172 |
+
]
|
| 173 |
+
},
|
| 174 |
"attrs": { "activation": "silu", "state_update_capacity": 4 },
|
| 175 |
"provenance": {
|
| 176 |
+
"notes": "The compact state_update accompanies convolution and captures up to the configured contiguous-prefix capacity."
|
| 177 |
}
|
| 178 |
},
|
| 179 |
{
|
|
|
|
| 195 |
"outputT": { "shape": [512, 4096], "dtype": "float32" },
|
| 196 |
"finalStateT": { "shape": [4, 4096, 3], "dtype": "float32" }
|
| 197 |
},
|
| 198 |
+
"bench": {
|
| 199 |
+
"metrics": [
|
| 200 |
+
{
|
| 201 |
+
"type": "bandwidth",
|
| 202 |
+
"name": "Logical tensor traffic",
|
| 203 |
+
"provenance": "logical",
|
| 204 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 205 |
+
}
|
| 206 |
+
]
|
| 207 |
+
},
|
| 208 |
"attrs": { "activation": "silu" }
|
| 209 |
},
|
| 210 |
{
|
|
|
|
| 226 |
"outputT": { "shape": [512, 4096], "dtype": "float16" },
|
| 227 |
"finalStateT": { "shape": [8, 4096, 3], "dtype": "float16" }
|
| 228 |
},
|
| 229 |
+
"bench": {
|
| 230 |
+
"metrics": [
|
| 231 |
+
{
|
| 232 |
+
"type": "bandwidth",
|
| 233 |
+
"name": "Logical tensor traffic",
|
| 234 |
+
"provenance": "logical",
|
| 235 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 236 |
+
}
|
| 237 |
+
]
|
| 238 |
+
},
|
| 239 |
"attrs": { "activation": "silu" }
|
| 240 |
},
|
| 241 |
{
|
|
|
|
| 257 |
"outputT": { "shape": [512, 4096], "dtype": "float32" },
|
| 258 |
"finalStateT": { "shape": [8, 4096, 2], "dtype": "float32" }
|
| 259 |
},
|
| 260 |
+
"bench": {
|
| 261 |
+
"metrics": [
|
| 262 |
+
{
|
| 263 |
+
"type": "bandwidth",
|
| 264 |
+
"name": "Logical tensor traffic",
|
| 265 |
+
"provenance": "logical",
|
| 266 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 267 |
+
}
|
| 268 |
+
]
|
| 269 |
+
},
|
| 270 |
"attrs": { "activation": "silu" }
|
| 271 |
+
},
|
| 272 |
+
{
|
| 273 |
+
"name": "varlenconv-unit-capture-b1-c4096-k4-cap4",
|
| 274 |
+
"preset": "smoke",
|
| 275 |
+
"vars": { "dtype": "float32" },
|
| 276 |
+
"inputs": {
|
| 277 |
+
"inputT": { "shape": [1, 4096], "dtype": "float32", "dist": "normal", "seed": 4100, "scale": 1 },
|
| 278 |
+
"weightT": { "shape": [4096, 1, 4], "dtype": "float32", "dist": "normal", "seed": 4101, "scale": 1 },
|
| 279 |
+
"cumulativeSequenceLengthT": { "dtype": "int32", "shape": [2], "data": { "kind": "values", "values": [0, 1] } },
|
| 280 |
+
"biasT": { "shape": [4096], "dtype": "float32", "dist": "normal", "seed": 4102, "scale": 1 },
|
| 281 |
+
"initialStateT": { "shape": [1, 4096, 3], "dtype": "float32", "dist": "normal", "seed": 4103, "scale": 1 },
|
| 282 |
+
"captureCountT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [2] } }
|
| 283 |
+
},
|
| 284 |
+
"outputs": {
|
| 285 |
+
"outputT": { "shape": [1, 4096], "dtype": "float32" },
|
| 286 |
+
"finalStateT": { "shape": [1, 4096, 3], "dtype": "float32" },
|
| 287 |
+
"stateUpdateT": { "dtype": "float32", "shape": [1, 4, 4096] }
|
| 288 |
+
},
|
| 289 |
+
"bench": {
|
| 290 |
+
"metrics": [
|
| 291 |
+
{
|
| 292 |
+
"type": "bandwidth",
|
| 293 |
+
"name": "Logical tensor traffic",
|
| 294 |
+
"provenance": "logical",
|
| 295 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 296 |
+
}
|
| 297 |
+
]
|
| 298 |
+
},
|
| 299 |
+
"attrs": { "activation": "silu", "state_update_capacity": 4 }
|
| 300 |
+
},
|
| 301 |
+
{
|
| 302 |
+
"name": "varlenconv-unit-capture-b64-c4096-k4-cap4",
|
| 303 |
+
"preset": "smoke",
|
| 304 |
+
"vars": { "dtype": "float32" },
|
| 305 |
+
"inputs": {
|
| 306 |
+
"inputT": { "shape": [64, 4096], "dtype": "float32", "dist": "normal", "seed": 4100, "scale": 1 },
|
| 307 |
+
"weightT": { "shape": [4096, 1, 4], "dtype": "float32", "dist": "normal", "seed": 4101, "scale": 1 },
|
| 308 |
+
"cumulativeSequenceLengthT": {
|
| 309 |
+
"dtype": "int32",
|
| 310 |
+
"shape": [65],
|
| 311 |
+
"data": {
|
| 312 |
+
"kind": "values",
|
| 313 |
+
"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64]
|
| 314 |
+
}
|
| 315 |
+
},
|
| 316 |
+
"biasT": { "shape": [4096], "dtype": "float32", "dist": "normal", "seed": 4102, "scale": 1 },
|
| 317 |
+
"initialStateT": { "shape": [64, 4096, 3], "dtype": "float32", "dist": "normal", "seed": 4103, "scale": 1 },
|
| 318 |
+
"captureCountT": {
|
| 319 |
+
"dtype": "int32",
|
| 320 |
+
"shape": [64],
|
| 321 |
+
"data": {
|
| 322 |
+
"kind": "values",
|
| 323 |
+
"values": { "$ref": "#/fixtureArrays/varlenconv-unit-capture-b64-c4096-k4-cap4_input_captureCountT" }
|
| 324 |
+
}
|
| 325 |
+
}
|
| 326 |
+
},
|
| 327 |
+
"outputs": {
|
| 328 |
+
"outputT": { "shape": [64, 4096], "dtype": "float32" },
|
| 329 |
+
"finalStateT": { "shape": [64, 4096, 3], "dtype": "float32" },
|
| 330 |
+
"stateUpdateT": { "dtype": "float32", "shape": [64, 4, 4096] }
|
| 331 |
+
},
|
| 332 |
+
"bench": {
|
| 333 |
+
"metrics": [
|
| 334 |
+
{
|
| 335 |
+
"type": "bandwidth",
|
| 336 |
+
"name": "Logical tensor traffic",
|
| 337 |
+
"provenance": "logical",
|
| 338 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 339 |
+
}
|
| 340 |
+
]
|
| 341 |
+
},
|
| 342 |
+
"attrs": { "activation": "silu", "state_update_capacity": 4 }
|
| 343 |
+
},
|
| 344 |
+
{
|
| 345 |
+
"name": "varlenconv-unit-alignment-b64-c4098-k3-cap4",
|
| 346 |
+
"preset": "smoke",
|
| 347 |
+
"vars": { "dtype": "float32" },
|
| 348 |
+
"inputs": {
|
| 349 |
+
"inputT": { "shape": [64, 4098], "dtype": "float32", "dist": "normal", "seed": 4100, "scale": 1 },
|
| 350 |
+
"weightT": { "shape": [4098, 1, 3], "dtype": "float32", "dist": "normal", "seed": 4101, "scale": 1 },
|
| 351 |
+
"cumulativeSequenceLengthT": {
|
| 352 |
+
"dtype": "int32",
|
| 353 |
+
"shape": [65],
|
| 354 |
+
"dist": "linearMod",
|
| 355 |
+
"mod": 65,
|
| 356 |
+
"step": 1,
|
| 357 |
+
"offset": 0
|
| 358 |
+
},
|
| 359 |
+
"biasT": { "shape": [4098], "dtype": "float32", "dist": "normal", "seed": 4102, "scale": 1 },
|
| 360 |
+
"initialStateT": { "shape": [64, 4098, 2], "dtype": "float32", "dist": "normal", "seed": 4103, "scale": 1 },
|
| 361 |
+
"captureCountT": {
|
| 362 |
+
"dtype": "int32",
|
| 363 |
+
"shape": [64],
|
| 364 |
+
"data": {
|
| 365 |
+
"kind": "values",
|
| 366 |
+
"values": { "$ref": "#/fixtureArrays/varlenconv-unit-capture-b64-c4096-k4-cap4_input_captureCountT" }
|
| 367 |
+
}
|
| 368 |
+
}
|
| 369 |
+
},
|
| 370 |
+
"outputs": {
|
| 371 |
+
"outputT": { "shape": [64, 4098], "dtype": "float32" },
|
| 372 |
+
"finalStateT": { "shape": [64, 4098, 2], "dtype": "float32" },
|
| 373 |
+
"stateUpdateT": { "dtype": "float32", "shape": [64, 4, 4098] }
|
| 374 |
+
},
|
| 375 |
+
"bench": {
|
| 376 |
+
"metrics": [
|
| 377 |
+
{
|
| 378 |
+
"type": "bandwidth",
|
| 379 |
+
"name": "Logical tensor traffic",
|
| 380 |
+
"provenance": "logical",
|
| 381 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 382 |
+
}
|
| 383 |
+
]
|
| 384 |
+
},
|
| 385 |
+
"attrs": { "activation": "silu", "state_update_capacity": 4 }
|
| 386 |
+
},
|
| 387 |
+
{
|
| 388 |
+
"name": "varlenconv-unit-alignment-b64-c4097-k8-cap8",
|
| 389 |
+
"preset": "smoke",
|
| 390 |
+
"vars": { "dtype": "float32" },
|
| 391 |
+
"inputs": {
|
| 392 |
+
"inputT": { "shape": [64, 4097], "dtype": "float32", "dist": "normal", "seed": 4100, "scale": 1 },
|
| 393 |
+
"weightT": { "shape": [4097, 1, 8], "dtype": "float32", "dist": "normal", "seed": 4101, "scale": 1 },
|
| 394 |
+
"cumulativeSequenceLengthT": {
|
| 395 |
+
"dtype": "int32",
|
| 396 |
+
"shape": [65],
|
| 397 |
+
"dist": "linearMod",
|
| 398 |
+
"mod": 65,
|
| 399 |
+
"step": 1,
|
| 400 |
+
"offset": 0
|
| 401 |
+
},
|
| 402 |
+
"biasT": { "shape": [4097], "dtype": "float32", "dist": "normal", "seed": 4102, "scale": 1 },
|
| 403 |
+
"initialStateT": { "shape": [64, 4097, 7], "dtype": "float32", "dist": "normal", "seed": 4103, "scale": 1 },
|
| 404 |
+
"captureCountT": {
|
| 405 |
+
"dtype": "int32",
|
| 406 |
+
"shape": [64],
|
| 407 |
+
"data": {
|
| 408 |
+
"kind": "values",
|
| 409 |
+
"values": { "$ref": "#/fixtureArrays/varlenconv-unit-capture-b64-c4096-k4-cap4_input_captureCountT" }
|
| 410 |
+
}
|
| 411 |
+
}
|
| 412 |
+
},
|
| 413 |
+
"outputs": {
|
| 414 |
+
"outputT": { "shape": [64, 4097], "dtype": "float32" },
|
| 415 |
+
"finalStateT": { "shape": [64, 4097, 7], "dtype": "float32" },
|
| 416 |
+
"stateUpdateT": { "dtype": "float32", "shape": [64, 8, 4097] }
|
| 417 |
+
},
|
| 418 |
+
"bench": {
|
| 419 |
+
"metrics": [
|
| 420 |
+
{
|
| 421 |
+
"type": "bandwidth",
|
| 422 |
+
"name": "Logical tensor traffic",
|
| 423 |
+
"provenance": "logical",
|
| 424 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 425 |
+
}
|
| 426 |
+
]
|
| 427 |
+
},
|
| 428 |
+
"attrs": { "activation": "silu", "state_update_capacity": 8 }
|
| 429 |
+
},
|
| 430 |
+
{
|
| 431 |
+
"name": "varlenconv-capture-b64-t128-c4096-k4-d1",
|
| 432 |
+
"preset": "smoke",
|
| 433 |
+
"vars": { "dtype": "float32" },
|
| 434 |
+
"inputs": {
|
| 435 |
+
"inputT": { "shape": [128, 4096], "dtype": "float32", "dist": "normal", "seed": 4100, "scale": 1 },
|
| 436 |
+
"weightT": { "shape": [4096, 1, 4], "dtype": "float32", "dist": "normal", "seed": 4101, "scale": 1 },
|
| 437 |
+
"cumulativeSequenceLengthT": {
|
| 438 |
+
"dtype": "int32",
|
| 439 |
+
"shape": [65],
|
| 440 |
+
"dist": "linearMod",
|
| 441 |
+
"mod": 130,
|
| 442 |
+
"step": 2,
|
| 443 |
+
"offset": 0
|
| 444 |
+
},
|
| 445 |
+
"biasT": { "shape": [4096], "dtype": "float32", "dist": "normal", "seed": 4102, "scale": 1 },
|
| 446 |
+
"initialStateT": { "shape": [64, 4096, 3], "dtype": "float32", "dist": "normal", "seed": 4103, "scale": 1 },
|
| 447 |
+
"captureCountT": {
|
| 448 |
+
"dtype": "int32",
|
| 449 |
+
"shape": [64],
|
| 450 |
+
"data": {
|
| 451 |
+
"kind": "values",
|
| 452 |
+
"values": { "$ref": "#/fixtureArrays/varlenconv-unit-capture-b64-c4096-k4-cap4_input_captureCountT" }
|
| 453 |
+
}
|
| 454 |
+
}
|
| 455 |
+
},
|
| 456 |
+
"outputs": {
|
| 457 |
+
"outputT": { "shape": [128, 4096], "dtype": "float32" },
|
| 458 |
+
"finalStateT": { "shape": [64, 4096, 3], "dtype": "float32" },
|
| 459 |
+
"stateUpdateT": { "dtype": "float32", "shape": [64, 4, 4096] }
|
| 460 |
+
},
|
| 461 |
+
"bench": {
|
| 462 |
+
"metrics": [
|
| 463 |
+
{
|
| 464 |
+
"type": "bandwidth",
|
| 465 |
+
"name": "Logical tensor traffic",
|
| 466 |
+
"provenance": "logical",
|
| 467 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 468 |
+
}
|
| 469 |
+
]
|
| 470 |
+
},
|
| 471 |
+
"attrs": { "activation": "silu", "state_update_capacity": 4, "dilation": 1 }
|
| 472 |
+
},
|
| 473 |
+
{
|
| 474 |
+
"name": "varlenconv-capture-b64-t128-c4096-k4-d2",
|
| 475 |
+
"preset": "smoke",
|
| 476 |
+
"vars": { "dtype": "float32" },
|
| 477 |
+
"inputs": {
|
| 478 |
+
"inputT": { "shape": [128, 4096], "dtype": "float32", "dist": "normal", "seed": 4100, "scale": 1 },
|
| 479 |
+
"weightT": { "shape": [4096, 1, 4], "dtype": "float32", "dist": "normal", "seed": 4101, "scale": 1 },
|
| 480 |
+
"cumulativeSequenceLengthT": {
|
| 481 |
+
"dtype": "int32",
|
| 482 |
+
"shape": [65],
|
| 483 |
+
"dist": "linearMod",
|
| 484 |
+
"mod": 130,
|
| 485 |
+
"step": 2,
|
| 486 |
+
"offset": 0
|
| 487 |
+
},
|
| 488 |
+
"biasT": { "shape": [4096], "dtype": "float32", "dist": "normal", "seed": 4102, "scale": 1 },
|
| 489 |
+
"initialStateT": { "shape": [64, 4096, 6], "dtype": "float32", "dist": "normal", "seed": 4103, "scale": 1 },
|
| 490 |
+
"captureCountT": {
|
| 491 |
+
"dtype": "int32",
|
| 492 |
+
"shape": [64],
|
| 493 |
+
"data": {
|
| 494 |
+
"kind": "values",
|
| 495 |
+
"values": { "$ref": "#/fixtureArrays/varlenconv-unit-capture-b64-c4096-k4-cap4_input_captureCountT" }
|
| 496 |
+
}
|
| 497 |
+
}
|
| 498 |
+
},
|
| 499 |
+
"outputs": {
|
| 500 |
+
"outputT": { "shape": [128, 4096], "dtype": "float32" },
|
| 501 |
+
"finalStateT": { "shape": [64, 4096, 6], "dtype": "float32" },
|
| 502 |
+
"stateUpdateT": { "dtype": "float32", "shape": [64, 4, 4096] }
|
| 503 |
+
},
|
| 504 |
+
"bench": {
|
| 505 |
+
"metrics": [
|
| 506 |
+
{
|
| 507 |
+
"type": "bandwidth",
|
| 508 |
+
"name": "Logical tensor traffic",
|
| 509 |
+
"provenance": "logical",
|
| 510 |
+
"value": "(numel(shapes.inputT) + numel(shapes.weightT) + numel(shapes.initialStateT) + numel(shapes.outputT) + numel(shapes.finalStateT) + (numel(shapes.biasT) if has(shapes, \"biasT\") else 0) + (numel(shapes.stateUpdateT) if has(shapes, \"stateUpdateT\") else 0)) * dtypeBytes(args.dtype) + 4 * (numel(shapes.cumulativeSequenceLengthT) + (numel(shapes.captureCountT) if has(shapes, \"captureCountT\") else 0))"
|
| 511 |
+
}
|
| 512 |
+
]
|
| 513 |
+
},
|
| 514 |
+
"attrs": { "activation": "silu", "state_update_capacity": 4, "dilation": 2 }
|
| 515 |
}
|
| 516 |
]
|
| 517 |
}
|
build/webgpu/manifest.json
CHANGED
|
@@ -21,7 +21,11 @@
|
|
| 21 |
"shape": "[batchSize, stateUpdateCapacity, channels]"
|
| 22 |
}
|
| 23 |
},
|
| 24 |
-
"attributes": {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
"attributeConstraints": { "activation": { "values": ["none", "silu", "swish"] } },
|
| 26 |
"typeConstraints": { "T": ["float32", "float16"], "M": ["int32"] },
|
| 27 |
"tunables": {
|
|
@@ -35,33 +39,31 @@
|
|
| 35 |
"batchSize": "dim(shapes.cumulativeSequenceLengthT, 0) - 1",
|
| 36 |
"weightRankOk": "ranks.weightT == 3 and dim(shapes.weightT, 1) == 1",
|
| 37 |
"kernelSize": "dim(shapes.weightT, 2)",
|
| 38 |
-
"stateLength": "kernelSize - 1",
|
| 39 |
"stateUpdateCapacity": "attrs.state_update_capacity",
|
| 40 |
"capturePairOk": "present.captureCountT == (stateUpdateCapacity > 0)",
|
| 41 |
"stateShape": "ranks.initialStateT == 3 and dim(shapes.initialStateT, 0) == batchSize and dim(shapes.initialStateT, 1) == channels and dim(shapes.initialStateT, 2) == stateLength",
|
| 42 |
"finalStateShape": "ranks.finalStateT == 3 and dim(shapes.finalStateT, 0) == batchSize and dim(shapes.finalStateT, 1) == channels and dim(shapes.finalStateT, 2) == stateLength",
|
| 43 |
"captureShape": "not present.captureCountT or (ranks.captureCountT == 1 and dim(shapes.captureCountT, 0) == batchSize and tensorDtypes.captureCountT == \"int32\")",
|
| 44 |
"stateUpdateShape": "not present.stateUpdateT or (ranks.stateUpdateT == 3 and dim(shapes.stateUpdateT, 0) == batchSize and dim(shapes.stateUpdateT, 1) == stateUpdateCapacity and dim(shapes.stateUpdateT, 2) == channels and tensorDtypes.stateUpdateT == tensorDtypes.inputT)",
|
| 45 |
-
"commonContract": "ranks.inputT == 2 and weightRankOk and ranks.outputT == 2 and ranks.cumulativeSequenceLengthT == 1 and channels >= 1 and kernelSize >= 1 and batchSize >= 1 and totalTokens >= batchSize and stateUpdateCapacity >= 0 and stateUpdateCapacity <= 8 and floor(stateUpdateCapacity) == stateUpdateCapacity and capturePairOk and captureShape and stateUpdateShape and (tensorDtypes.inputT == \"float32\" or tensorDtypes.inputT == \"float16\") and tensorDtypes.weightT == tensorDtypes.inputT and tensorDtypes.outputT == tensorDtypes.inputT and tensorDtypes.initialStateT == tensorDtypes.inputT and tensorDtypes.finalStateT == tensorDtypes.inputT and tensorDtypes.cumulativeSequenceLengthT == \"int32\" and f16Ok(dtypes.T) and dim(shapes.weightT, 0) == channels and dim(shapes.outputT, 0) == totalTokens and dim(shapes.outputT, 1) == channels and stateShape and finalStateShape",
|
| 46 |
"biasOk": "ranks.biasT == 1 and tensorDtypes.biasT == tensorDtypes.inputT and dim(shapes.biasT, 0) == channels",
|
| 47 |
"plainContract": "commonContract and not present.biasT and (not present.stateUpdateT or stateUpdateCapacity == 0)",
|
| 48 |
"biasContract": "commonContract and present.biasT and biasOk and (not present.stateUpdateT or stateUpdateCapacity == 0)",
|
| 49 |
"stateUpdateContract": "commonContract and not present.biasT and present.stateUpdateT and stateUpdateCapacity > 0",
|
| 50 |
-
"biasStateUpdateContract": "commonContract and present.biasT and biasOk and present.stateUpdateT and stateUpdateCapacity > 0"
|
|
|
|
|
|
|
|
|
|
| 51 |
},
|
| 52 |
"bindings": {
|
| 53 |
-
"input": { "arg": "inputT", "
|
| 54 |
-
"weight": { "arg": "weightT", "
|
| 55 |
-
"cumulative_sequence_length": {
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
},
|
| 60 |
-
"initial_state": { "arg": "initialStateT", "buffer": "read-only-storage", "elementType": "$inputScalar" },
|
| 61 |
-
"output": { "arg": "outputT", "buffer": "storage", "elementType": "$outputScalar" },
|
| 62 |
-
"final_state": { "arg": "finalStateT", "buffer": "storage", "elementType": "$outputScalar" },
|
| 63 |
"params": {
|
| 64 |
-
"buffer": "uniform",
|
| 65 |
"struct": [
|
| 66 |
{ "name": "batchSize", "type": "u32", "value": "batchSize" },
|
| 67 |
{ "name": "channels", "type": "u32", "value": "channels" },
|
|
@@ -69,34 +71,173 @@
|
|
| 69 |
{ "name": "kernelSize", "type": "u32", "value": "kernelSize" }
|
| 70 |
]
|
| 71 |
},
|
| 72 |
-
"bias": { "arg": "biasT", "
|
| 73 |
-
"capture_count": { "arg": "captureCountT", "
|
| 74 |
-
"state_update": { "arg": "stateUpdateT", "
|
| 75 |
-
"
|
| 76 |
"name": "params",
|
| 77 |
-
"buffer": "uniform",
|
| 78 |
"struct": [
|
| 79 |
{ "name": "batchSize", "type": "u32", "value": "batchSize" },
|
| 80 |
{ "name": "channels", "type": "u32", "value": "channels" },
|
| 81 |
{ "name": "totalTokens", "type": "u32", "value": "totalTokens" },
|
| 82 |
{ "name": "stateUpdateCapacity", "type": "u32", "value": "stateUpdateCapacity" }
|
| 83 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
}
|
| 85 |
},
|
| 86 |
"variants": [
|
| 87 |
{
|
| 88 |
-
"id": "
|
| 89 |
-
"priority":
|
| 90 |
-
"when": ["plainContract", "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
"derive": {
|
| 92 |
"hasBias": false,
|
| 93 |
-
"useSilu": "attrs.activation != \"none\"",
|
| 94 |
"inputScalar": "dtypes.T",
|
| 95 |
"outputScalar": "dtypes.T",
|
| 96 |
"workgroupSize": "tunables.streamWorkgroupSize",
|
| 97 |
"chunkSize": "min(tunables.streamChunk, ceilDiv(totalTokens, batchSize))"
|
| 98 |
},
|
| 99 |
"passes": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
{
|
| 101 |
"id": "main",
|
| 102 |
"name": "VarlenCausalConvWithState.Stream",
|
|
@@ -111,38 +252,51 @@
|
|
| 111 |
]
|
| 112 |
},
|
| 113 |
{
|
| 114 |
-
"id": "
|
| 115 |
-
"priority":
|
| 116 |
-
"when": ["
|
| 117 |
"derive": {
|
| 118 |
-
"hasBias":
|
| 119 |
-
"useSilu": "attrs.activation != \"none\"",
|
| 120 |
"inputScalar": "dtypes.T",
|
| 121 |
"outputScalar": "dtypes.T",
|
| 122 |
-
"workgroupSize": "tunables.
|
| 123 |
-
"chunkSize": "min(tunables.streamChunk, ceilDiv(totalTokens, batchSize))"
|
| 124 |
},
|
| 125 |
"passes": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
{
|
| 127 |
"id": "main",
|
| 128 |
-
"name": "VarlenCausalConvWithState
|
| 129 |
-
"shader": "varlen-causal-conv
|
| 130 |
-
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "
|
| 131 |
"dispatch": {
|
| 132 |
-
"x": "min(ceilDiv((
|
| 133 |
-
"y": "ceilDiv(ceilDiv((
|
| 134 |
"z": 1
|
| 135 |
}
|
| 136 |
}
|
| 137 |
]
|
| 138 |
},
|
| 139 |
{
|
| 140 |
-
"id": "
|
| 141 |
-
"priority":
|
| 142 |
-
"when": ["
|
| 143 |
"derive": {
|
| 144 |
-
"hasBias":
|
| 145 |
-
"useSilu": "attrs.activation != \"none\"",
|
| 146 |
"inputScalar": "dtypes.T",
|
| 147 |
"outputScalar": "dtypes.T",
|
| 148 |
"workgroupSize": "tunables.streamWorkgroupSize",
|
|
@@ -153,18 +307,23 @@
|
|
| 153 |
"id": "state_update",
|
| 154 |
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 155 |
"shader": "varlen-state-update.wgsl.jinja",
|
| 156 |
-
"bindings": ["
|
| 157 |
"dispatch": {
|
| 158 |
-
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 159 |
-
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 160 |
"z": 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
}
|
| 162 |
},
|
| 163 |
{
|
| 164 |
"id": "main",
|
| 165 |
"name": "VarlenCausalConvWithState.Stream",
|
| 166 |
"shader": "varlen-causal-conv-stream.wgsl.jinja",
|
| 167 |
-
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "output", "final_state", "params"],
|
| 168 |
"dispatch": {
|
| 169 |
"x": "min(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 170 |
"y": "ceilDiv(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
|
@@ -174,34 +333,62 @@
|
|
| 174 |
]
|
| 175 |
},
|
| 176 |
{
|
| 177 |
-
"id": "
|
| 178 |
-
"priority":
|
| 179 |
-
"when": ["biasStateUpdateContract", "
|
| 180 |
"derive": {
|
| 181 |
"hasBias": true,
|
| 182 |
-
"useSilu": "attrs.activation != \"none\"",
|
| 183 |
"inputScalar": "dtypes.T",
|
| 184 |
"outputScalar": "dtypes.T",
|
| 185 |
-
"workgroupSize": "tunables.
|
| 186 |
-
"chunkSize": "min(tunables.streamChunk, ceilDiv(totalTokens, batchSize))"
|
| 187 |
},
|
| 188 |
"passes": [
|
| 189 |
{
|
| 190 |
"id": "state_update",
|
| 191 |
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 192 |
"shader": "varlen-state-update.wgsl.jinja",
|
| 193 |
-
"bindings": ["
|
| 194 |
"dispatch": {
|
| 195 |
-
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 196 |
-
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 197 |
"z": 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
}
|
| 199 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
{
|
| 201 |
"id": "main",
|
| 202 |
"name": "VarlenCausalConvWithState.Stream",
|
| 203 |
"shader": "varlen-causal-conv-stream.wgsl.jinja",
|
| 204 |
-
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "
|
| 205 |
"dispatch": {
|
| 206 |
"x": "min(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 207 |
"y": "ceilDiv(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
|
@@ -215,8 +402,7 @@
|
|
| 215 |
"priority": 0,
|
| 216 |
"when": ["plainContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX"],
|
| 217 |
"derive": {
|
| 218 |
-
"hasBias":
|
| 219 |
-
"useSilu": "attrs.activation != \"none\"",
|
| 220 |
"inputScalar": "dtypes.T",
|
| 221 |
"outputScalar": "dtypes.T",
|
| 222 |
"workgroupSize": "tunables.workgroupSize"
|
|
@@ -235,13 +421,37 @@
|
|
| 235 |
}
|
| 236 |
]
|
| 237 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
{
|
| 239 |
"id": "bias",
|
| 240 |
"priority": 0,
|
| 241 |
"when": ["biasContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX"],
|
| 242 |
"derive": {
|
| 243 |
-
"hasBias":
|
| 244 |
-
"useSilu": "attrs.activation != \"none\"",
|
| 245 |
"inputScalar": "dtypes.T",
|
| 246 |
"outputScalar": "dtypes.T",
|
| 247 |
"workgroupSize": "tunables.workgroupSize"
|
|
@@ -260,13 +470,48 @@
|
|
| 260 |
}
|
| 261 |
]
|
| 262 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
{
|
| 264 |
"id": "state_update",
|
| 265 |
"priority": 0,
|
| 266 |
"when": ["stateUpdateContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX"],
|
| 267 |
"derive": {
|
| 268 |
-
"hasBias":
|
| 269 |
-
"useSilu": "attrs.activation != \"none\"",
|
| 270 |
"inputScalar": "dtypes.T",
|
| 271 |
"outputScalar": "dtypes.T",
|
| 272 |
"workgroupSize": "tunables.workgroupSize"
|
|
@@ -276,7 +521,7 @@
|
|
| 276 |
"id": "state_update",
|
| 277 |
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 278 |
"shader": "varlen-state-update.wgsl.jinja",
|
| 279 |
-
"bindings": ["input", "cumulative_sequence_length", "capture_count", "state_update", "
|
| 280 |
"dispatch": {
|
| 281 |
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 282 |
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
|
@@ -296,13 +541,48 @@
|
|
| 296 |
}
|
| 297 |
]
|
| 298 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 299 |
{
|
| 300 |
"id": "bias_state_update",
|
| 301 |
"priority": 0,
|
| 302 |
"when": ["biasStateUpdateContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX"],
|
| 303 |
"derive": {
|
| 304 |
-
"hasBias":
|
| 305 |
-
"useSilu": "attrs.activation != \"none\"",
|
| 306 |
"inputScalar": "dtypes.T",
|
| 307 |
"outputScalar": "dtypes.T",
|
| 308 |
"workgroupSize": "tunables.workgroupSize"
|
|
@@ -312,7 +592,7 @@
|
|
| 312 |
"id": "state_update",
|
| 313 |
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 314 |
"shader": "varlen-state-update.wgsl.jinja",
|
| 315 |
-
"bindings": ["input", "cumulative_sequence_length", "capture_count", "state_update", "
|
| 316 |
"dispatch": {
|
| 317 |
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 318 |
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
|
|
|
| 21 |
"shape": "[batchSize, stateUpdateCapacity, channels]"
|
| 22 |
}
|
| 23 |
},
|
| 24 |
+
"attributes": {
|
| 25 |
+
"activation": { "default": "none" },
|
| 26 |
+
"dilation": { "default": 1 },
|
| 27 |
+
"state_update_capacity": { "default": 0 }
|
| 28 |
+
},
|
| 29 |
"attributeConstraints": { "activation": { "values": ["none", "silu", "swish"] } },
|
| 30 |
"typeConstraints": { "T": ["float32", "float16"], "M": ["int32"] },
|
| 31 |
"tunables": {
|
|
|
|
| 39 |
"batchSize": "dim(shapes.cumulativeSequenceLengthT, 0) - 1",
|
| 40 |
"weightRankOk": "ranks.weightT == 3 and dim(shapes.weightT, 1) == 1",
|
| 41 |
"kernelSize": "dim(shapes.weightT, 2)",
|
| 42 |
+
"stateLength": "(kernelSize - 1) * attrs.dilation",
|
| 43 |
"stateUpdateCapacity": "attrs.state_update_capacity",
|
| 44 |
"capturePairOk": "present.captureCountT == (stateUpdateCapacity > 0)",
|
| 45 |
"stateShape": "ranks.initialStateT == 3 and dim(shapes.initialStateT, 0) == batchSize and dim(shapes.initialStateT, 1) == channels and dim(shapes.initialStateT, 2) == stateLength",
|
| 46 |
"finalStateShape": "ranks.finalStateT == 3 and dim(shapes.finalStateT, 0) == batchSize and dim(shapes.finalStateT, 1) == channels and dim(shapes.finalStateT, 2) == stateLength",
|
| 47 |
"captureShape": "not present.captureCountT or (ranks.captureCountT == 1 and dim(shapes.captureCountT, 0) == batchSize and tensorDtypes.captureCountT == \"int32\")",
|
| 48 |
"stateUpdateShape": "not present.stateUpdateT or (ranks.stateUpdateT == 3 and dim(shapes.stateUpdateT, 0) == batchSize and dim(shapes.stateUpdateT, 1) == stateUpdateCapacity and dim(shapes.stateUpdateT, 2) == channels and tensorDtypes.stateUpdateT == tensorDtypes.inputT)",
|
| 49 |
+
"commonContract": "ranks.inputT == 2 and weightRankOk and ranks.outputT == 2 and ranks.cumulativeSequenceLengthT == 1 and channels >= 1 and kernelSize >= 1 and batchSize >= 1 and totalTokens >= batchSize and stateUpdateCapacity >= 0 and stateUpdateCapacity <= 8 and floor(stateUpdateCapacity) == stateUpdateCapacity and capturePairOk and captureShape and stateUpdateShape and (tensorDtypes.inputT == \"float32\" or tensorDtypes.inputT == \"float16\") and tensorDtypes.weightT == tensorDtypes.inputT and tensorDtypes.outputT == tensorDtypes.inputT and tensorDtypes.initialStateT == tensorDtypes.inputT and tensorDtypes.finalStateT == tensorDtypes.inputT and tensorDtypes.cumulativeSequenceLengthT == \"int32\" and f16Ok(dtypes.T) and dim(shapes.weightT, 0) == channels and dim(shapes.outputT, 0) == totalTokens and dim(shapes.outputT, 1) == channels and stateShape and finalStateShape and attrs.dilation >= 1 and floor(attrs.dilation) == attrs.dilation",
|
| 50 |
"biasOk": "ranks.biasT == 1 and tensorDtypes.biasT == tensorDtypes.inputT and dim(shapes.biasT, 0) == channels",
|
| 51 |
"plainContract": "commonContract and not present.biasT and (not present.stateUpdateT or stateUpdateCapacity == 0)",
|
| 52 |
"biasContract": "commonContract and present.biasT and biasOk and (not present.stateUpdateT or stateUpdateCapacity == 0)",
|
| 53 |
"stateUpdateContract": "commonContract and not present.biasT and present.stateUpdateT and stateUpdateCapacity > 0",
|
| 54 |
+
"biasStateUpdateContract": "commonContract and present.biasT and biasOk and present.stateUpdateT and stateUpdateCapacity > 0",
|
| 55 |
+
"causalDilation": "attrs.dilation",
|
| 56 |
+
"unitWg": "min(tunables.streamWorkgroupSize, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)",
|
| 57 |
+
"useSilu": "attrs.activation != \"none\""
|
| 58 |
},
|
| 59 |
"bindings": {
|
| 60 |
+
"input": { "arg": "inputT", "elementType": "$inputScalar" },
|
| 61 |
+
"weight": { "arg": "weightT", "elementType": "$inputScalar" },
|
| 62 |
+
"cumulative_sequence_length": { "arg": "cumulativeSequenceLengthT", "elementType": "i32" },
|
| 63 |
+
"initial_state": { "arg": "initialStateT", "elementType": "$inputScalar" },
|
| 64 |
+
"output": { "arg": "outputT", "elementType": "$outputScalar" },
|
| 65 |
+
"final_state": { "arg": "finalStateT", "elementType": "$outputScalar" },
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
"params": {
|
|
|
|
| 67 |
"struct": [
|
| 68 |
{ "name": "batchSize", "type": "u32", "value": "batchSize" },
|
| 69 |
{ "name": "channels", "type": "u32", "value": "channels" },
|
|
|
|
| 71 |
{ "name": "kernelSize", "type": "u32", "value": "kernelSize" }
|
| 72 |
]
|
| 73 |
},
|
| 74 |
+
"bias": { "arg": "biasT", "elementType": "$inputScalar" },
|
| 75 |
+
"capture_count": { "arg": "captureCountT", "elementType": "i32" },
|
| 76 |
+
"state_update": { "arg": "stateUpdateT", "elementType": "$outputScalar" },
|
| 77 |
+
"params__uniform": {
|
| 78 |
"name": "params",
|
|
|
|
| 79 |
"struct": [
|
| 80 |
{ "name": "batchSize", "type": "u32", "value": "batchSize" },
|
| 81 |
{ "name": "channels", "type": "u32", "value": "channels" },
|
| 82 |
{ "name": "totalTokens", "type": "u32", "value": "totalTokens" },
|
| 83 |
{ "name": "stateUpdateCapacity", "type": "u32", "value": "stateUpdateCapacity" }
|
| 84 |
]
|
| 85 |
+
},
|
| 86 |
+
"input_unit": { "arg": "inputT", "name": "input", "elementType": "$unitStorageType" },
|
| 87 |
+
"bias_unit": { "arg": "biasT", "name": "bias", "elementType": "$unitStorageType" },
|
| 88 |
+
"output_unit": { "arg": "outputT", "name": "output", "elementType": "$unitStorageType" },
|
| 89 |
+
"state_update_unit": { "arg": "stateUpdateT", "name": "state_update", "elementType": "$unitStorageType" },
|
| 90 |
+
"params_unit": {
|
| 91 |
+
"name": "params",
|
| 92 |
+
"struct": [
|
| 93 |
+
{ "name": "channels", "type": "u32", "value": "channels" },
|
| 94 |
+
{ "name": "totalTokens", "type": "u32", "value": "totalTokens" }
|
| 95 |
+
]
|
| 96 |
+
},
|
| 97 |
+
"weight_unit": { "arg": "weightT", "elementType": "$unitStorageType", "name": "weight" },
|
| 98 |
+
"initial_state_unit": { "arg": "initialStateT", "elementType": "$unitStorageType", "name": "initial_state" },
|
| 99 |
+
"final_state_unit": { "arg": "finalStateT", "elementType": "$unitStorageType", "name": "final_state" },
|
| 100 |
+
"input_capture": { "arg": "inputT", "name": "input", "elementType": "$captureStorageType" },
|
| 101 |
+
"state_update_capture": { "arg": "stateUpdateT", "name": "state_update", "elementType": "$captureStorageType" },
|
| 102 |
+
"params_capture": {
|
| 103 |
+
"name": "params",
|
| 104 |
+
"struct": [
|
| 105 |
+
{ "name": "batchSize", "type": "u32", "value": "batchSize" },
|
| 106 |
+
{ "name": "channels", "type": "u32", "value": "channels / captureVectorWidth" },
|
| 107 |
+
{ "name": "totalTokens", "type": "u32", "value": "totalTokens" },
|
| 108 |
+
{ "name": "stateUpdateCapacity", "type": "u32", "value": "stateUpdateCapacity" }
|
| 109 |
+
]
|
| 110 |
}
|
| 111 |
},
|
| 112 |
"variants": [
|
| 113 |
{
|
| 114 |
+
"id": "unit_plain",
|
| 115 |
+
"priority": 50,
|
| 116 |
+
"when": ["plainContract", "tensorDtypes.inputT == \"float32\"", "totalTokens == batchSize", "attrs.dilation == 1", "kernelSize >= 2", "kernelSize <= 8", "unitWg >= 1", "floor(unitWg) == unitWg"],
|
| 117 |
+
"derive": {
|
| 118 |
+
"hasBias": false,
|
| 119 |
+
"hasCapture": false,
|
| 120 |
+
"unitVectorWidth": "4 if channels % 4 == 0 else (2 if channels % 2 == 0 else 1)",
|
| 121 |
+
"unitStorageType": "dtypes.T if unitVectorWidth == 1 else \"vec\" ~ unitVectorWidth ~ \"<\" ~ dtypes.T ~ \">\"",
|
| 122 |
+
"unitValueType": "\"f32\" if unitVectorWidth == 1 else \"vec\" ~ unitVectorWidth ~ \"<f32>\""
|
| 123 |
+
},
|
| 124 |
+
"passes": [
|
| 125 |
+
{
|
| 126 |
+
"id": "main",
|
| 127 |
+
"name": "VarlenCausalConvWithState.UnitSequence",
|
| 128 |
+
"shader": "varlen-unit-sequence.wgsl.jinja",
|
| 129 |
+
"bindings": ["input_unit", "weight_unit", "initial_state_unit", "output_unit", "final_state_unit", "params_unit"],
|
| 130 |
+
"dispatch": {
|
| 131 |
+
"x": "min(ceilDiv((totalTokens * channels / unitVectorWidth), (unitWg)), 65535)",
|
| 132 |
+
"y": "ceilDiv(ceilDiv((totalTokens * channels / unitVectorWidth), (unitWg)), 65535)",
|
| 133 |
+
"z": 1
|
| 134 |
+
}
|
| 135 |
+
}
|
| 136 |
+
]
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"id": "unit_bias",
|
| 140 |
+
"priority": 50,
|
| 141 |
+
"when": ["biasContract", "tensorDtypes.inputT == \"float32\"", "totalTokens == batchSize", "attrs.dilation == 1", "kernelSize >= 2", "kernelSize <= 8", "unitWg >= 1", "floor(unitWg) == unitWg"],
|
| 142 |
+
"derive": {
|
| 143 |
+
"hasBias": true,
|
| 144 |
+
"hasCapture": false,
|
| 145 |
+
"unitVectorWidth": "4 if channels % 4 == 0 else (2 if channels % 2 == 0 else 1)",
|
| 146 |
+
"unitStorageType": "dtypes.T if unitVectorWidth == 1 else \"vec\" ~ unitVectorWidth ~ \"<\" ~ dtypes.T ~ \">\"",
|
| 147 |
+
"unitValueType": "\"f32\" if unitVectorWidth == 1 else \"vec\" ~ unitVectorWidth ~ \"<f32>\""
|
| 148 |
+
},
|
| 149 |
+
"passes": [
|
| 150 |
+
{
|
| 151 |
+
"id": "main",
|
| 152 |
+
"name": "VarlenCausalConvWithState.UnitSequence",
|
| 153 |
+
"shader": "varlen-unit-sequence.wgsl.jinja",
|
| 154 |
+
"bindings": ["input_unit", "weight_unit", "initial_state_unit", "bias_unit", "output_unit", "final_state_unit", "params_unit"],
|
| 155 |
+
"dispatch": {
|
| 156 |
+
"x": "min(ceilDiv((totalTokens * channels / unitVectorWidth), (unitWg)), 65535)",
|
| 157 |
+
"y": "ceilDiv(ceilDiv((totalTokens * channels / unitVectorWidth), (unitWg)), 65535)",
|
| 158 |
+
"z": 1
|
| 159 |
+
}
|
| 160 |
+
}
|
| 161 |
+
]
|
| 162 |
+
},
|
| 163 |
+
{
|
| 164 |
+
"id": "unit_state_update",
|
| 165 |
+
"priority": 50,
|
| 166 |
+
"when": ["stateUpdateContract", "tensorDtypes.inputT == \"float32\"", "totalTokens == batchSize", "attrs.dilation == 1", "kernelSize >= 2", "kernelSize <= 8", "unitWg >= 1", "floor(unitWg) == unitWg"],
|
| 167 |
+
"derive": {
|
| 168 |
+
"hasBias": false,
|
| 169 |
+
"hasCapture": true,
|
| 170 |
+
"unitVectorWidth": "4 if channels % 4 == 0 else (2 if channels % 2 == 0 else 1)",
|
| 171 |
+
"unitStorageType": "dtypes.T if unitVectorWidth == 1 else \"vec\" ~ unitVectorWidth ~ \"<\" ~ dtypes.T ~ \">\"",
|
| 172 |
+
"unitValueType": "\"f32\" if unitVectorWidth == 1 else \"vec\" ~ unitVectorWidth ~ \"<f32>\""
|
| 173 |
+
},
|
| 174 |
+
"passes": [
|
| 175 |
+
{
|
| 176 |
+
"id": "main",
|
| 177 |
+
"name": "VarlenCausalConvWithState.UnitSequence",
|
| 178 |
+
"shader": "varlen-unit-sequence.wgsl.jinja",
|
| 179 |
+
"bindings": ["input_unit", "weight_unit", "initial_state_unit", "output_unit", "final_state_unit", "params_unit", "capture_count", "state_update_unit"],
|
| 180 |
+
"dispatch": {
|
| 181 |
+
"x": "min(ceilDiv((totalTokens * channels / unitVectorWidth), (unitWg)), 65535)",
|
| 182 |
+
"y": "ceilDiv(ceilDiv((totalTokens * channels / unitVectorWidth), (unitWg)), 65535)",
|
| 183 |
+
"z": 1
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
]
|
| 187 |
+
},
|
| 188 |
+
{
|
| 189 |
+
"id": "unit_bias_state_update",
|
| 190 |
+
"priority": 50,
|
| 191 |
+
"when": ["biasStateUpdateContract", "tensorDtypes.inputT == \"float32\"", "totalTokens == batchSize", "attrs.dilation == 1", "kernelSize >= 2", "kernelSize <= 8", "unitWg >= 1", "floor(unitWg) == unitWg"],
|
| 192 |
+
"derive": {
|
| 193 |
+
"hasBias": true,
|
| 194 |
+
"hasCapture": true,
|
| 195 |
+
"unitVectorWidth": "4 if channels % 4 == 0 else (2 if channels % 2 == 0 else 1)",
|
| 196 |
+
"unitStorageType": "dtypes.T if unitVectorWidth == 1 else \"vec\" ~ unitVectorWidth ~ \"<\" ~ dtypes.T ~ \">\"",
|
| 197 |
+
"unitValueType": "\"f32\" if unitVectorWidth == 1 else \"vec\" ~ unitVectorWidth ~ \"<f32>\""
|
| 198 |
+
},
|
| 199 |
+
"passes": [
|
| 200 |
+
{
|
| 201 |
+
"id": "main",
|
| 202 |
+
"name": "VarlenCausalConvWithState.UnitSequence",
|
| 203 |
+
"shader": "varlen-unit-sequence.wgsl.jinja",
|
| 204 |
+
"bindings": ["input_unit", "weight_unit", "initial_state_unit", "bias_unit", "output_unit", "final_state_unit", "params_unit", "capture_count", "state_update_unit"],
|
| 205 |
+
"dispatch": {
|
| 206 |
+
"x": "min(ceilDiv((totalTokens * channels / unitVectorWidth), (unitWg)), 65535)",
|
| 207 |
+
"y": "ceilDiv(ceilDiv((totalTokens * channels / unitVectorWidth), (unitWg)), 65535)",
|
| 208 |
+
"z": 1
|
| 209 |
+
}
|
| 210 |
+
}
|
| 211 |
+
]
|
| 212 |
+
},
|
| 213 |
+
{
|
| 214 |
+
"id": "capture_copy_state_update_stream",
|
| 215 |
+
"priority": 25,
|
| 216 |
+
"when": ["stateUpdateContract", "kernelSize >= 2", "kernelSize <= 8", "tunables.streamChunk >= 1", "floor(tunables.streamChunk) == tunables.streamChunk", "tunables.streamWorkgroupSize >= 1", "floor(tunables.streamWorkgroupSize) == tunables.streamWorkgroupSize", "tunables.streamWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.streamWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "attrs.dilation == 1", "tensorDtypes.inputT == \"float32\"", "channels % 2 == 0"],
|
| 217 |
"derive": {
|
| 218 |
"hasBias": false,
|
|
|
|
| 219 |
"inputScalar": "dtypes.T",
|
| 220 |
"outputScalar": "dtypes.T",
|
| 221 |
"workgroupSize": "tunables.streamWorkgroupSize",
|
| 222 |
"chunkSize": "min(tunables.streamChunk, ceilDiv(totalTokens, batchSize))"
|
| 223 |
},
|
| 224 |
"passes": [
|
| 225 |
+
{
|
| 226 |
+
"id": "state_update",
|
| 227 |
+
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 228 |
+
"shader": "varlen-state-update.wgsl.jinja",
|
| 229 |
+
"bindings": ["input_capture", "cumulative_sequence_length", "capture_count", "state_update_capture", "params_capture"],
|
| 230 |
+
"dispatch": {
|
| 231 |
+
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels / captureVectorWidth), (workgroupSize)), 65535)",
|
| 232 |
+
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels / captureVectorWidth), (workgroupSize)), 65535)",
|
| 233 |
+
"z": 1
|
| 234 |
+
},
|
| 235 |
+
"derive": {
|
| 236 |
+
"captureVectorWidth": "4 if channels % 4 == 0 else 2",
|
| 237 |
+
"captureStorageType": "\"vec\" ~ captureVectorWidth ~ \"<\" ~ dtypes.T ~ \">\"",
|
| 238 |
+
"outputScalar": "captureStorageType"
|
| 239 |
+
}
|
| 240 |
+
},
|
| 241 |
{
|
| 242 |
"id": "main",
|
| 243 |
"name": "VarlenCausalConvWithState.Stream",
|
|
|
|
| 252 |
]
|
| 253 |
},
|
| 254 |
{
|
| 255 |
+
"id": "capture_copy_state_update",
|
| 256 |
+
"priority": 5,
|
| 257 |
+
"when": ["stateUpdateContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX", "tensorDtypes.inputT == \"float32\"", "channels % 2 == 0"],
|
| 258 |
"derive": {
|
| 259 |
+
"hasBias": false,
|
|
|
|
| 260 |
"inputScalar": "dtypes.T",
|
| 261 |
"outputScalar": "dtypes.T",
|
| 262 |
+
"workgroupSize": "tunables.workgroupSize"
|
|
|
|
| 263 |
},
|
| 264 |
"passes": [
|
| 265 |
+
{
|
| 266 |
+
"id": "state_update",
|
| 267 |
+
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 268 |
+
"shader": "varlen-state-update.wgsl.jinja",
|
| 269 |
+
"bindings": ["input_capture", "cumulative_sequence_length", "capture_count", "state_update_capture", "params_capture"],
|
| 270 |
+
"dispatch": {
|
| 271 |
+
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels / captureVectorWidth), (workgroupSize)), 65535)",
|
| 272 |
+
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels / captureVectorWidth), (workgroupSize)), 65535)",
|
| 273 |
+
"z": 1
|
| 274 |
+
},
|
| 275 |
+
"derive": {
|
| 276 |
+
"captureVectorWidth": "4 if channels % 4 == 0 else 2",
|
| 277 |
+
"captureStorageType": "\"vec\" ~ captureVectorWidth ~ \"<\" ~ dtypes.T ~ \">\"",
|
| 278 |
+
"outputScalar": "captureStorageType"
|
| 279 |
+
}
|
| 280 |
+
},
|
| 281 |
{
|
| 282 |
"id": "main",
|
| 283 |
+
"name": "VarlenCausalConvWithState",
|
| 284 |
+
"shader": "varlen-causal-conv.wgsl.jinja",
|
| 285 |
+
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "output", "final_state", "params"],
|
| 286 |
"dispatch": {
|
| 287 |
+
"x": "min(ceilDiv((totalTokens * channels), (workgroupSize)), 65535)",
|
| 288 |
+
"y": "ceilDiv(ceilDiv((totalTokens * channels), (workgroupSize)), 65535)",
|
| 289 |
"z": 1
|
| 290 |
}
|
| 291 |
}
|
| 292 |
]
|
| 293 |
},
|
| 294 |
{
|
| 295 |
+
"id": "capture_copy_bias_state_update_stream",
|
| 296 |
+
"priority": 25,
|
| 297 |
+
"when": ["biasStateUpdateContract", "kernelSize >= 2", "kernelSize <= 8", "tunables.streamChunk >= 1", "floor(tunables.streamChunk) == tunables.streamChunk", "tunables.streamWorkgroupSize >= 1", "floor(tunables.streamWorkgroupSize) == tunables.streamWorkgroupSize", "tunables.streamWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.streamWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "attrs.dilation == 1", "tensorDtypes.inputT == \"float32\"", "channels % 2 == 0"],
|
| 298 |
"derive": {
|
| 299 |
+
"hasBias": true,
|
|
|
|
| 300 |
"inputScalar": "dtypes.T",
|
| 301 |
"outputScalar": "dtypes.T",
|
| 302 |
"workgroupSize": "tunables.streamWorkgroupSize",
|
|
|
|
| 307 |
"id": "state_update",
|
| 308 |
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 309 |
"shader": "varlen-state-update.wgsl.jinja",
|
| 310 |
+
"bindings": ["input_capture", "cumulative_sequence_length", "capture_count", "state_update_capture", "params_capture"],
|
| 311 |
"dispatch": {
|
| 312 |
+
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels / captureVectorWidth), (workgroupSize)), 65535)",
|
| 313 |
+
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels / captureVectorWidth), (workgroupSize)), 65535)",
|
| 314 |
"z": 1
|
| 315 |
+
},
|
| 316 |
+
"derive": {
|
| 317 |
+
"captureVectorWidth": "4 if channels % 4 == 0 else 2",
|
| 318 |
+
"captureStorageType": "\"vec\" ~ captureVectorWidth ~ \"<\" ~ dtypes.T ~ \">\"",
|
| 319 |
+
"outputScalar": "captureStorageType"
|
| 320 |
}
|
| 321 |
},
|
| 322 |
{
|
| 323 |
"id": "main",
|
| 324 |
"name": "VarlenCausalConvWithState.Stream",
|
| 325 |
"shader": "varlen-causal-conv-stream.wgsl.jinja",
|
| 326 |
+
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "bias", "output", "final_state", "params"],
|
| 327 |
"dispatch": {
|
| 328 |
"x": "min(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 329 |
"y": "ceilDiv(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
|
|
|
| 333 |
]
|
| 334 |
},
|
| 335 |
{
|
| 336 |
+
"id": "capture_copy_bias_state_update",
|
| 337 |
+
"priority": 5,
|
| 338 |
+
"when": ["biasStateUpdateContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX", "tensorDtypes.inputT == \"float32\"", "channels % 2 == 0"],
|
| 339 |
"derive": {
|
| 340 |
"hasBias": true,
|
|
|
|
| 341 |
"inputScalar": "dtypes.T",
|
| 342 |
"outputScalar": "dtypes.T",
|
| 343 |
+
"workgroupSize": "tunables.workgroupSize"
|
|
|
|
| 344 |
},
|
| 345 |
"passes": [
|
| 346 |
{
|
| 347 |
"id": "state_update",
|
| 348 |
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 349 |
"shader": "varlen-state-update.wgsl.jinja",
|
| 350 |
+
"bindings": ["input_capture", "cumulative_sequence_length", "capture_count", "state_update_capture", "params_capture"],
|
| 351 |
"dispatch": {
|
| 352 |
+
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels / captureVectorWidth), (workgroupSize)), 65535)",
|
| 353 |
+
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels / captureVectorWidth), (workgroupSize)), 65535)",
|
| 354 |
"z": 1
|
| 355 |
+
},
|
| 356 |
+
"derive": {
|
| 357 |
+
"captureVectorWidth": "4 if channels % 4 == 0 else 2",
|
| 358 |
+
"captureStorageType": "\"vec\" ~ captureVectorWidth ~ \"<\" ~ dtypes.T ~ \">\"",
|
| 359 |
+
"outputScalar": "captureStorageType"
|
| 360 |
}
|
| 361 |
},
|
| 362 |
+
{
|
| 363 |
+
"id": "main",
|
| 364 |
+
"name": "VarlenCausalConvWithState",
|
| 365 |
+
"shader": "varlen-causal-conv.wgsl.jinja",
|
| 366 |
+
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "bias", "output", "final_state", "params"],
|
| 367 |
+
"dispatch": {
|
| 368 |
+
"x": "min(ceilDiv((totalTokens * channels), (workgroupSize)), 65535)",
|
| 369 |
+
"y": "ceilDiv(ceilDiv((totalTokens * channels), (workgroupSize)), 65535)",
|
| 370 |
+
"z": 1
|
| 371 |
+
}
|
| 372 |
+
}
|
| 373 |
+
]
|
| 374 |
+
},
|
| 375 |
+
{
|
| 376 |
+
"id": "plain_stream",
|
| 377 |
+
"priority": 20,
|
| 378 |
+
"when": ["plainContract", "kernelSize >= 2", "kernelSize <= 8", "tunables.streamChunk >= 1", "floor(tunables.streamChunk) == tunables.streamChunk", "tunables.streamWorkgroupSize >= 1", "floor(tunables.streamWorkgroupSize) == tunables.streamWorkgroupSize", "tunables.streamWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.streamWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "attrs.dilation == 1"],
|
| 379 |
+
"derive": {
|
| 380 |
+
"hasBias": "present.biasT",
|
| 381 |
+
"inputScalar": "dtypes.T",
|
| 382 |
+
"outputScalar": "dtypes.T",
|
| 383 |
+
"workgroupSize": "tunables.streamWorkgroupSize",
|
| 384 |
+
"chunkSize": "min(tunables.streamChunk, ceilDiv(totalTokens, batchSize))"
|
| 385 |
+
},
|
| 386 |
+
"passes": [
|
| 387 |
{
|
| 388 |
"id": "main",
|
| 389 |
"name": "VarlenCausalConvWithState.Stream",
|
| 390 |
"shader": "varlen-causal-conv-stream.wgsl.jinja",
|
| 391 |
+
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "output", "final_state", "params"],
|
| 392 |
"dispatch": {
|
| 393 |
"x": "min(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 394 |
"y": "ceilDiv(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
|
|
|
| 402 |
"priority": 0,
|
| 403 |
"when": ["plainContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX"],
|
| 404 |
"derive": {
|
| 405 |
+
"hasBias": "present.biasT",
|
|
|
|
| 406 |
"inputScalar": "dtypes.T",
|
| 407 |
"outputScalar": "dtypes.T",
|
| 408 |
"workgroupSize": "tunables.workgroupSize"
|
|
|
|
| 421 |
}
|
| 422 |
]
|
| 423 |
},
|
| 424 |
+
{
|
| 425 |
+
"id": "bias_stream",
|
| 426 |
+
"priority": 20,
|
| 427 |
+
"when": ["biasContract", "kernelSize >= 2", "kernelSize <= 8", "tunables.streamChunk >= 1", "floor(tunables.streamChunk) == tunables.streamChunk", "tunables.streamWorkgroupSize >= 1", "floor(tunables.streamWorkgroupSize) == tunables.streamWorkgroupSize", "tunables.streamWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.streamWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "attrs.dilation == 1"],
|
| 428 |
+
"derive": {
|
| 429 |
+
"hasBias": "present.biasT",
|
| 430 |
+
"inputScalar": "dtypes.T",
|
| 431 |
+
"outputScalar": "dtypes.T",
|
| 432 |
+
"workgroupSize": "tunables.streamWorkgroupSize",
|
| 433 |
+
"chunkSize": "min(tunables.streamChunk, ceilDiv(totalTokens, batchSize))"
|
| 434 |
+
},
|
| 435 |
+
"passes": [
|
| 436 |
+
{
|
| 437 |
+
"id": "main",
|
| 438 |
+
"name": "VarlenCausalConvWithState.Stream",
|
| 439 |
+
"shader": "varlen-causal-conv-stream.wgsl.jinja",
|
| 440 |
+
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "bias", "output", "final_state", "params"],
|
| 441 |
+
"dispatch": {
|
| 442 |
+
"x": "min(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 443 |
+
"y": "ceilDiv(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 444 |
+
"z": 1
|
| 445 |
+
}
|
| 446 |
+
}
|
| 447 |
+
]
|
| 448 |
+
},
|
| 449 |
{
|
| 450 |
"id": "bias",
|
| 451 |
"priority": 0,
|
| 452 |
"when": ["biasContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX"],
|
| 453 |
"derive": {
|
| 454 |
+
"hasBias": "present.biasT",
|
|
|
|
| 455 |
"inputScalar": "dtypes.T",
|
| 456 |
"outputScalar": "dtypes.T",
|
| 457 |
"workgroupSize": "tunables.workgroupSize"
|
|
|
|
| 470 |
}
|
| 471 |
]
|
| 472 |
},
|
| 473 |
+
{
|
| 474 |
+
"id": "state_update_stream",
|
| 475 |
+
"priority": 20,
|
| 476 |
+
"when": ["stateUpdateContract", "kernelSize >= 2", "kernelSize <= 8", "tunables.streamChunk >= 1", "floor(tunables.streamChunk) == tunables.streamChunk", "tunables.streamWorkgroupSize >= 1", "floor(tunables.streamWorkgroupSize) == tunables.streamWorkgroupSize", "tunables.streamWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.streamWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "attrs.dilation == 1"],
|
| 477 |
+
"derive": {
|
| 478 |
+
"hasBias": "present.biasT",
|
| 479 |
+
"inputScalar": "dtypes.T",
|
| 480 |
+
"outputScalar": "dtypes.T",
|
| 481 |
+
"workgroupSize": "tunables.streamWorkgroupSize",
|
| 482 |
+
"chunkSize": "min(tunables.streamChunk, ceilDiv(totalTokens, batchSize))"
|
| 483 |
+
},
|
| 484 |
+
"passes": [
|
| 485 |
+
{
|
| 486 |
+
"id": "state_update",
|
| 487 |
+
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 488 |
+
"shader": "varlen-state-update.wgsl.jinja",
|
| 489 |
+
"bindings": ["input", "cumulative_sequence_length", "capture_count", "state_update", "params__uniform"],
|
| 490 |
+
"dispatch": {
|
| 491 |
+
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 492 |
+
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 493 |
+
"z": 1
|
| 494 |
+
}
|
| 495 |
+
},
|
| 496 |
+
{
|
| 497 |
+
"id": "main",
|
| 498 |
+
"name": "VarlenCausalConvWithState.Stream",
|
| 499 |
+
"shader": "varlen-causal-conv-stream.wgsl.jinja",
|
| 500 |
+
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "output", "final_state", "params"],
|
| 501 |
+
"dispatch": {
|
| 502 |
+
"x": "min(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 503 |
+
"y": "ceilDiv(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 504 |
+
"z": 1
|
| 505 |
+
}
|
| 506 |
+
}
|
| 507 |
+
]
|
| 508 |
+
},
|
| 509 |
{
|
| 510 |
"id": "state_update",
|
| 511 |
"priority": 0,
|
| 512 |
"when": ["stateUpdateContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX"],
|
| 513 |
"derive": {
|
| 514 |
+
"hasBias": "present.biasT",
|
|
|
|
| 515 |
"inputScalar": "dtypes.T",
|
| 516 |
"outputScalar": "dtypes.T",
|
| 517 |
"workgroupSize": "tunables.workgroupSize"
|
|
|
|
| 521 |
"id": "state_update",
|
| 522 |
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 523 |
"shader": "varlen-state-update.wgsl.jinja",
|
| 524 |
+
"bindings": ["input", "cumulative_sequence_length", "capture_count", "state_update", "params__uniform"],
|
| 525 |
"dispatch": {
|
| 526 |
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 527 |
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
|
|
|
| 541 |
}
|
| 542 |
]
|
| 543 |
},
|
| 544 |
+
{
|
| 545 |
+
"id": "bias_state_update_stream",
|
| 546 |
+
"priority": 20,
|
| 547 |
+
"when": ["biasStateUpdateContract", "kernelSize >= 2", "kernelSize <= 8", "tunables.streamChunk >= 1", "floor(tunables.streamChunk) == tunables.streamChunk", "tunables.streamWorkgroupSize >= 1", "floor(tunables.streamWorkgroupSize) == tunables.streamWorkgroupSize", "tunables.streamWorkgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.streamWorkgroupSize <= device.limits.maxComputeWorkgroupSizeX", "attrs.dilation == 1"],
|
| 548 |
+
"derive": {
|
| 549 |
+
"hasBias": "present.biasT",
|
| 550 |
+
"inputScalar": "dtypes.T",
|
| 551 |
+
"outputScalar": "dtypes.T",
|
| 552 |
+
"workgroupSize": "tunables.streamWorkgroupSize",
|
| 553 |
+
"chunkSize": "min(tunables.streamChunk, ceilDiv(totalTokens, batchSize))"
|
| 554 |
+
},
|
| 555 |
+
"passes": [
|
| 556 |
+
{
|
| 557 |
+
"id": "state_update",
|
| 558 |
+
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 559 |
+
"shader": "varlen-state-update.wgsl.jinja",
|
| 560 |
+
"bindings": ["input", "cumulative_sequence_length", "capture_count", "state_update", "params__uniform"],
|
| 561 |
+
"dispatch": {
|
| 562 |
+
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 563 |
+
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 564 |
+
"z": 1
|
| 565 |
+
}
|
| 566 |
+
},
|
| 567 |
+
{
|
| 568 |
+
"id": "main",
|
| 569 |
+
"name": "VarlenCausalConvWithState.Stream",
|
| 570 |
+
"shader": "varlen-causal-conv-stream.wgsl.jinja",
|
| 571 |
+
"bindings": ["input", "weight", "cumulative_sequence_length", "initial_state", "bias", "output", "final_state", "params"],
|
| 572 |
+
"dispatch": {
|
| 573 |
+
"x": "min(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 574 |
+
"y": "ceilDiv(ceilDiv((ceilDiv(totalTokens, chunkSize) * channels), (workgroupSize)), 65535)",
|
| 575 |
+
"z": 1
|
| 576 |
+
}
|
| 577 |
+
}
|
| 578 |
+
]
|
| 579 |
+
},
|
| 580 |
{
|
| 581 |
"id": "bias_state_update",
|
| 582 |
"priority": 0,
|
| 583 |
"when": ["biasStateUpdateContract", "tunables.workgroupSize >= 1", "floor(tunables.workgroupSize) == tunables.workgroupSize", "tunables.workgroupSize <= device.limits.maxComputeInvocationsPerWorkgroup", "tunables.workgroupSize <= device.limits.maxComputeWorkgroupSizeX"],
|
| 584 |
"derive": {
|
| 585 |
+
"hasBias": "present.biasT",
|
|
|
|
| 586 |
"inputScalar": "dtypes.T",
|
| 587 |
"outputScalar": "dtypes.T",
|
| 588 |
"workgroupSize": "tunables.workgroupSize"
|
|
|
|
| 592 |
"id": "state_update",
|
| 593 |
"name": "VarlenCausalConvWithState.StateUpdate",
|
| 594 |
"shader": "varlen-state-update.wgsl.jinja",
|
| 595 |
+
"bindings": ["input", "cumulative_sequence_length", "capture_count", "state_update", "params__uniform"],
|
| 596 |
"dispatch": {
|
| 597 |
"x": "min(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
| 598 |
"y": "ceilDiv(ceilDiv((batchSize * stateUpdateCapacity * channels), (workgroupSize)), 65535)",
|
build/webgpu/metadata.json
CHANGED
|
@@ -1,31 +1,40 @@
|
|
| 1 |
{
|
| 2 |
"name": "com.microsoft.VarlenCausalConvWithState",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"backend": { "type": "webgpu" },
|
| 7 |
"digest": {
|
| 8 |
"algorithm": "sha256",
|
| 9 |
"files": {
|
| 10 |
-
"bench.json": "
|
| 11 |
-
"manifest.json": "
|
| 12 |
-
"test.json": "
|
| 13 |
-
"varlen-causal-conv-stream.wgsl.jinja": "
|
| 14 |
-
"varlen-causal-conv.wgsl.jinja": "
|
| 15 |
-
"varlen-state-update.wgsl.jinja": "aTGir5h/LQkg5ami41pKaH4EG8ybaltnnM0oJSJ6Neg="
|
|
|
|
| 16 |
}
|
| 17 |
},
|
| 18 |
-
"provenance": { "kernel": { "sha": "
|
| 19 |
"webgpu": {
|
| 20 |
-
"manifestSpec": "2.
|
| 21 |
"variants": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
"plain_stream": ["varlen-causal-conv-stream.wgsl.jinja"],
|
| 23 |
-
"bias_stream": ["varlen-causal-conv-stream.wgsl.jinja"],
|
| 24 |
-
"state_update_stream": ["varlen-causal-conv-stream.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
| 25 |
-
"bias_state_update_stream": ["varlen-causal-conv-stream.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
| 26 |
"plain": ["varlen-causal-conv.wgsl.jinja"],
|
|
|
|
| 27 |
"bias": ["varlen-causal-conv.wgsl.jinja"],
|
|
|
|
| 28 |
"state_update": ["varlen-causal-conv.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
|
|
|
| 29 |
"bias_state_update": ["varlen-causal-conv.wgsl.jinja", "varlen-state-update.wgsl.jinja"]
|
| 30 |
}
|
| 31 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"name": "com.microsoft.VarlenCausalConvWithState",
|
| 3 |
+
"id": "_com_microsoft_varlencausalconvwithstate_webgpu_a11f8c1",
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"backend": { "type": "webgpu" },
|
| 7 |
"digest": {
|
| 8 |
"algorithm": "sha256",
|
| 9 |
"files": {
|
| 10 |
+
"bench.json": "0VIH7EDZLjXt1ZgOmAA4oDeWfhadYrY8VJOkvCIbDlg=",
|
| 11 |
+
"manifest.json": "uEm8UogYuIyHJRhVKAebGdlv7yxdEIRJs7rLubPctf0=",
|
| 12 |
+
"test.json": "o32EnBOjkjEdcFA/wkWFt1ywXTCCN20uEndKoBIoYB8=",
|
| 13 |
+
"varlen-causal-conv-stream.wgsl.jinja": "th2IihEJq0gHEpdRm2PNN8MleOvgSZlAstRE0W6wXmo=",
|
| 14 |
+
"varlen-causal-conv.wgsl.jinja": "t9K8tccFYN5I9uDeOAUs+gtNaHrQS6iy2S0IbQtp4ik=",
|
| 15 |
+
"varlen-state-update.wgsl.jinja": "aTGir5h/LQkg5ami41pKaH4EG8ybaltnnM0oJSJ6Neg=",
|
| 16 |
+
"varlen-unit-sequence.wgsl.jinja": "g2tYe2vdYUlDWySCvrljSsqUAuodUmjYnOW/6tr51jw="
|
| 17 |
}
|
| 18 |
},
|
| 19 |
+
"provenance": { "kernel": { "sha": "6fdf6301e2bbcc2f03bf1eaf493b7ad55ef33afc", "dirty": false } },
|
| 20 |
"webgpu": {
|
| 21 |
+
"manifestSpec": "2.1",
|
| 22 |
"variants": {
|
| 23 |
+
"unit_plain": ["varlen-unit-sequence.wgsl.jinja"],
|
| 24 |
+
"unit_bias": ["varlen-unit-sequence.wgsl.jinja"],
|
| 25 |
+
"unit_state_update": ["varlen-unit-sequence.wgsl.jinja"],
|
| 26 |
+
"unit_bias_state_update": ["varlen-unit-sequence.wgsl.jinja"],
|
| 27 |
+
"capture_copy_state_update_stream": ["varlen-causal-conv-stream.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
| 28 |
+
"capture_copy_state_update": ["varlen-causal-conv.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
| 29 |
+
"capture_copy_bias_state_update_stream": ["varlen-causal-conv-stream.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
| 30 |
+
"capture_copy_bias_state_update": ["varlen-causal-conv.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
| 31 |
"plain_stream": ["varlen-causal-conv-stream.wgsl.jinja"],
|
|
|
|
|
|
|
|
|
|
| 32 |
"plain": ["varlen-causal-conv.wgsl.jinja"],
|
| 33 |
+
"bias_stream": ["varlen-causal-conv-stream.wgsl.jinja"],
|
| 34 |
"bias": ["varlen-causal-conv.wgsl.jinja"],
|
| 35 |
+
"state_update_stream": ["varlen-causal-conv-stream.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
| 36 |
"state_update": ["varlen-causal-conv.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
| 37 |
+
"bias_state_update_stream": ["varlen-causal-conv-stream.wgsl.jinja", "varlen-state-update.wgsl.jinja"],
|
| 38 |
"bias_state_update": ["varlen-causal-conv.wgsl.jinja", "varlen-state-update.wgsl.jinja"]
|
| 39 |
}
|
| 40 |
}
|
build/webgpu/test.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
build/webgpu/varlen-causal-conv-stream.wgsl.jinja
CHANGED
|
@@ -6,9 +6,7 @@ fn sequence_of_token(token: u32, batch_size: u32) -> u32 {
|
|
| 6 |
}
|
| 7 |
}
|
| 8 |
return batch_size - 1u;
|
| 9 |
-
}
|
| 10 |
-
{%- endmacro %}
|
| 11 |
-
|
| 12 |
{% macro varlen_conv_helpers(useSilu) %}
|
| 13 |
// virtual[pos] is one sequence's raw sample stream: the kernelSize-1 carried samples
|
| 14 |
// from initial_state, then the sequence's own tokens. Reading the window through this
|
|
@@ -21,15 +19,22 @@ fn virtual_sample(start: u32, state_base: u32, channel: u32, state_length: u32,
|
|
| 21 |
return f32(initial_state[state_base + pos]);
|
| 22 |
}
|
| 23 |
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
| 25 |
{% if useSilu %}
|
| 26 |
return value / (1.0 + exp(-value));
|
| 27 |
{% else %}
|
| 28 |
return value;
|
| 29 |
{% endif %}
|
| 30 |
-
}
|
| 31 |
-
{%- endmacro %}
|
| 32 |
{% set stateLength = kernelSize - 1 %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
{{ env.wgsl.resourceDeclarations }}
|
| 34 |
|
| 35 |
// com.microsoft.VarlenCausalConvWithState, streaming pass.
|
|
@@ -49,9 +54,7 @@ const STATE_LENGTH: u32 = {{ stateLength }}u;
|
|
| 49 |
|
| 50 |
@compute @workgroup_size(WG, 1, 1)
|
| 51 |
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
| 52 |
-
|
| 53 |
-
// per-axis dispatch fold width. Reduces to gid.x when the dispatch does not fold.
|
| 54 |
-
let index = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * WG;
|
| 55 |
let blocks = (params.totalTokens + CHUNK - 1u) / CHUNK;
|
| 56 |
if (index >= blocks * params.channels) {
|
| 57 |
return;
|
|
|
|
| 6 |
}
|
| 7 |
}
|
| 8 |
return batch_size - 1u;
|
| 9 |
+
}{% endmacro %}
|
|
|
|
|
|
|
| 10 |
{% macro varlen_conv_helpers(useSilu) %}
|
| 11 |
// virtual[pos] is one sequence's raw sample stream: the kernelSize-1 carried samples
|
| 12 |
// from initial_state, then the sequence's own tokens. Reading the window through this
|
|
|
|
| 19 |
return f32(initial_state[state_base + pos]);
|
| 20 |
}
|
| 21 |
|
| 22 |
+
{{ varlen_conv_activation(useSilu) }}{% endmacro %}
|
| 23 |
+
{% macro varlen_conv_activation(useSilu, width=1) %}
|
| 24 |
+
{% set valueType = "f32" if width == 1 else "vec" ~ width ~ "<f32>" %}
|
| 25 |
+
fn activate(value: {{ valueType }}) -> {{ valueType }} {
|
| 26 |
{% if useSilu %}
|
| 27 |
return value / (1.0 + exp(-value));
|
| 28 |
{% else %}
|
| 29 |
return value;
|
| 30 |
{% endif %}
|
| 31 |
+
}{% endmacro %}
|
|
|
|
| 32 |
{% set stateLength = kernelSize - 1 %}
|
| 33 |
+
{% macro flat_index_2d(workgroupSize, name="i", bound="params.count", guardInline=false) %}
|
| 34 |
+
{% set wgTerm = workgroupSize ~ "u" if workgroupSize is number else workgroupSize %}
|
| 35 |
+
// 2D-folded flat index: gid.y carries the high bits past the dispatch's
|
| 36 |
+
// per-axis workgroup fold width.
|
| 37 |
+
let {{ name }} = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ wgTerm }};{% endmacro %}
|
| 38 |
{{ env.wgsl.resourceDeclarations }}
|
| 39 |
|
| 40 |
// com.microsoft.VarlenCausalConvWithState, streaming pass.
|
|
|
|
| 54 |
|
| 55 |
@compute @workgroup_size(WG, 1, 1)
|
| 56 |
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
| 57 |
+
{{ flat_index_2d("WG", "index", "") }}
|
|
|
|
|
|
|
| 58 |
let blocks = (params.totalTokens + CHUNK - 1u) / CHUNK;
|
| 59 |
if (index >= blocks * params.channels) {
|
| 60 |
return;
|
build/webgpu/varlen-causal-conv.wgsl.jinja
CHANGED
|
@@ -6,9 +6,7 @@ fn sequence_of_token(token: u32, batch_size: u32) -> u32 {
|
|
| 6 |
}
|
| 7 |
}
|
| 8 |
return batch_size - 1u;
|
| 9 |
-
}
|
| 10 |
-
{%- endmacro %}
|
| 11 |
-
|
| 12 |
{% macro varlen_conv_helpers(useSilu) %}
|
| 13 |
// virtual[pos] is one sequence's raw sample stream: the kernelSize-1 carried samples
|
| 14 |
// from initial_state, then the sequence's own tokens. Reading the window through this
|
|
@@ -21,14 +19,24 @@ fn virtual_sample(start: u32, state_base: u32, channel: u32, state_length: u32,
|
|
| 21 |
return f32(initial_state[state_base + pos]);
|
| 22 |
}
|
| 23 |
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
| 25 |
{% if useSilu %}
|
| 26 |
return value / (1.0 + exp(-value));
|
| 27 |
{% else %}
|
| 28 |
return value;
|
| 29 |
{% endif %}
|
| 30 |
-
}
|
| 31 |
-
{%
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
{{ env.wgsl.resourceDeclarations }}
|
| 33 |
|
| 34 |
// com.microsoft.VarlenCausalConvWithState, portable pass.
|
|
@@ -45,15 +53,10 @@ const WG: u32 = {{ workgroupSize }}u;
|
|
| 45 |
|
| 46 |
@compute @workgroup_size(WG, 1, 1)
|
| 47 |
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
| 48 |
-
|
| 49 |
-
// per-axis dispatch fold width. Reduces to gid.x when the dispatch does not fold.
|
| 50 |
-
let index = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * WG;
|
| 51 |
-
if (index >= params.totalTokens * params.channels) {
|
| 52 |
-
return;
|
| 53 |
-
}
|
| 54 |
let token = index / params.channels;
|
| 55 |
let channel = index % params.channels;
|
| 56 |
-
let state_length = params.kernelSize - 1u;
|
| 57 |
|
| 58 |
// A malformed schedule returns before any buffer access. This is memory-safety
|
| 59 |
// containment, not validation; outputs are unspecified for such a request.
|
|
@@ -75,7 +78,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
| 75 |
acc = f32(bias[channel]);
|
| 76 |
{% endif %}
|
| 77 |
for (var k: u32 = 0u; k < params.kernelSize; k = k + 1u) {
|
| 78 |
-
let value = virtual_sample(start, state_base, channel, state_length, local + k);
|
| 79 |
acc = acc + value * f32(weight[channel * params.kernelSize + k]);
|
| 80 |
}
|
| 81 |
output[index] = {{ outputScalar }}(activate(acc));
|
|
|
|
| 6 |
}
|
| 7 |
}
|
| 8 |
return batch_size - 1u;
|
| 9 |
+
}{% endmacro %}
|
|
|
|
|
|
|
| 10 |
{% macro varlen_conv_helpers(useSilu) %}
|
| 11 |
// virtual[pos] is one sequence's raw sample stream: the kernelSize-1 carried samples
|
| 12 |
// from initial_state, then the sequence's own tokens. Reading the window through this
|
|
|
|
| 19 |
return f32(initial_state[state_base + pos]);
|
| 20 |
}
|
| 21 |
|
| 22 |
+
{{ varlen_conv_activation(useSilu) }}{% endmacro %}
|
| 23 |
+
{% macro varlen_conv_activation(useSilu, width=1) %}
|
| 24 |
+
{% set valueType = "f32" if width == 1 else "vec" ~ width ~ "<f32>" %}
|
| 25 |
+
fn activate(value: {{ valueType }}) -> {{ valueType }} {
|
| 26 |
{% if useSilu %}
|
| 27 |
return value / (1.0 + exp(-value));
|
| 28 |
{% else %}
|
| 29 |
return value;
|
| 30 |
{% endif %}
|
| 31 |
+
}{% endmacro %}
|
| 32 |
+
{% macro flat_index_2d(workgroupSize, name="i", bound="params.count", guardInline=false) %}
|
| 33 |
+
{% set wgTerm = workgroupSize ~ "u" if workgroupSize is number else workgroupSize %}
|
| 34 |
+
// 2D-folded flat index: gid.y carries the high bits past the dispatch's
|
| 35 |
+
// per-axis workgroup fold width.
|
| 36 |
+
let {{ name }} = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ wgTerm }};
|
| 37 |
+
if ({{ name }} >= {{ bound }}) {
|
| 38 |
+
return;
|
| 39 |
+
}{% endmacro %}
|
| 40 |
{{ env.wgsl.resourceDeclarations }}
|
| 41 |
|
| 42 |
// com.microsoft.VarlenCausalConvWithState, portable pass.
|
|
|
|
| 53 |
|
| 54 |
@compute @workgroup_size(WG, 1, 1)
|
| 55 |
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
| 56 |
+
{{ flat_index_2d("WG", "index", "params.totalTokens * params.channels") }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
let token = index / params.channels;
|
| 58 |
let channel = index % params.channels;
|
| 59 |
+
let state_length = {% if causalDilation != 1 %}(params.kernelSize - 1u) * {{ causalDilation }}u{% else %}params.kernelSize - 1u{% endif %};
|
| 60 |
|
| 61 |
// A malformed schedule returns before any buffer access. This is memory-safety
|
| 62 |
// containment, not validation; outputs are unspecified for such a request.
|
|
|
|
| 78 |
acc = f32(bias[channel]);
|
| 79 |
{% endif %}
|
| 80 |
for (var k: u32 = 0u; k < params.kernelSize; k = k + 1u) {
|
| 81 |
+
let value = virtual_sample(start, state_base, channel, state_length, local + k{% if causalDilation != 1 %} * {{ causalDilation }}u{% endif %});
|
| 82 |
acc = acc + value * f32(weight[channel * params.kernelSize + k]);
|
| 83 |
}
|
| 84 |
output[index] = {{ outputScalar }}(activate(acc));
|
build/webgpu/varlen-unit-sequence.wgsl.jinja
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{% macro varlen_conv_activation(useSilu, width=1) %}
|
| 2 |
+
{% set valueType = "f32" if width == 1 else "vec" ~ width ~ "<f32>" %}
|
| 3 |
+
fn activate(value: {{ valueType }}) -> {{ valueType }} {
|
| 4 |
+
{% if useSilu %}
|
| 5 |
+
return value / ({% if width == 1 %}1.0{% else %}{{ valueType }}(1.0){% endif %} + exp(-value));
|
| 6 |
+
{% else %}
|
| 7 |
+
return value;
|
| 8 |
+
{% endif %}
|
| 9 |
+
}{% endmacro %}
|
| 10 |
+
{% set stateLength = kernelSize - 1 %}
|
| 11 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 12 |
+
{{ varlen_conv_activation(useSilu, unitVectorWidth) }}
|
| 13 |
+
const WG: u32 = {{ unitWg }}u;
|
| 14 |
+
@compute @workgroup_size(WG)
|
| 15 |
+
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
| 16 |
+
let index = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * WG;
|
| 17 |
+
let channelGroups = params.channels / {{ unitVectorWidth }}u;
|
| 18 |
+
if (index >= params.totalTokens * channelGroups) { return; }
|
| 19 |
+
// Strictly increasing integer prefix sums over T == batch imply one token per sequence.
|
| 20 |
+
let sequence = index / channelGroups;
|
| 21 |
+
let channel = index % channelGroups;
|
| 22 |
+
// Loads follow the contiguous channel-major storage layout. Their components
|
| 23 |
+
// are rearranged into channel vectors at compile time for the original
|
| 24 |
+
// ordered tap sum.
|
| 25 |
+
let weightBase = channel * {{ kernelSize }}u;
|
| 26 |
+
let stateBase = (sequence * channelGroups + channel) * {{ stateLength }}u;
|
| 27 |
+
{% for i in range(kernelSize) %}
|
| 28 |
+
let packedW{{ i }} = weight[weightBase + {{ i }}u];
|
| 29 |
+
{% endfor %}
|
| 30 |
+
{% for i in range(stateLength) %}
|
| 31 |
+
let packedS{{ i }} = initial_state[stateBase + {{ i }}u];
|
| 32 |
+
{% endfor %}
|
| 33 |
+
{% for i in range(kernelSize) %}
|
| 34 |
+
let w{{ i }} = {{ unitValueType }}({% for c in range(unitVectorWidth) %}packedW{{ ((c * kernelSize + i) / unitVectorWidth)|int }}{% if unitVectorWidth > 1 %}[{{ (c * kernelSize + i) % unitVectorWidth }}]{% endif %}{% if not loop.last %}, {% endif %}{% endfor %});
|
| 35 |
+
{% endfor %}
|
| 36 |
+
{% for i in range(stateLength) %}
|
| 37 |
+
let s{{ i }} = {{ unitValueType }}({% for c in range(unitVectorWidth) %}packedS{{ ((c * stateLength + i) / unitVectorWidth)|int }}{% if unitVectorWidth > 1 %}[{{ (c * stateLength + i) % unitVectorWidth }}]{% endif %}{% if not loop.last %}, {% endif %}{% endfor %});
|
| 38 |
+
{% endfor %}
|
| 39 |
+
{% if hasBias %}
|
| 40 |
+
let biasValue = {{ unitValueType }}(bias[channel]);
|
| 41 |
+
{% else %}
|
| 42 |
+
let biasValue = {{ unitValueType }}(0.0);
|
| 43 |
+
{% endif %}
|
| 44 |
+
let x = {{ unitValueType }}(input[index]);
|
| 45 |
+
output[index] = {{ unitStorageType }}(activate(biasValue{% for i in range(stateLength) %} + s{{ i }} * w{{ i }}{% endfor %} + x * w{{ kernelSize - 1 }}));
|
| 46 |
+
// Repack the shifted state without scalar scatter stores.
|
| 47 |
+
{% for i in range(stateLength) %}
|
| 48 |
+
final_state[stateBase + {{ i }}u] = {{ unitStorageType }}({% for c in range(unitVectorWidth) %}{% set scalarOffset = i * unitVectorWidth + c %}{% set tap = scalarOffset % stateLength %}{% if tap == stateLength - 1 %}x{% else %}s{{ tap + 1 }}{% endif %}{% if unitVectorWidth > 1 %}[{{ (scalarOffset / stateLength)|int }}]{% endif %}{% if not loop.last %}, {% endif %}{% endfor %});
|
| 49 |
+
{% endfor %}
|
| 50 |
+
{% if hasCapture %}
|
| 51 |
+
var captured = {{ unitStorageType }}(0.0);
|
| 52 |
+
if (capture_count[sequence] > 0) { captured = {{ unitStorageType }}(x); }
|
| 53 |
+
let updateBase = (sequence * {{ stateUpdateCapacity }}u) * channelGroups + channel;
|
| 54 |
+
state_update[updateBase] = captured;
|
| 55 |
+
{% for slot in range(1, stateUpdateCapacity) %}
|
| 56 |
+
state_update[updateBase + {{ slot }}u * channelGroups] = {{ unitStorageType }}(0.0);
|
| 57 |
+
{% endfor %}
|
| 58 |
+
{% endif %}
|
| 59 |
+
}
|