sync 2e7068faf55e
Browse files- README.md +91 -0
- build/webgpu/bench.json +473 -0
- build/webgpu/expert-group-slots.wgsl.jinja +70 -0
- build/webgpu/manifest.json +0 -0
- build/webgpu/metadata.json +26 -0
- build/webgpu/moe-ffn-gemv.wgsl.jinja +160 -0
- build/webgpu/moe-ffn-grouped.wgsl.jinja +254 -0
- build/webgpu/moe-ffn-stage.wgsl.jinja +121 -0
- build/webgpu/moe-mix-stage.wgsl.jinja +33 -0
- build/webgpu/moe-output-gemv.wgsl.jinja +70 -0
- build/webgpu/moe-output-grouped.wgsl.jinja +177 -0
- build/webgpu/moe-output-stage.wgsl.jinja +44 -0
- build/webgpu/moe-route-stage.wgsl.jinja +76 -0
- build/webgpu/test.json +2001 -0
README.md
CHANGED
|
@@ -1,3 +1,94 @@
|
|
| 1 |
---
|
|
|
|
| 2 |
license: apache-2.0
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
library_name: kernels
|
| 3 |
license: apache-2.0
|
| 4 |
+
tags:
|
| 5 |
+
- kernel
|
| 6 |
+
- webgpu
|
| 7 |
+
- wgsl
|
| 8 |
---
|
| 9 |
+
# com.microsoft.MoE
|
| 10 |
+
|
| 11 |
+
`com.microsoft` · ONNX Runtime contrib operator · contrib since_version 1
|
| 12 |
+
|
| 13 |
+
## Description
|
| 14 |
+
|
| 15 |
+
Mixture of Experts: applies softmax to `router_probs`, routes each token to the top-`k` experts, applies FC1 and `activation_type`, projects through FC2, then sums the selected outputs using their routing probabilities. SwiGLU takes its operands from a separate FC3 (`swiglu_fusion` 0) or a fused FC1 in interleaved (1) or concatenated (2) order; SiLU may also use FC3 as its multiplicative linear projection. This inference package supports float32 and dense routing (`use_sparse_mixer = 0`); float16, bfloat16, and sparse mixing are not implemented. Quantized weights use `com.microsoft.QMoE`.
|
| 16 |
+
|
| 17 |
+
See the [ONNX Runtime `MoE` contrib-operator spec](https://github.com/microsoft/onnxruntime/blob/main/docs/ContribOperators.md#com.microsoft.MoE) for the reference semantics.
|
| 18 |
+
|
| 19 |
+
## Inputs
|
| 20 |
+
|
| 21 |
+
| Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
|
| 22 |
+
| --- | --- | --- | --- | --- | --- | --- |
|
| 23 |
+
| `input` | `inputT` | `T` | — | — | Token activations, either 2D `(num_tokens, hidden_size)` or 3D `(batch_size, sequence_length, hidden_size)`. | required |
|
| 24 |
+
| `router_probs` | `routerT` | `T` | `2` | — | 2D router logits of shape `(num_tokens, num_experts)`, where `num_tokens` is the product of every leading dimension of `input`. Despite the historical port name, the operator applies a full softmax before top-k selection. | required |
|
| 25 |
+
| `fc1_experts_weights` | `fc1T` | `T` | `3` | — | 3D first-layer expert weights of shape `(num_experts, fusion_size * inter_size, hidden_size)`, where `fusion_size` is 2 for fused SwiGLU (`swiglu_fusion` 1 or 2) and 1 otherwise. | required |
|
| 26 |
+
| `fc1_experts_bias` | `fc1BiasT` | `T` | `2` | — | Optional 2D FC1 bias of shape `(num_experts, fusion_size * inter_size)`. | optional |
|
| 27 |
+
| `fc2_experts_weights` | `fc2T` | `T` | `3` | — | 3D second-layer expert weights of shape `(num_experts, hidden_size, inter_size)`. | required |
|
| 28 |
+
| `fc2_experts_bias` | `fc2BiasT` | `T` | `2` | — | Optional 2D FC2 bias of shape `(num_experts, hidden_size)`, added per expert before that expert's routing weight is applied. | optional |
|
| 29 |
+
| `fc3_experts_weights` | `fc3T` | `T` | `3` | — | Optional 3D third-layer expert weights of shape `(num_experts, inter_size, hidden_size)`. It supplies the separate linear operand for SwiGLU when `swiglu_fusion` is 0, or the multiplicative linear projection for SiLU gating. Other activations do not consume FC3. | optional |
|
| 30 |
+
| `fc3_experts_bias` | `fc3BiasT` | `T` | `2` | — | Optional 2D FC3 bias of shape `(num_experts, inter_size)`. | optional |
|
| 31 |
+
|
| 32 |
+
## Outputs
|
| 33 |
+
|
| 34 |
+
| Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
|
| 35 |
+
| --- | --- | --- | --- | --- | --- | --- |
|
| 36 |
+
| `output` | `outputT` | `T` | same as `input` | same as `input` | Routed expert output with the same shape as `input`. | required |
|
| 37 |
+
|
| 38 |
+
## Attributes
|
| 39 |
+
|
| 40 |
+
Attributes and default values (overridable per request):
|
| 41 |
+
|
| 42 |
+
| Attribute | Default | Description |
|
| 43 |
+
| --- | --- | --- |
|
| 44 |
+
| `activation_alpha` | `1` | Alpha parameter used by the activation; the schema default is 1. |
|
| 45 |
+
| `activation_beta` | `0` | Beta parameter used by the activation; the schema default is 0. |
|
| 46 |
+
| `activation_type` | `"relu"` | Activation applied to the FC1 projection: `relu`, `gelu`, `silu`, `swiglu`, or `identity`. The schema default is `relu`. |
|
| 47 |
+
| `k` | `1` | Number of experts selected per token; the schema default is 1. |
|
| 48 |
+
| `normalize_routing_weights` | `0` | Whether to normalize the selected routing weights; the schema default is 0. |
|
| 49 |
+
| `swiglu_fusion` | `0` | 0 keeps the SwiGLU operands in separate FC1/FC3 GEMMs, 1 interleaves them in one FC1 row, and 2 concatenates them. The schema default is 0. |
|
| 50 |
+
| `use_sparse_mixer` | `0` | Whether to use sparse-mixer routing. The standard default and only supported value is 0. |
|
| 51 |
+
| `swiglu_limit` | — | Optional SwiGLU clamp limit; omission means no clamp. |
|
| 52 |
+
|
| 53 |
+
## Type constraints
|
| 54 |
+
|
| 55 |
+
| Variable | Allowed dtypes |
|
| 56 |
+
| --- | --- |
|
| 57 |
+
| `T` | `float32` |
|
| 58 |
+
|
| 59 |
+
## Files
|
| 60 |
+
|
| 61 |
+
- [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
|
| 62 |
+
- [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
|
| 63 |
+
- [`test.json`](build/webgpu/test.json) — correctness cases
|
| 64 |
+
- [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
|
| 65 |
+
- [`expert-group-slots.wgsl.jinja`](build/webgpu/expert-group-slots.wgsl.jinja)
|
| 66 |
+
- [`moe-ffn-gemv.wgsl.jinja`](build/webgpu/moe-ffn-gemv.wgsl.jinja)
|
| 67 |
+
- [`moe-ffn-grouped.wgsl.jinja`](build/webgpu/moe-ffn-grouped.wgsl.jinja)
|
| 68 |
+
- [`moe-ffn-stage.wgsl.jinja`](build/webgpu/moe-ffn-stage.wgsl.jinja)
|
| 69 |
+
- [`moe-mix-stage.wgsl.jinja`](build/webgpu/moe-mix-stage.wgsl.jinja)
|
| 70 |
+
- [`moe-output-gemv.wgsl.jinja`](build/webgpu/moe-output-gemv.wgsl.jinja)
|
| 71 |
+
- [`moe-output-grouped.wgsl.jinja`](build/webgpu/moe-output-grouped.wgsl.jinja)
|
| 72 |
+
- [`moe-output-stage.wgsl.jinja`](build/webgpu/moe-output-stage.wgsl.jinja)
|
| 73 |
+
- [`moe-route-stage.wgsl.jinja`](build/webgpu/moe-route-stage.wgsl.jinja)
|
| 74 |
+
|
| 75 |
+
## Use with `@huggingface/kernels`
|
| 76 |
+
|
| 77 |
+
The loader derives every required output's shape and logical dtype from the manifest contract and this call.
|
| 78 |
+
It then allocates the result tensors automatically.
|
| 79 |
+
|
| 80 |
+
The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
|
| 81 |
+
|
| 82 |
+
Replace each `*Data` placeholder with a typed array containing the corresponding input data.
|
| 83 |
+
|
| 84 |
+
```js
|
| 85 |
+
import { getKernel } from "@huggingface/kernels";
|
| 86 |
+
|
| 87 |
+
const kernel = await getKernel("webgpu-kernels/com.microsoft.MoE", { version: 1 });
|
| 88 |
+
const { outputT } = await kernel({
|
| 89 |
+
inputT: { data: inputTData, shape: [1, 1] },
|
| 90 |
+
routerT: { data: routerTData, shape: [1, 2] },
|
| 91 |
+
fc1T: { data: fc1TData, shape: [2, 1, 1] },
|
| 92 |
+
fc2T: { data: fc2TData, shape: [2, 1, 1] },
|
| 93 |
+
});
|
| 94 |
+
```
|
build/webgpu/bench.json
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"op": "com.microsoft.MoE",
|
| 3 |
+
"tunableSpace": {
|
| 4 |
+
"workgroupSize": [64, 128],
|
| 5 |
+
"decodeLanes": [32],
|
| 6 |
+
"groupThreads": [8, 16],
|
| 7 |
+
"groupRegM": [1, 2, 4],
|
| 8 |
+
"groupRegN": [1, 2, 4],
|
| 9 |
+
"groupTileK": [8, 16, 32]
|
| 10 |
+
},
|
| 11 |
+
"cases": [
|
| 12 |
+
{
|
| 13 |
+
"name": "moe-f32-t64-h256-e8-k2-i256-swiglu",
|
| 14 |
+
"attrs": {
|
| 15 |
+
"k": 2,
|
| 16 |
+
"activation_type": "swiglu",
|
| 17 |
+
"swiglu_fusion": 2,
|
| 18 |
+
"normalize_routing_weights": 1,
|
| 19 |
+
"activation_alpha": 1.702
|
| 20 |
+
},
|
| 21 |
+
"inputs": {
|
| 22 |
+
"inputT": {
|
| 23 |
+
"dtype": "float32",
|
| 24 |
+
"shape": [64, 256],
|
| 25 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 26 |
+
},
|
| 27 |
+
"routerT": {
|
| 28 |
+
"dtype": "float32",
|
| 29 |
+
"shape": [64, 8],
|
| 30 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 31 |
+
},
|
| 32 |
+
"fc1T": {
|
| 33 |
+
"dtype": "float32",
|
| 34 |
+
"shape": [8, 512, 256],
|
| 35 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.05 }
|
| 36 |
+
},
|
| 37 |
+
"fc2T": {
|
| 38 |
+
"dtype": "float32",
|
| 39 |
+
"shape": [8, 256, 256],
|
| 40 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.05 }
|
| 41 |
+
}
|
| 42 |
+
},
|
| 43 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [64, 256] } }
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"name": "moe-f32-swiglu-t1-h1024-e8-k2-i512-decode",
|
| 47 |
+
"preset": "smoke",
|
| 48 |
+
"vars": { "tokens": 1, "hidden": 1024, "experts": 8, "inter": 512, "topK": 2 },
|
| 49 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 50 |
+
"inputs": {
|
| 51 |
+
"inputT": {
|
| 52 |
+
"dtype": "float32",
|
| 53 |
+
"shape": [1, 1024],
|
| 54 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.31, "scale": 0.5 }
|
| 55 |
+
},
|
| 56 |
+
"routerT": {
|
| 57 |
+
"dtype": "float32",
|
| 58 |
+
"shape": [1, 8],
|
| 59 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.33, "cosStep": 0.19, "scale": 0.7 }
|
| 60 |
+
},
|
| 61 |
+
"fc1T": {
|
| 62 |
+
"dtype": "float32",
|
| 63 |
+
"shape": [8, 1024, 1024],
|
| 64 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.23, "scale": 0.05 }
|
| 65 |
+
},
|
| 66 |
+
"fc2T": {
|
| 67 |
+
"dtype": "float32",
|
| 68 |
+
"shape": [8, 1024, 512],
|
| 69 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.15, "cosStep": 0.41, "scale": 0.05 }
|
| 70 |
+
}
|
| 71 |
+
},
|
| 72 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [1, 1024] } },
|
| 73 |
+
"bench": { "metrics": [{ "type": "bandwidth", "value": "args.topK * 3 * args.hidden * args.inter * 4" }] },
|
| 74 |
+
"provenance": {
|
| 75 |
+
"notes": "Scored as bandwidth, not gflops: a decode step reads whole expert weight matrices to produce one output row, so memory is its roofline and the compute peak is the wrong denominator. The prefill cases stay on gflops."
|
| 76 |
+
}
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
"name": "moe-f32-relu-t1-h1024-e8-k1-i1024-decode-relu",
|
| 80 |
+
"preset": "stress",
|
| 81 |
+
"vars": { "tokens": 1, "hidden": 1024, "experts": 8, "inter": 1024, "topK": 1 },
|
| 82 |
+
"attrs": { "k": 1, "activation_type": "relu", "normalize_routing_weights": 1 },
|
| 83 |
+
"inputs": {
|
| 84 |
+
"inputT": {
|
| 85 |
+
"dtype": "float32",
|
| 86 |
+
"shape": [1, 1024],
|
| 87 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 88 |
+
},
|
| 89 |
+
"routerT": {
|
| 90 |
+
"dtype": "float32",
|
| 91 |
+
"shape": [1, 8],
|
| 92 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 93 |
+
},
|
| 94 |
+
"fc1T": {
|
| 95 |
+
"dtype": "float32",
|
| 96 |
+
"shape": [8, 1024, 1024],
|
| 97 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.21, "cosStep": 0.23, "scale": 0.05 }
|
| 98 |
+
},
|
| 99 |
+
"fc2T": {
|
| 100 |
+
"dtype": "float32",
|
| 101 |
+
"shape": [8, 1024, 1024],
|
| 102 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.41, "scale": 0.05 }
|
| 103 |
+
}
|
| 104 |
+
},
|
| 105 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [1, 1024] } },
|
| 106 |
+
"bench": { "metrics": [{ "type": "bandwidth", "value": "args.topK * 2 * args.hidden * args.inter * 4" }] },
|
| 107 |
+
"provenance": {
|
| 108 |
+
"notes": "Scored as bandwidth, not gflops: a decode step reads whole expert weight matrices to produce one output row, so memory is its roofline and the compute peak is the wrong denominator. The prefill cases stay on gflops."
|
| 109 |
+
}
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"name": "moe-f32-swiglu-t8-h1024-e8-k2-i512-decode-batch8",
|
| 113 |
+
"preset": "stress",
|
| 114 |
+
"vars": { "tokens": 8, "hidden": 1024, "experts": 8, "inter": 512, "topK": 2 },
|
| 115 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 116 |
+
"inputs": {
|
| 117 |
+
"inputT": {
|
| 118 |
+
"dtype": "float32",
|
| 119 |
+
"shape": [8, 1024],
|
| 120 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.21, "cosStep": 0.31, "scale": 0.5 }
|
| 121 |
+
},
|
| 122 |
+
"routerT": {
|
| 123 |
+
"dtype": "float32",
|
| 124 |
+
"shape": [8, 8],
|
| 125 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.41, "cosStep": 0.19, "scale": 0.7 }
|
| 126 |
+
},
|
| 127 |
+
"fc1T": {
|
| 128 |
+
"dtype": "float32",
|
| 129 |
+
"shape": [8, 1024, 1024],
|
| 130 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.25, "cosStep": 0.23, "scale": 0.05 }
|
| 131 |
+
},
|
| 132 |
+
"fc2T": {
|
| 133 |
+
"dtype": "float32",
|
| 134 |
+
"shape": [8, 1024, 512],
|
| 135 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.23, "cosStep": 0.41, "scale": 0.05 }
|
| 136 |
+
}
|
| 137 |
+
},
|
| 138 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [8, 1024] } },
|
| 139 |
+
"bench": { "metrics": [{ "type": "bandwidth", "value": "args.topK * 3 * args.hidden * args.inter * 4" }] },
|
| 140 |
+
"provenance": {
|
| 141 |
+
"notes": "Scored as bandwidth, not gflops: a decode step reads whole expert weight matrices to produce one output row, so memory is its roofline and the compute peak is the wrong denominator. The prefill cases stay on gflops."
|
| 142 |
+
}
|
| 143 |
+
},
|
| 144 |
+
{
|
| 145 |
+
"name": "moe-f32-swiglu-t256-h1024-e8-k2-i512-prefill",
|
| 146 |
+
"preset": "stress",
|
| 147 |
+
"vars": { "tokens": 256, "hidden": 1024, "experts": 8, "inter": 512, "topK": 2 },
|
| 148 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 149 |
+
"inputs": {
|
| 150 |
+
"inputT": {
|
| 151 |
+
"dtype": "float32",
|
| 152 |
+
"shape": [256, 1024],
|
| 153 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.31, "scale": 0.5 }
|
| 154 |
+
},
|
| 155 |
+
"routerT": {
|
| 156 |
+
"dtype": "float32",
|
| 157 |
+
"shape": [256, 8],
|
| 158 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.49, "cosStep": 0.19, "scale": 0.7 }
|
| 159 |
+
},
|
| 160 |
+
"fc1T": {
|
| 161 |
+
"dtype": "float32",
|
| 162 |
+
"shape": [8, 1024, 1024],
|
| 163 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.33, "cosStep": 0.23, "scale": 0.05 }
|
| 164 |
+
},
|
| 165 |
+
"fc2T": {
|
| 166 |
+
"dtype": "float32",
|
| 167 |
+
"shape": [8, 1024, 512],
|
| 168 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.41, "scale": 0.05 }
|
| 169 |
+
}
|
| 170 |
+
},
|
| 171 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [256, 1024] } },
|
| 172 |
+
"bench": {
|
| 173 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 174 |
+
}
|
| 175 |
+
},
|
| 176 |
+
{
|
| 177 |
+
"name": "moe-f32-swiglu-t32-h1024-e8-k2-i512-prefill-small",
|
| 178 |
+
"preset": "stress",
|
| 179 |
+
"vars": { "tokens": 32, "hidden": 1024, "experts": 8, "inter": 512, "topK": 2 },
|
| 180 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 181 |
+
"inputs": {
|
| 182 |
+
"inputT": {
|
| 183 |
+
"dtype": "float32",
|
| 184 |
+
"shape": [32, 1024],
|
| 185 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.23, "cosStep": 0.31, "scale": 0.5 }
|
| 186 |
+
},
|
| 187 |
+
"routerT": {
|
| 188 |
+
"dtype": "float32",
|
| 189 |
+
"shape": [32, 8],
|
| 190 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.49, "cosStep": 0.19, "scale": 0.7 }
|
| 191 |
+
},
|
| 192 |
+
"fc1T": {
|
| 193 |
+
"dtype": "float32",
|
| 194 |
+
"shape": [8, 1024, 1024],
|
| 195 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.33, "cosStep": 0.23, "scale": 0.05 }
|
| 196 |
+
},
|
| 197 |
+
"fc2T": {
|
| 198 |
+
"dtype": "float32",
|
| 199 |
+
"shape": [8, 1024, 512],
|
| 200 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.41, "scale": 0.05 }
|
| 201 |
+
}
|
| 202 |
+
},
|
| 203 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [32, 1024] } },
|
| 204 |
+
"bench": {
|
| 205 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 206 |
+
}
|
| 207 |
+
},
|
| 208 |
+
{
|
| 209 |
+
"name": "moe-f32-swiglu-t64-h1024-e8-k2-i512-prefill-small",
|
| 210 |
+
"preset": "stress",
|
| 211 |
+
"vars": { "tokens": 64, "hidden": 1024, "experts": 8, "inter": 512, "topK": 2 },
|
| 212 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 213 |
+
"inputs": {
|
| 214 |
+
"inputT": {
|
| 215 |
+
"dtype": "float32",
|
| 216 |
+
"shape": [64, 1024],
|
| 217 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.27, "cosStep": 0.31, "scale": 0.5 }
|
| 218 |
+
},
|
| 219 |
+
"routerT": {
|
| 220 |
+
"dtype": "float32",
|
| 221 |
+
"shape": [64, 8],
|
| 222 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.49, "cosStep": 0.19, "scale": 0.7 }
|
| 223 |
+
},
|
| 224 |
+
"fc1T": {
|
| 225 |
+
"dtype": "float32",
|
| 226 |
+
"shape": [8, 1024, 1024],
|
| 227 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.33, "cosStep": 0.23, "scale": 0.05 }
|
| 228 |
+
},
|
| 229 |
+
"fc2T": {
|
| 230 |
+
"dtype": "float32",
|
| 231 |
+
"shape": [8, 1024, 512],
|
| 232 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.41, "scale": 0.05 }
|
| 233 |
+
}
|
| 234 |
+
},
|
| 235 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [64, 1024] } },
|
| 236 |
+
"bench": {
|
| 237 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 238 |
+
}
|
| 239 |
+
},
|
| 240 |
+
{
|
| 241 |
+
"name": "moe-f32-swiglu-t96-h1024-e8-k2-i512-prefill-small",
|
| 242 |
+
"preset": "stress",
|
| 243 |
+
"vars": { "tokens": 96, "hidden": 1024, "experts": 8, "inter": 512, "topK": 2 },
|
| 244 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 245 |
+
"inputs": {
|
| 246 |
+
"inputT": {
|
| 247 |
+
"dtype": "float32",
|
| 248 |
+
"shape": [96, 1024],
|
| 249 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.21, "cosStep": 0.31, "scale": 0.5 }
|
| 250 |
+
},
|
| 251 |
+
"routerT": {
|
| 252 |
+
"dtype": "float32",
|
| 253 |
+
"shape": [96, 8],
|
| 254 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.49, "cosStep": 0.19, "scale": 0.7 }
|
| 255 |
+
},
|
| 256 |
+
"fc1T": {
|
| 257 |
+
"dtype": "float32",
|
| 258 |
+
"shape": [8, 1024, 1024],
|
| 259 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.33, "cosStep": 0.23, "scale": 0.05 }
|
| 260 |
+
},
|
| 261 |
+
"fc2T": {
|
| 262 |
+
"dtype": "float32",
|
| 263 |
+
"shape": [8, 1024, 512],
|
| 264 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.41, "scale": 0.05 }
|
| 265 |
+
}
|
| 266 |
+
},
|
| 267 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 1024] } },
|
| 268 |
+
"bench": {
|
| 269 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 270 |
+
}
|
| 271 |
+
},
|
| 272 |
+
{
|
| 273 |
+
"name": "moe-f32-swiglu-t128-h1024-e8-k2-i512-prefill-small",
|
| 274 |
+
"preset": "stress",
|
| 275 |
+
"vars": { "tokens": 128, "hidden": 1024, "experts": 8, "inter": 512, "topK": 2 },
|
| 276 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 277 |
+
"inputs": {
|
| 278 |
+
"inputT": {
|
| 279 |
+
"dtype": "float32",
|
| 280 |
+
"shape": [128, 1024],
|
| 281 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.31, "scale": 0.5 }
|
| 282 |
+
},
|
| 283 |
+
"routerT": {
|
| 284 |
+
"dtype": "float32",
|
| 285 |
+
"shape": [128, 8],
|
| 286 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.49, "cosStep": 0.19, "scale": 0.7 }
|
| 287 |
+
},
|
| 288 |
+
"fc1T": {
|
| 289 |
+
"dtype": "float32",
|
| 290 |
+
"shape": [8, 1024, 1024],
|
| 291 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.33, "cosStep": 0.23, "scale": 0.05 }
|
| 292 |
+
},
|
| 293 |
+
"fc2T": {
|
| 294 |
+
"dtype": "float32",
|
| 295 |
+
"shape": [8, 1024, 512],
|
| 296 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.41, "scale": 0.05 }
|
| 297 |
+
}
|
| 298 |
+
},
|
| 299 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [128, 1024] } },
|
| 300 |
+
"bench": {
|
| 301 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 302 |
+
}
|
| 303 |
+
},
|
| 304 |
+
{
|
| 305 |
+
"name": "moe-f32-swiglu-t48-h1024-e8-k2-i1024-prefill-band",
|
| 306 |
+
"preset": "stress",
|
| 307 |
+
"vars": { "tokens": 48, "hidden": 1024, "experts": 8, "inter": 1024, "topK": 2 },
|
| 308 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 309 |
+
"inputs": {
|
| 310 |
+
"inputT": {
|
| 311 |
+
"dtype": "float32",
|
| 312 |
+
"shape": [48, 1024],
|
| 313 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.31, "scale": 0.5 }
|
| 314 |
+
},
|
| 315 |
+
"routerT": {
|
| 316 |
+
"dtype": "float32",
|
| 317 |
+
"shape": [48, 8],
|
| 318 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.47, "cosStep": 0.19, "scale": 0.7 }
|
| 319 |
+
},
|
| 320 |
+
"fc1T": {
|
| 321 |
+
"dtype": "float32",
|
| 322 |
+
"shape": [8, 2048, 1024],
|
| 323 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.33, "cosStep": 0.23, "scale": 0.05 }
|
| 324 |
+
},
|
| 325 |
+
"fc2T": {
|
| 326 |
+
"dtype": "float32",
|
| 327 |
+
"shape": [8, 1024, 1024],
|
| 328 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.41, "scale": 0.05 }
|
| 329 |
+
}
|
| 330 |
+
},
|
| 331 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [48, 1024] } },
|
| 332 |
+
"bench": {
|
| 333 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 334 |
+
}
|
| 335 |
+
},
|
| 336 |
+
{
|
| 337 |
+
"name": "moe-f32-swiglu-t96-h1024-e16-k2-i512-prefill-band",
|
| 338 |
+
"preset": "stress",
|
| 339 |
+
"vars": { "tokens": 96, "hidden": 1024, "experts": 16, "inter": 512, "topK": 2 },
|
| 340 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 341 |
+
"inputs": {
|
| 342 |
+
"inputT": {
|
| 343 |
+
"dtype": "float32",
|
| 344 |
+
"shape": [96, 1024],
|
| 345 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.43, "cosStep": 0.31, "scale": 0.5 }
|
| 346 |
+
},
|
| 347 |
+
"routerT": {
|
| 348 |
+
"dtype": "float32",
|
| 349 |
+
"shape": [96, 16],
|
| 350 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.53, "cosStep": 0.19, "scale": 0.7 }
|
| 351 |
+
},
|
| 352 |
+
"fc1T": {
|
| 353 |
+
"dtype": "float32",
|
| 354 |
+
"shape": [16, 1024, 1024],
|
| 355 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.33, "cosStep": 0.23, "scale": 0.05 }
|
| 356 |
+
},
|
| 357 |
+
"fc2T": {
|
| 358 |
+
"dtype": "float32",
|
| 359 |
+
"shape": [16, 1024, 512],
|
| 360 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.41, "scale": 0.05 }
|
| 361 |
+
}
|
| 362 |
+
},
|
| 363 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 1024] } },
|
| 364 |
+
"bench": {
|
| 365 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 366 |
+
}
|
| 367 |
+
},
|
| 368 |
+
{
|
| 369 |
+
"name": "moe-f32-qwen3-moe-decode-t1-h2048-e32-k8-i768",
|
| 370 |
+
"preset": "model",
|
| 371 |
+
"provenance": {
|
| 372 |
+
"notes": "Qwen3-MoE class defaults (hidden_size 2048, moe_intermediate_size 768, num_experts_per_tok 8); expert count capped at 32 of the config's 128 to keep each weight tensor under 512 MB. Scored as bandwidth, not gflops: a decode step reads whole expert weight matrices to produce one output row, so memory is its roofline and the compute peak is the wrong denominator. The prefill cases stay on gflops."
|
| 373 |
+
},
|
| 374 |
+
"vars": { "tokens": 1, "hidden": 2048, "experts": 32, "inter": 768, "topK": 8 },
|
| 375 |
+
"attrs": { "k": 8, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 376 |
+
"inputs": {
|
| 377 |
+
"inputT": { "shape": [1, 2048], "dtype": "float32", "dist": "normal", "seed": 3011, "scale": 0.5 },
|
| 378 |
+
"routerT": { "shape": [1, 32], "dtype": "float32", "dist": "normal", "seed": 3012, "scale": 0.7 },
|
| 379 |
+
"fc1T": { "shape": [32, 1536, 2048], "dtype": "float32", "dist": "normal", "seed": 3013, "scale": 0.05 },
|
| 380 |
+
"fc2T": { "shape": [32, 2048, 768], "dtype": "float32", "dist": "normal", "seed": 3014, "scale": 0.05 }
|
| 381 |
+
},
|
| 382 |
+
"outputs": { "outputT": { "shape": [1, 2048], "dtype": "float32" } },
|
| 383 |
+
"bench": { "metrics": [{ "type": "bandwidth", "value": "args.topK * 3 * args.hidden * args.inter * 4" }] }
|
| 384 |
+
},
|
| 385 |
+
{
|
| 386 |
+
"name": "moe-f32-qwen3-moe-prefill-t256-h2048-e32-k8-i768",
|
| 387 |
+
"preset": "model",
|
| 388 |
+
"provenance": {
|
| 389 |
+
"notes": "Qwen3-MoE class defaults at a 256-token prefill chunk; 2048 routed slots put every expert over the grouped schedule's slot floor."
|
| 390 |
+
},
|
| 391 |
+
"vars": { "tokens": 256, "hidden": 2048, "experts": 32, "inter": 768, "topK": 8 },
|
| 392 |
+
"attrs": { "k": 8, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 393 |
+
"inputs": {
|
| 394 |
+
"inputT": { "shape": [256, 2048], "dtype": "float32", "dist": "normal", "seed": 3021, "scale": 0.5 },
|
| 395 |
+
"routerT": { "shape": [256, 32], "dtype": "float32", "dist": "normal", "seed": 3022, "scale": 0.7 },
|
| 396 |
+
"fc1T": { "shape": [32, 1536, 2048], "dtype": "float32", "dist": "normal", "seed": 3023, "scale": 0.05 },
|
| 397 |
+
"fc2T": { "shape": [32, 2048, 768], "dtype": "float32", "dist": "normal", "seed": 3024, "scale": 0.05 }
|
| 398 |
+
},
|
| 399 |
+
"outputs": { "outputT": { "shape": [256, 2048], "dtype": "float32" } },
|
| 400 |
+
"bench": {
|
| 401 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 402 |
+
}
|
| 403 |
+
},
|
| 404 |
+
{
|
| 405 |
+
"name": "moe-f32-olmoe-decode-t1-h2048-e16-k8-i2048",
|
| 406 |
+
"preset": "model",
|
| 407 |
+
"provenance": {
|
| 408 |
+
"notes": "OLMoE class defaults (hidden_size 2048, intermediate_size 2048, num_experts_per_tok 8); expert count capped at 16 of the config's 64. Scored as bandwidth, not gflops: a decode step reads whole expert weight matrices to produce one output row, so memory is its roofline and the compute peak is the wrong denominator. The prefill cases stay on gflops."
|
| 409 |
+
},
|
| 410 |
+
"vars": { "tokens": 1, "hidden": 2048, "experts": 16, "inter": 2048, "topK": 8 },
|
| 411 |
+
"attrs": { "k": 8, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 412 |
+
"inputs": {
|
| 413 |
+
"inputT": { "shape": [1, 2048], "dtype": "float32", "dist": "normal", "seed": 3031, "scale": 0.5 },
|
| 414 |
+
"routerT": { "shape": [1, 16], "dtype": "float32", "dist": "normal", "seed": 3032, "scale": 0.7 },
|
| 415 |
+
"fc1T": { "shape": [16, 4096, 2048], "dtype": "float32", "dist": "normal", "seed": 3033, "scale": 0.05 },
|
| 416 |
+
"fc2T": { "shape": [16, 2048, 2048], "dtype": "float32", "dist": "normal", "seed": 3034, "scale": 0.05 }
|
| 417 |
+
},
|
| 418 |
+
"outputs": { "outputT": { "shape": [1, 2048], "dtype": "float32" } },
|
| 419 |
+
"bench": { "metrics": [{ "type": "bandwidth", "value": "args.topK * 3 * args.hidden * args.inter * 4" }] }
|
| 420 |
+
},
|
| 421 |
+
{
|
| 422 |
+
"name": "moe-f32-olmoe-prefill-t128-h2048-e16-k8-i2048",
|
| 423 |
+
"preset": "model",
|
| 424 |
+
"provenance": { "notes": "OLMoE class defaults at a 128-token prefill chunk." },
|
| 425 |
+
"vars": { "tokens": 128, "hidden": 2048, "experts": 16, "inter": 2048, "topK": 8 },
|
| 426 |
+
"attrs": { "k": 8, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 427 |
+
"inputs": {
|
| 428 |
+
"inputT": { "shape": [128, 2048], "dtype": "float32", "dist": "normal", "seed": 3041, "scale": 0.5 },
|
| 429 |
+
"routerT": { "shape": [128, 16], "dtype": "float32", "dist": "normal", "seed": 3042, "scale": 0.7 },
|
| 430 |
+
"fc1T": { "shape": [16, 4096, 2048], "dtype": "float32", "dist": "normal", "seed": 3043, "scale": 0.05 },
|
| 431 |
+
"fc2T": { "shape": [16, 2048, 2048], "dtype": "float32", "dist": "normal", "seed": 3044, "scale": 0.05 }
|
| 432 |
+
},
|
| 433 |
+
"outputs": { "outputT": { "shape": [128, 2048], "dtype": "float32" } },
|
| 434 |
+
"bench": {
|
| 435 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 436 |
+
}
|
| 437 |
+
},
|
| 438 |
+
{
|
| 439 |
+
"name": "moe-f32-qwen2-moe-decode-t1-h2048-e20-k4-i1408",
|
| 440 |
+
"preset": "model",
|
| 441 |
+
"provenance": {
|
| 442 |
+
"notes": "Qwen2-MoE class defaults (hidden_size 2048, moe_intermediate_size 1408, num_experts_per_tok 4); expert count capped at 20 of the config's 60. Scored as bandwidth, not gflops: a decode step reads whole expert weight matrices to produce one output row, so memory is its roofline and the compute peak is the wrong denominator. The prefill cases stay on gflops."
|
| 443 |
+
},
|
| 444 |
+
"vars": { "tokens": 1, "hidden": 2048, "experts": 20, "inter": 1408, "topK": 4 },
|
| 445 |
+
"attrs": { "k": 4, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 446 |
+
"inputs": {
|
| 447 |
+
"inputT": { "shape": [1, 2048], "dtype": "float32", "dist": "normal", "seed": 3051, "scale": 0.5 },
|
| 448 |
+
"routerT": { "shape": [1, 20], "dtype": "float32", "dist": "normal", "seed": 3052, "scale": 0.7 },
|
| 449 |
+
"fc1T": { "shape": [20, 2816, 2048], "dtype": "float32", "dist": "normal", "seed": 3053, "scale": 0.05 },
|
| 450 |
+
"fc2T": { "shape": [20, 2048, 1408], "dtype": "float32", "dist": "normal", "seed": 3054, "scale": 0.05 }
|
| 451 |
+
},
|
| 452 |
+
"outputs": { "outputT": { "shape": [1, 2048], "dtype": "float32" } },
|
| 453 |
+
"bench": { "metrics": [{ "type": "bandwidth", "value": "args.topK * 3 * args.hidden * args.inter * 4" }] }
|
| 454 |
+
},
|
| 455 |
+
{
|
| 456 |
+
"name": "moe-f32-qwen2-moe-prefill-t256-h2048-e20-k4-i1408",
|
| 457 |
+
"preset": "model",
|
| 458 |
+
"provenance": { "notes": "Qwen2-MoE class defaults at a 256-token prefill chunk." },
|
| 459 |
+
"vars": { "tokens": 256, "hidden": 2048, "experts": 20, "inter": 1408, "topK": 4 },
|
| 460 |
+
"attrs": { "k": 4, "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 461 |
+
"inputs": {
|
| 462 |
+
"inputT": { "shape": [256, 2048], "dtype": "float32", "dist": "normal", "seed": 3061, "scale": 0.5 },
|
| 463 |
+
"routerT": { "shape": [256, 20], "dtype": "float32", "dist": "normal", "seed": 3062, "scale": 0.7 },
|
| 464 |
+
"fc1T": { "shape": [20, 2816, 2048], "dtype": "float32", "dist": "normal", "seed": 3063, "scale": 0.05 },
|
| 465 |
+
"fc2T": { "shape": [20, 2048, 1408], "dtype": "float32", "dist": "normal", "seed": 3064, "scale": 0.05 }
|
| 466 |
+
},
|
| 467 |
+
"outputs": { "outputT": { "shape": [256, 2048], "dtype": "float32" } },
|
| 468 |
+
"bench": {
|
| 469 |
+
"metrics": [{ "type": "gflops", "value": "2 * args.tokens * args.topK * args.hidden * args.inter * 3" }]
|
| 470 |
+
}
|
| 471 |
+
}
|
| 472 |
+
]
|
| 473 |
+
}
|
build/webgpu/expert-group-slots.wgsl.jinja
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
+
|
| 3 |
+
// Group this token chunk's routed slots by expert, then cut each expert's run into
|
| 4 |
+
// MTILE-row tiles for the grouped FFN stage.
|
| 5 |
+
//
|
| 6 |
+
// The unit being grouped is the SLOT, not the token: a token contributes TOP_K slots and each
|
| 7 |
+
// one carries its own expert, so the slot space is a K-COVER of [0, chunkTokens * TOP_K) rather
|
| 8 |
+
// than a partition of the tokens. That is what lets the grouped tiles serve any k -- a token
|
| 9 |
+
// simply appears once in each of the (up to TOP_K) expert runs it was routed to.
|
| 10 |
+
//
|
| 11 |
+
// tile_meta[0] is the tile count; tile t occupies the three words at 1 + t * 3 and holds its
|
| 12 |
+
// expert, the start of its slice of slot_list, and how many rows of that slice are real.
|
| 13 |
+
//
|
| 14 |
+
// Each expert run may end with one partial tile, so the grouped schedule carries
|
| 15 |
+
// about EXPERTS * MTILE / 2 padded rows.
|
| 16 |
+
const EXPERTS: u32 = {{ experts }}u;
|
| 17 |
+
const TOP_K: u32 = {{ topK }}u;
|
| 18 |
+
const MTILE: u32 = {{ groupTileM }}u;
|
| 19 |
+
const WG: u32 = {{ groupRouteWorkgroup }}u;
|
| 20 |
+
|
| 21 |
+
var<workgroup> counts: array<atomic<u32>, {{ experts }}>;
|
| 22 |
+
var<workgroup> offsets: array<u32, {{ experts }}>;
|
| 23 |
+
|
| 24 |
+
@compute @workgroup_size(WG, 1, 1)
|
| 25 |
+
fn main(@builtin(local_invocation_index) lid: u32) {
|
| 26 |
+
let slot_total = params.tokenCount * TOP_K;
|
| 27 |
+
let slot_base = params.tokenOffset * TOP_K;
|
| 28 |
+
|
| 29 |
+
for (var e = lid; e < EXPERTS; e = e + WG) {
|
| 30 |
+
atomicStore(&counts[e], 0u);
|
| 31 |
+
}
|
| 32 |
+
workgroupBarrier();
|
| 33 |
+
|
| 34 |
+
for (var p = lid; p < slot_total; p = p + WG) {
|
| 35 |
+
atomicAdd(&counts[route_expert[slot_base + p]], 1u);
|
| 36 |
+
}
|
| 37 |
+
workgroupBarrier();
|
| 38 |
+
|
| 39 |
+
// One lane lays out the EXPERTS-sized run and tile tables. The chunk-sized
|
| 40 |
+
// scatter below is distributed over the workgroup.
|
| 41 |
+
if (lid == 0u) {
|
| 42 |
+
var offset = 0u;
|
| 43 |
+
var tile = 0u;
|
| 44 |
+
for (var e = 0u; e < EXPERTS; e = e + 1u) {
|
| 45 |
+
offsets[e] = offset;
|
| 46 |
+
let n = atomicLoad(&counts[e]);
|
| 47 |
+
var done = 0u;
|
| 48 |
+
while (done < n) {
|
| 49 |
+
let rows = min(MTILE, n - done);
|
| 50 |
+
tile_meta[1u + tile * 3u] = e;
|
| 51 |
+
tile_meta[1u + tile * 3u + 1u] = offset + done;
|
| 52 |
+
tile_meta[1u + tile * 3u + 2u] = rows;
|
| 53 |
+
tile = tile + 1u;
|
| 54 |
+
done = done + rows;
|
| 55 |
+
}
|
| 56 |
+
offset = offset + n;
|
| 57 |
+
atomicStore(&counts[e], 0u);
|
| 58 |
+
}
|
| 59 |
+
tile_meta[0] = tile;
|
| 60 |
+
}
|
| 61 |
+
workgroupBarrier();
|
| 62 |
+
|
| 63 |
+
// Each slot atomically claims a position in its expert's run. Arrival order is
|
| 64 |
+
// safe because downstream dots use the slot's own row and reduce to its token;
|
| 65 |
+
// no consumer assigns meaning to order within a run.
|
| 66 |
+
for (var p = lid; p < slot_total; p = p + WG) {
|
| 67 |
+
let expert = route_expert[slot_base + p];
|
| 68 |
+
slot_list[offsets[expert] + atomicAdd(&counts[expert], 1u)] = p;
|
| 69 |
+
}
|
| 70 |
+
}
|
build/webgpu/manifest.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
build/webgpu/metadata.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "com.microsoft.MoE",
|
| 3 |
+
"id": "_com_microsoft_moe_webgpu_9c7f8e1",
|
| 4 |
+
"version": 1,
|
| 5 |
+
"license": "Apache-2.0",
|
| 6 |
+
"backend": { "type": "webgpu" },
|
| 7 |
+
"digest": {
|
| 8 |
+
"algorithm": "sha256",
|
| 9 |
+
"files": {
|
| 10 |
+
"bench.json": "Oq7rf+LMUf5McimJEVeHF3PM3CEHu7X/yCrhSJdoZq4=",
|
| 11 |
+
"expert-group-slots.wgsl.jinja": "Ta+3H2FA1qRRzksdkwgKLZiO+AokmuM+B9JVN8cv1EQ=",
|
| 12 |
+
"manifest.json": "1u7xRTHJz3qXke+74gJ0e7GZQdJ9SCJw/8gpaOkB9U4=",
|
| 13 |
+
"moe-ffn-gemv.wgsl.jinja": "loPQLZYp+Lkz/jq0ML5cYbMFP+IWHlpULSiZcaOx33s=",
|
| 14 |
+
"moe-ffn-grouped.wgsl.jinja": "m5rGC8aq9oW2TsQ2P3B2uV7Hm7u90DFORehlxFnSw5c=",
|
| 15 |
+
"moe-ffn-stage.wgsl.jinja": "uIz5vVs9A8s5K5B2ZDj4fYDX3BGsWUfR8LxThIR95Tk=",
|
| 16 |
+
"moe-mix-stage.wgsl.jinja": "+deuFyuBn04UeIX8Hk2/ntCHNfM1vgkNDTcsh3uXVdI=",
|
| 17 |
+
"moe-output-gemv.wgsl.jinja": "5yj+BoTsRHiHW92Q8fVvtojdkY7r1jHupMX+FPVQMBk=",
|
| 18 |
+
"moe-output-grouped.wgsl.jinja": "qzP5G/WtwF4zOBrtySCLTCBflHuvKlU8dk4/CRIzxe8=",
|
| 19 |
+
"moe-output-stage.wgsl.jinja": "wtB+CtWxl8XChH4Y4/8LEBdHOznrdsUlAo65tmGEuWw=",
|
| 20 |
+
"moe-route-stage.wgsl.jinja": "6uVRcLbpzp0Y1a8+jRTHOfvBhfCKpCoVju0dBDCVlgo=",
|
| 21 |
+
"test.json": "T5bB5QuC2mzb2c0i+BQMaTbJjyyvFaL3ikEc4mFJBaw="
|
| 22 |
+
}
|
| 23 |
+
},
|
| 24 |
+
"provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
|
| 25 |
+
"webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/com.microsoft.MoE" }
|
| 26 |
+
}
|
build/webgpu/moe-ffn-gemv.wgsl.jinja
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
+
|
| 3 |
+
// FC1 (and, where the schema splits them, FC3) projection plus the activation, on the
|
| 4 |
+
// cooperative schedule. The split stage gives one thread a whole HIDDEN-long reduction, so a
|
| 5 |
+
// decode dispatch offers only tokens * TOP_K * INTER invocations; here a workgroup owns ROWS
|
| 6 |
+
// intermediate lanes of one routed slot and LANES lanes split the reduction instead.
|
| 7 |
+
// Both operands of a two-operand activation are reduced in the same loop, so each input element
|
| 8 |
+
// is loaded once and used by both projections.
|
| 9 |
+
const HIDDEN: u32 = {{ hidden }}u;
|
| 10 |
+
const INTER: u32 = {{ inter }}u;
|
| 11 |
+
const FC1_ROWS: u32 = {{ fc1Rows }}u;
|
| 12 |
+
const TOP_K: u32 = {{ topK }}u;
|
| 13 |
+
const LANES: u32 = {{ decodeLanes }}u;
|
| 14 |
+
const ROWS: u32 = {{ decodeRows }}u;
|
| 15 |
+
{% if activation == "gelu" %}fn tanh_safe(x: f32) -> f32 {
|
| 16 |
+
if (x > 10.0) { return 1.0; }
|
| 17 |
+
if (x < -10.0) { return -1.0; }
|
| 18 |
+
return tanh(x);
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
fn gelu_tanh(v: f32) -> f32 {
|
| 22 |
+
return 0.5 * v * (1.0 + tanh_safe(0.7978845608028654 * (v + 0.044715 * v * v * v)));
|
| 23 |
+
}{% endif %}
|
| 24 |
+
{% set isSwiglu = activation == "swiglu" %}
|
| 25 |
+
{% set secondFromFc3 = hasFc3 and (not isSwiglu or swigluFusion == 0) %}
|
| 26 |
+
{% set hasSecond = isSwiglu or hasFc3 %}
|
| 27 |
+
{% set primaryRow = "i * 2u" if (isSwiglu and swigluFusion == 1) else "i" %}
|
| 28 |
+
|
| 29 |
+
fn fc1_row(expert: u32, row: u32) -> u32 {
|
| 30 |
+
return (expert * FC1_ROWS + row) * HIDDEN;
|
| 31 |
+
}
|
| 32 |
+
{% if activation == "swiglu" %}
|
| 33 |
+
|
| 34 |
+
fn swiglu(gate_in: f32, up_in: f32) -> f32 {
|
| 35 |
+
{% if hasSwigluLimit %}
|
| 36 |
+
// swiglu_limit clamps the gate operand from above and the linear operand to [-limit, limit]
|
| 37 |
+
// before the product; when the attribute is absent no clamp is applied.
|
| 38 |
+
let gate = min(gate_in, {{ swigluLimit }});
|
| 39 |
+
let up = clamp(up_in, -({{ swigluLimit }}), {{ swigluLimit }});
|
| 40 |
+
{% else %}
|
| 41 |
+
let gate = gate_in;
|
| 42 |
+
let up = up_in;
|
| 43 |
+
{% endif %}
|
| 44 |
+
return gate / (1.0 + exp(-params.activationAlpha * gate)) * (up + params.activationBeta);
|
| 45 |
+
}
|
| 46 |
+
{% endif %}
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
{% macro rowlane_fold(arrays, lanes="LANES", lane="lane", slot="slot") %}
|
| 50 |
+
var n = {{ lanes }};
|
| 51 |
+
while (n > 1u) {
|
| 52 |
+
let half = (n + 1u) / 2u;
|
| 53 |
+
if ({{ lane }} + half < n) {
|
| 54 |
+
{% for a in arrays %}
|
| 55 |
+
{{ a }}[{{ slot }}] = {{ a }}[{{ slot }}] + {{ a }}[{{ slot }} + half];
|
| 56 |
+
{% endfor %}
|
| 57 |
+
}
|
| 58 |
+
workgroupBarrier();
|
| 59 |
+
n = half;
|
| 60 |
+
}
|
| 61 |
+
{%- endmacro %}
|
| 62 |
+
|
| 63 |
+
var<workgroup> primary_partial: array<f32, {{ decodeLanes * decodeRows }}>;
|
| 64 |
+
{% if hasSecond %}
|
| 65 |
+
var<workgroup> secondary_partial: array<f32, {{ decodeLanes * decodeRows }}>;
|
| 66 |
+
{% endif %}
|
| 67 |
+
|
| 68 |
+
@compute @workgroup_size(LANES, ROWS, 1)
|
| 69 |
+
fn main(@builtin(workgroup_id) wid: vec3<u32>,
|
| 70 |
+
@builtin(local_invocation_id) lid: vec3<u32>) {
|
| 71 |
+
let i = wid.x * ROWS + lid.y;
|
| 72 |
+
let lane = lid.x;
|
| 73 |
+
// wid.y is the routed slot's index within this token chunk -- the split stage's
|
| 74 |
+
// `local_token * TOP_K + j` -- so hidden_act is addressed identically by both schedules.
|
| 75 |
+
let local_slot = wid.y;
|
| 76 |
+
let token = params.tokenOffset + local_slot / TOP_K;
|
| 77 |
+
let expert = route_expert[token * TOP_K + local_slot % TOP_K];
|
| 78 |
+
let in_range = i < INTER;
|
| 79 |
+
|
| 80 |
+
var primary = 0.0;
|
| 81 |
+
{% if hasSecond %}
|
| 82 |
+
var secondary = 0.0;
|
| 83 |
+
{% endif %}
|
| 84 |
+
if (in_range) {
|
| 85 |
+
let a_base = fc1_row(expert, {{ primaryRow }});
|
| 86 |
+
{% if secondFromFc3 %}
|
| 87 |
+
let b_base = (expert * INTER + i) * HIDDEN;
|
| 88 |
+
{% elif isSwiglu and swigluFusion == 1 %}
|
| 89 |
+
// swiglu_fusion 1: one fused FC1 whose row pairs are interleaved on each row of 2 * inter.
|
| 90 |
+
let b_base = fc1_row(expert, i * 2u + 1u);
|
| 91 |
+
{% elif hasSecond %}
|
| 92 |
+
// swiglu_fusion 2: one fused FC1 whose two halves are concatenated on each row.
|
| 93 |
+
let b_base = fc1_row(expert, INTER + i);
|
| 94 |
+
{% endif %}
|
| 95 |
+
for (var h = lane; h < HIDDEN; h = h + LANES) {
|
| 96 |
+
let x = input[token * HIDDEN + h];
|
| 97 |
+
primary = primary + x * fc1_experts_weights[a_base + h];
|
| 98 |
+
{% if secondFromFc3 %}
|
| 99 |
+
secondary = secondary + x * fc3_experts_weights[b_base + h];
|
| 100 |
+
{% elif hasSecond %}
|
| 101 |
+
secondary = secondary + x * fc1_experts_weights[b_base + h];
|
| 102 |
+
{% endif %}
|
| 103 |
+
}
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
let slot = lid.y * LANES + lane;
|
| 107 |
+
primary_partial[slot] = primary;
|
| 108 |
+
{% if hasSecond %}
|
| 109 |
+
secondary_partial[slot] = secondary;
|
| 110 |
+
{% endif %}
|
| 111 |
+
workgroupBarrier();
|
| 112 |
+
{% if hasSecond %}
|
| 113 |
+
{{ rowlane_fold(["primary_partial", "secondary_partial"]) }}
|
| 114 |
+
{% else %}
|
| 115 |
+
{{ rowlane_fold(["primary_partial"]) }}
|
| 116 |
+
{% endif %}
|
| 117 |
+
|
| 118 |
+
if (lane == 0u && in_range) {
|
| 119 |
+
let base = lid.y * LANES;
|
| 120 |
+
// A bias belongs to the whole projection, so it is added once to the folded sum rather
|
| 121 |
+
// than to any lane's partial.
|
| 122 |
+
{% if hasFc1Bias %}
|
| 123 |
+
let a = primary_partial[base] + fc1_experts_bias[expert * FC1_ROWS + {{ primaryRow }}];
|
| 124 |
+
{% else %}
|
| 125 |
+
let a = primary_partial[base];
|
| 126 |
+
{% endif %}
|
| 127 |
+
{% if secondFromFc3 and hasFc3Bias %}
|
| 128 |
+
let b = secondary_partial[base] + fc3_experts_bias[expert * INTER + i];
|
| 129 |
+
{% elif secondFromFc3 %}
|
| 130 |
+
let b = secondary_partial[base];
|
| 131 |
+
{% elif hasSecond and hasFc1Bias and swigluFusion == 1 %}
|
| 132 |
+
let b = secondary_partial[base] + fc1_experts_bias[expert * FC1_ROWS + i * 2u + 1u];
|
| 133 |
+
{% elif hasSecond and hasFc1Bias %}
|
| 134 |
+
let b = secondary_partial[base] + fc1_experts_bias[expert * FC1_ROWS + INTER + i];
|
| 135 |
+
{% elif hasSecond %}
|
| 136 |
+
let b = secondary_partial[base];
|
| 137 |
+
{% endif %}
|
| 138 |
+
{% if isSwiglu %}
|
| 139 |
+
let value = swiglu(a, b);
|
| 140 |
+
{% else %}
|
| 141 |
+
{% if activation == "relu" %}
|
| 142 |
+
let activated = max(a, 0.0);
|
| 143 |
+
{% elif activation == "gelu" %}
|
| 144 |
+
// The operator uses the tanh GELU approximation.
|
| 145 |
+
let activated = gelu_tanh(a);
|
| 146 |
+
{% elif activation == "silu" %}
|
| 147 |
+
let activated = a / (1.0 + exp(-a));
|
| 148 |
+
{% else %}
|
| 149 |
+
let activated = a;
|
| 150 |
+
{% endif %}
|
| 151 |
+
{% if hasFc3 %}
|
| 152 |
+
// SiLU with FC3 is the gated-MLP form: SiLU(FC1) multiplies the linear FC3 projection.
|
| 153 |
+
let value = activated * b;
|
| 154 |
+
{% else %}
|
| 155 |
+
let value = activated;
|
| 156 |
+
{% endif %}
|
| 157 |
+
{% endif %}
|
| 158 |
+
hidden_act[local_slot * INTER + i] = value;
|
| 159 |
+
}
|
| 160 |
+
}
|
build/webgpu/moe-ffn-grouped.wgsl.jinja
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
+
|
| 3 |
+
// FC1 (and, where the schema splits them, FC3) projection plus the activation, on the grouped
|
| 4 |
+
// schedule. The other two schedules read a whole expert weight matrix once per routed slot,
|
| 5 |
+
// which at prefill is the entire cost: for hidden 1024 / inter 512 that is 2 MB of weights per
|
| 6 |
+
// slot, re-read for every slot the expert serves.
|
| 7 |
+
//
|
| 8 |
+
// Here the group stage has already sorted the chunk's slots by expert, so a tile of MTILE rows
|
| 9 |
+
// shares ONE expert -- and therefore one weight tile, staged in workgroup memory and reused by
|
| 10 |
+
// every row.
|
| 11 |
+
const HIDDEN: u32 = {{ hidden }}u;
|
| 12 |
+
const INTER: u32 = {{ inter }}u;
|
| 13 |
+
const FC1_ROWS: u32 = {{ fc1Rows }}u;
|
| 14 |
+
const TOP_K: u32 = {{ topK }}u;
|
| 15 |
+
const MTILE: u32 = {{ groupTileM }}u;
|
| 16 |
+
const NTILE: u32 = {{ groupTileN }}u;
|
| 17 |
+
const KTILE: u32 = {{ groupTileK }}u;
|
| 18 |
+
const THREADS_SIDE: u32 = {{ groupThreads }}u;
|
| 19 |
+
const THREADS: u32 = THREADS_SIDE * THREADS_SIDE;
|
| 20 |
+
{% if activation == "gelu" %}fn tanh_safe(x: f32) -> f32 {
|
| 21 |
+
if (x > 10.0) { return 1.0; }
|
| 22 |
+
if (x < -10.0) { return -1.0; }
|
| 23 |
+
return tanh(x);
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
fn gelu_tanh(v: f32) -> f32 {
|
| 27 |
+
return 0.5 * v * (1.0 + tanh_safe(0.7978845608028654 * (v + 0.044715 * v * v * v)));
|
| 28 |
+
}{% endif %}
|
| 29 |
+
{% set isSwiglu = activation == "swiglu" %}
|
| 30 |
+
{% set secondFromFc3 = hasFc3 and (not isSwiglu or swigluFusion == 0) %}
|
| 31 |
+
{% set hasSecond = isSwiglu or hasFc3 %}
|
| 32 |
+
{% set primaryRow = "(col * 2u)" if (isSwiglu and swigluFusion == 1) else "col" %}
|
| 33 |
+
{% if secondFromFc3 %}
|
| 34 |
+
{% set secondRowBase = "(expert * INTER + col)" %}
|
| 35 |
+
{% set secondBuffer = "fc3_experts_weights" %}
|
| 36 |
+
{% elif isSwiglu and swigluFusion == 1 %}
|
| 37 |
+
{% set secondRowBase = "(expert * FC1_ROWS + col * 2u + 1u)" %}
|
| 38 |
+
{% set secondBuffer = "fc1_experts_weights" %}
|
| 39 |
+
{% elif hasSecond %}
|
| 40 |
+
{% set secondRowBase = "(expert * FC1_ROWS + INTER + col)" %}
|
| 41 |
+
{% set secondBuffer = "fc1_experts_weights" %}
|
| 42 |
+
{% endif %}
|
| 43 |
+
{% if activation == "swiglu" %}
|
| 44 |
+
|
| 45 |
+
fn swiglu(gate_in: f32, up_in: f32) -> f32 {
|
| 46 |
+
{% if hasSwigluLimit %}
|
| 47 |
+
// swiglu_limit clamps the gate operand from above and the linear operand to [-limit, limit]
|
| 48 |
+
// before the product; when the attribute is absent no clamp is applied.
|
| 49 |
+
let gate = min(gate_in, {{ swigluLimit }});
|
| 50 |
+
let up = clamp(up_in, -({{ swigluLimit }}), {{ swigluLimit }});
|
| 51 |
+
{% else %}
|
| 52 |
+
let gate = gate_in;
|
| 53 |
+
let up = up_in;
|
| 54 |
+
{% endif %}
|
| 55 |
+
return gate / (1.0 + exp(-params.activationAlpha * gate)) * (up + params.activationBeta);
|
| 56 |
+
}
|
| 57 |
+
{% endif %}
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
const KVEC: u32 = {{ groupTileKVec }}u;
|
| 61 |
+
{% macro stage_group_tiles(aLoad, bLoad, b2Load, kExtent, nExtent, guarded, bLoadVec4="", b2LoadVec4="", aLoadVec4="") %}
|
| 62 |
+
for (var idx = tid; idx < MTILE * KVEC; idx = idx + THREADS) {
|
| 63 |
+
let m = idx / KVEC;
|
| 64 |
+
let kb = (idx % KVEC) * 4u;
|
| 65 |
+
var a_vec: vec4<f32>;
|
| 66 |
+
{% if aLoadVec4 and not guarded %}
|
| 67 |
+
a_vec = {{ aLoadVec4 }};
|
| 68 |
+
{% else %}
|
| 69 |
+
{% for j in range(4) %}
|
| 70 |
+
{
|
| 71 |
+
let k = kb + {{ j }}u;
|
| 72 |
+
a_vec[{{ j }}] = {{ ("select(0.0, " ~ aLoad ~ ", k_base + k < " ~ kExtent ~ ")") if guarded else aLoad }};
|
| 73 |
+
}
|
| 74 |
+
{% endfor %}
|
| 75 |
+
{% endif %}
|
| 76 |
+
a_tile[idx] = a_vec;
|
| 77 |
+
}
|
| 78 |
+
for (var idx = tid; idx < NTILE * KVEC; idx = idx + THREADS) {
|
| 79 |
+
let n = idx / KVEC;
|
| 80 |
+
let kb = (idx % KVEC) * 4u;
|
| 81 |
+
let col = n_base + n;
|
| 82 |
+
{% if guarded %}
|
| 83 |
+
let col_live = col < {{ nExtent }};
|
| 84 |
+
{% endif %}
|
| 85 |
+
var b_vec: vec4<f32>;
|
| 86 |
+
{% if b2Load %}
|
| 87 |
+
var b2_vec: vec4<f32>;
|
| 88 |
+
{% endif %}
|
| 89 |
+
{% if bLoadVec4 and not guarded %}
|
| 90 |
+
b_vec = {{ bLoadVec4 }};
|
| 91 |
+
{% if b2Load %}
|
| 92 |
+
b2_vec = {{ b2LoadVec4 }};
|
| 93 |
+
{% endif %}
|
| 94 |
+
{% else %}
|
| 95 |
+
{% for j in range(4) %}
|
| 96 |
+
{
|
| 97 |
+
let k = kb + {{ j }}u;
|
| 98 |
+
{% if guarded %}
|
| 99 |
+
let live = col_live && k_base + k < {{ kExtent }};
|
| 100 |
+
{% endif %}
|
| 101 |
+
b_vec[{{ j }}] = {{ ("select(0.0, " ~ bLoad ~ ", live)") if guarded else bLoad }};
|
| 102 |
+
{% if b2Load %}
|
| 103 |
+
b2_vec[{{ j }}] = {{ ("select(0.0, " ~ b2Load ~ ", live)") if guarded else b2Load }};
|
| 104 |
+
{% endif %}
|
| 105 |
+
}
|
| 106 |
+
{% endfor %}
|
| 107 |
+
{% endif %}
|
| 108 |
+
b_tile[idx] = b_vec;
|
| 109 |
+
{% if b2Load %}
|
| 110 |
+
b2_tile[idx] = b2_vec;
|
| 111 |
+
{% endif %}
|
| 112 |
+
}
|
| 113 |
+
{%- endmacro %}
|
| 114 |
+
|
| 115 |
+
{% macro group_tile_loop(aLoad, bLoad, b2Load, kExtent, nExtent, regM, regN, bLoadVec4="", b2LoadVec4="", aLoadVec4="") %}
|
| 116 |
+
{% for r in range(regM) %}
|
| 117 |
+
{% for c in range(regN) %}
|
| 118 |
+
var acc_{{ r }}_{{ c }} = 0.0;
|
| 119 |
+
{% if b2Load %}
|
| 120 |
+
var acc2_{{ r }}_{{ c }} = 0.0;
|
| 121 |
+
{% endif %}
|
| 122 |
+
{% endfor %}
|
| 123 |
+
{% endfor %}
|
| 124 |
+
|
| 125 |
+
// A tile that lies wholly inside both extents needs no per-element bounds check, and
|
| 126 |
+
// that is every tile but the edges: the guards below exist for a reduction axis or an
|
| 127 |
+
// output width the tile size does not divide, yet the interior tiles were paying four
|
| 128 |
+
// comparisons and four selects per staged vec4 -- against 64 fused multiply-adds of
|
| 129 |
+
// actual work. Both arms stage identical values. The test is workgroup-uniform, so the
|
| 130 |
+
// barrier after it is still reached by every invocation together.
|
| 131 |
+
let n_full = n_base + NTILE <= {{ nExtent }};
|
| 132 |
+
var k_base = 0u;
|
| 133 |
+
loop {
|
| 134 |
+
if (k_base >= {{ kExtent }}) {
|
| 135 |
+
break;
|
| 136 |
+
}
|
| 137 |
+
if (n_full && k_base + KTILE <= {{ kExtent }}) {
|
| 138 |
+
{{ stage_group_tiles(aLoad, bLoad, b2Load, kExtent, nExtent, false, bLoadVec4, b2LoadVec4, aLoadVec4) }}
|
| 139 |
+
} else {
|
| 140 |
+
{{ stage_group_tiles(aLoad, bLoad, b2Load, kExtent, nExtent, true) }}
|
| 141 |
+
}
|
| 142 |
+
workgroupBarrier();
|
| 143 |
+
|
| 144 |
+
for (var kv = 0u; kv < KVEC; kv = kv + 1u) {
|
| 145 |
+
{% for r in range(regM) %}
|
| 146 |
+
let a{{ r }} = a_tile[(lid.y * {{ regM }}u + {{ r }}u) * KVEC + kv];
|
| 147 |
+
{% endfor %}
|
| 148 |
+
{% for c in range(regN) %}
|
| 149 |
+
let b{{ c }} = b_tile[(lid.x * {{ regN }}u + {{ c }}u) * KVEC + kv];
|
| 150 |
+
{% if b2Load %}
|
| 151 |
+
let s{{ c }} = b2_tile[(lid.x * {{ regN }}u + {{ c }}u) * KVEC + kv];
|
| 152 |
+
{% endif %}
|
| 153 |
+
{% endfor %}
|
| 154 |
+
{% for r in range(regM) %}
|
| 155 |
+
{% for c in range(regN) %}
|
| 156 |
+
acc_{{ r }}_{{ c }} = acc_{{ r }}_{{ c }} + dot(a{{ r }}, b{{ c }});
|
| 157 |
+
{% if b2Load %}
|
| 158 |
+
acc2_{{ r }}_{{ c }} = acc2_{{ r }}_{{ c }} + dot(a{{ r }}, s{{ c }});
|
| 159 |
+
{% endif %}
|
| 160 |
+
{% endfor %}
|
| 161 |
+
{% endfor %}
|
| 162 |
+
}
|
| 163 |
+
// Orders this step's tile reads before the next step overwrites them.
|
| 164 |
+
workgroupBarrier();
|
| 165 |
+
k_base = k_base + KTILE;
|
| 166 |
+
}
|
| 167 |
+
{%- endmacro %}
|
| 168 |
+
|
| 169 |
+
var<workgroup> row_slot: array<u32, {{ groupTileM }}>;
|
| 170 |
+
var<workgroup> a_tile: array<vec4<f32>, {{ groupTileM * groupTileKVec }}>;
|
| 171 |
+
var<workgroup> b_tile: array<vec4<f32>, {{ groupTileN * groupTileKVec }}>;
|
| 172 |
+
{% if hasSecond %}
|
| 173 |
+
var<workgroup> b2_tile: array<vec4<f32>, {{ groupTileN * groupTileKVec }}>;
|
| 174 |
+
{% endif %}
|
| 175 |
+
|
| 176 |
+
@compute @workgroup_size(THREADS_SIDE, THREADS_SIDE, 1)
|
| 177 |
+
fn main(@builtin(workgroup_id) wid: vec3<u32>,
|
| 178 |
+
@builtin(local_invocation_id) lid: vec3<u32>) {
|
| 179 |
+
let tile = wid.x;
|
| 180 |
+
if (tile >= tile_meta[0]) {
|
| 181 |
+
return;
|
| 182 |
+
}
|
| 183 |
+
let expert = tile_meta[1u + tile * 3u];
|
| 184 |
+
let slice_base = tile_meta[1u + tile * 3u + 1u];
|
| 185 |
+
let rows = tile_meta[1u + tile * 3u + 2u];
|
| 186 |
+
let n_base = wid.y * NTILE;
|
| 187 |
+
let tid = lid.y * THREADS_SIDE + lid.x;
|
| 188 |
+
|
| 189 |
+
for (var m = tid; m < MTILE; m = m + THREADS) {
|
| 190 |
+
// Rows past this tile's end park on row 0; their results are discarded at the store.
|
| 191 |
+
row_slot[m] = select(0u, slot_list[slice_base + m], m < rows);
|
| 192 |
+
}
|
| 193 |
+
workgroupBarrier();
|
| 194 |
+
{% macro at(buf, idx) %}{% if groupVec4 %}{{ buf }}[({{ idx }}) / 4u][({{ idx }}) % 4u]{% else %}{{ buf }}[{{ idx }}]{% endif %}{% endmacro %}
|
| 195 |
+
{% macro at4(buf, idx) %}{{ buf }}[({{ idx }}) / 4u]{% endmacro %}
|
| 196 |
+
{% set aPre = "(params.tokenOffset + row_slot[m] / TOP_K) * HIDDEN + k_base + " %}
|
| 197 |
+
{% set bPre = "(expert * FC1_ROWS + " ~ primaryRow ~ ") * HIDDEN + k_base + " %}
|
| 198 |
+
{% set cPre = (secondRowBase ~ " * HIDDEN + k_base + ") if hasSecond else "" %}
|
| 199 |
+
{{ group_tile_loop(at("input", aPre ~ "k"),
|
| 200 |
+
at("fc1_experts_weights", bPre ~ "k"),
|
| 201 |
+
at(secondBuffer, cPre ~ "k") if hasSecond else "",
|
| 202 |
+
"HIDDEN", "INTER", regM, regN,
|
| 203 |
+
at4("fc1_experts_weights", bPre ~ "kb") if groupVec4 else "",
|
| 204 |
+
(at4(secondBuffer, cPre ~ "kb") if hasSecond else "") if groupVec4 else "",
|
| 205 |
+
at4("input", aPre ~ "kb") if groupVec4 else "") }}
|
| 206 |
+
|
| 207 |
+
{% for r in range(regM) %}
|
| 208 |
+
{% for c in range(regN) %}
|
| 209 |
+
{
|
| 210 |
+
let m = lid.y * {{ regM }}u + {{ r }}u;
|
| 211 |
+
let col = n_base + lid.x * {{ regN }}u + {{ c }}u;
|
| 212 |
+
if (m < rows && col < INTER) {
|
| 213 |
+
{% if hasFc1Bias %}
|
| 214 |
+
let a = acc_{{ r }}_{{ c }} + fc1_experts_bias[expert * FC1_ROWS + {{ primaryRow }}];
|
| 215 |
+
{% else %}
|
| 216 |
+
let a = acc_{{ r }}_{{ c }};
|
| 217 |
+
{% endif %}
|
| 218 |
+
{% if secondFromFc3 and hasFc3Bias %}
|
| 219 |
+
let b = acc2_{{ r }}_{{ c }} + fc3_experts_bias[expert * INTER + col];
|
| 220 |
+
{% elif secondFromFc3 %}
|
| 221 |
+
let b = acc2_{{ r }}_{{ c }};
|
| 222 |
+
{% elif hasSecond and hasFc1Bias and swigluFusion == 1 %}
|
| 223 |
+
let b = acc2_{{ r }}_{{ c }} + fc1_experts_bias[expert * FC1_ROWS + col * 2u + 1u];
|
| 224 |
+
{% elif hasSecond and hasFc1Bias %}
|
| 225 |
+
let b = acc2_{{ r }}_{{ c }} + fc1_experts_bias[expert * FC1_ROWS + INTER + col];
|
| 226 |
+
{% elif hasSecond %}
|
| 227 |
+
let b = acc2_{{ r }}_{{ c }};
|
| 228 |
+
{% endif %}
|
| 229 |
+
{% if isSwiglu %}
|
| 230 |
+
let value = swiglu(a, b);
|
| 231 |
+
{% else %}
|
| 232 |
+
{% if activation == "relu" %}
|
| 233 |
+
let activated = max(a, 0.0);
|
| 234 |
+
{% elif activation == "gelu" %}
|
| 235 |
+
// This operator's GELU mode uses the tanh approximation.
|
| 236 |
+
let activated = gelu_tanh(a);
|
| 237 |
+
{% elif activation == "silu" %}
|
| 238 |
+
let activated = a / (1.0 + exp(-a));
|
| 239 |
+
{% else %}
|
| 240 |
+
let activated = a;
|
| 241 |
+
{% endif %}
|
| 242 |
+
{% if hasFc3 %}
|
| 243 |
+
// SiLU with FC3 is the gated-MLP form: SiLU(FC1) multiplies the linear FC3 projection.
|
| 244 |
+
let value = activated * b;
|
| 245 |
+
{% else %}
|
| 246 |
+
let value = activated;
|
| 247 |
+
{% endif %}
|
| 248 |
+
{% endif %}
|
| 249 |
+
hidden_act[row_slot[m] * INTER + col] = value;
|
| 250 |
+
}
|
| 251 |
+
}
|
| 252 |
+
{% endfor %}
|
| 253 |
+
{% endfor %}
|
| 254 |
+
}
|
build/webgpu/moe-ffn-stage.wgsl.jinja
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
+
|
| 3 |
+
// FC1 (and, where the schema splits them, FC3) projection plus the activation. One thread owns
|
| 4 |
+
// one intermediate lane of one routed slot, so the grid is (token, slot, inter) flattened and
|
| 5 |
+
// hidden_act is addressed by the same flat index.
|
| 6 |
+
const HIDDEN: u32 = {{ hidden }}u;
|
| 7 |
+
const INTER: u32 = {{ inter }}u;
|
| 8 |
+
// WGSL rejects a const-expression `/ 0u` outright; the contract keeps INTER positive, and this
|
| 9 |
+
// guard keeps the divisor well-formed for any future degenerate arm.
|
| 10 |
+
const INTER_DIV: u32 = max(1u, INTER);
|
| 11 |
+
const FC1_ROWS: u32 = {{ fc1Rows }}u;
|
| 12 |
+
const TOP_K: u32 = {{ topK }}u;
|
| 13 |
+
const WG: u32 = {{ workgroupSize }}u;
|
| 14 |
+
{% if activation == "gelu" %}fn tanh_safe(x: f32) -> f32 {
|
| 15 |
+
if (x > 10.0) { return 1.0; }
|
| 16 |
+
if (x < -10.0) { return -1.0; }
|
| 17 |
+
return tanh(x);
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
fn gelu_tanh(v: f32) -> f32 {
|
| 21 |
+
return 0.5 * v * (1.0 + tanh_safe(0.7978845608028654 * (v + 0.044715 * v * v * v)));
|
| 22 |
+
}{% endif %}
|
| 23 |
+
|
| 24 |
+
fn fc1_row(expert: u32, row: u32) -> u32 {
|
| 25 |
+
return (expert * FC1_ROWS + row) * HIDDEN;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
fn project_fc1(expert: u32, row: u32, token: u32) -> f32 {
|
| 29 |
+
let base = fc1_row(expert, row);
|
| 30 |
+
var acc = 0.0;
|
| 31 |
+
for (var h: u32 = 0u; h < HIDDEN; h = h + 1u) {
|
| 32 |
+
acc = acc + input[token * HIDDEN + h] * fc1_experts_weights[base + h];
|
| 33 |
+
}
|
| 34 |
+
{% if hasFc1Bias %}
|
| 35 |
+
return acc + fc1_experts_bias[expert * FC1_ROWS + row];
|
| 36 |
+
{% else %}
|
| 37 |
+
return acc;
|
| 38 |
+
{% endif %}
|
| 39 |
+
}
|
| 40 |
+
{% if hasFc3 %}
|
| 41 |
+
|
| 42 |
+
fn project_fc3(expert: u32, row: u32, token: u32) -> f32 {
|
| 43 |
+
let base = (expert * INTER + row) * HIDDEN;
|
| 44 |
+
var acc = 0.0;
|
| 45 |
+
for (var h: u32 = 0u; h < HIDDEN; h = h + 1u) {
|
| 46 |
+
acc = acc + input[token * HIDDEN + h] * fc3_experts_weights[base + h];
|
| 47 |
+
}
|
| 48 |
+
{% if hasFc3Bias %}
|
| 49 |
+
return acc + fc3_experts_bias[expert * INTER + row];
|
| 50 |
+
{% else %}
|
| 51 |
+
return acc;
|
| 52 |
+
{% endif %}
|
| 53 |
+
}
|
| 54 |
+
{% endif %}
|
| 55 |
+
{% if activation == "swiglu" %}
|
| 56 |
+
|
| 57 |
+
fn swiglu(gate_in: f32, up_in: f32) -> f32 {
|
| 58 |
+
{% if hasSwigluLimit %}
|
| 59 |
+
// swiglu_limit clamps the gate operand from above and the linear operand to [-limit, limit]
|
| 60 |
+
// before the product; when the attribute is absent no clamp is applied.
|
| 61 |
+
let gate = min(gate_in, {{ swigluLimit }});
|
| 62 |
+
let up = clamp(up_in, -({{ swigluLimit }}), {{ swigluLimit }});
|
| 63 |
+
{% else %}
|
| 64 |
+
let gate = gate_in;
|
| 65 |
+
let up = up_in;
|
| 66 |
+
{% endif %}
|
| 67 |
+
return gate / (1.0 + exp(-params.activationAlpha * gate)) * (up + params.activationBeta);
|
| 68 |
+
}
|
| 69 |
+
{% endif %}
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
@compute @workgroup_size(WG, 1, 1)
|
| 73 |
+
fn main(@builtin(global_invocation_id) gid: vec3<u32>,
|
| 74 |
+
@builtin(num_workgroups) nwg: vec3<u32>) {
|
| 75 |
+
// 2D-folded flat index: gid.y carries the high bits past the maxComputeWorkgroupsPerDimension
|
| 76 |
+
// workgroup-per-dimension dispatch limit. Reduces to gid.x when nwg.y == 1.
|
| 77 |
+
let index = gid.x + gid.y * nwg.x * WG;
|
| 78 |
+
let total = params.tokenCount * TOP_K * INTER;
|
| 79 |
+
if (index >= total) {
|
| 80 |
+
return;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
let slot = index / INTER_DIV;
|
| 84 |
+
let local_token = slot / TOP_K;
|
| 85 |
+
let token = params.tokenOffset + local_token;
|
| 86 |
+
let i = index % INTER_DIV;
|
| 87 |
+
let expert = route_expert[token * TOP_K + slot % TOP_K];
|
| 88 |
+
|
| 89 |
+
{% if activation == "swiglu" %}
|
| 90 |
+
{% if swigluFusion == 0 %}
|
| 91 |
+
// swiglu_fusion 0: the two operands come from separate GEMMs, FC1 and FC3.
|
| 92 |
+
let value = swiglu(project_fc1(expert, i, token), project_fc3(expert, i, token));
|
| 93 |
+
{% elif swigluFusion == 1 %}
|
| 94 |
+
// swiglu_fusion 1: one fused FC1 whose row pairs are interleaved on each row of 2 * inter.
|
| 95 |
+
let value = swiglu(project_fc1(expert, i * 2u, token), project_fc1(expert, i * 2u + 1u, token));
|
| 96 |
+
{% else %}
|
| 97 |
+
// swiglu_fusion 2: one fused FC1 whose two halves are concatenated on each row.
|
| 98 |
+
let value = swiglu(project_fc1(expert, i, token), project_fc1(expert, INTER + i, token));
|
| 99 |
+
{% endif %}
|
| 100 |
+
{% else %}
|
| 101 |
+
let projected = project_fc1(expert, i, token);
|
| 102 |
+
{% if activation == "relu" %}
|
| 103 |
+
let activated = max(projected, 0.0);
|
| 104 |
+
{% elif activation == "gelu" %}
|
| 105 |
+
// The operator uses the tanh GELU approximation.
|
| 106 |
+
let activated = gelu_tanh(projected);
|
| 107 |
+
{% elif activation == "silu" %}
|
| 108 |
+
let activated = projected / (1.0 + exp(-projected));
|
| 109 |
+
{% else %}
|
| 110 |
+
let activated = projected;
|
| 111 |
+
{% endif %}
|
| 112 |
+
{% if hasFc3 %}
|
| 113 |
+
// SiLU with FC3 is the gated-MLP form: SiLU(FC1) multiplies the linear FC3 projection.
|
| 114 |
+
let value = activated * project_fc3(expert, i, token);
|
| 115 |
+
{% else %}
|
| 116 |
+
let value = activated;
|
| 117 |
+
{% endif %}
|
| 118 |
+
{% endif %}
|
| 119 |
+
|
| 120 |
+
hidden_act[(local_token * TOP_K + slot % TOP_K) * INTER + i] = value;
|
| 121 |
+
}
|
build/webgpu/moe-mix-stage.wgsl.jinja
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
+
|
| 3 |
+
// Routed sum for the grouped schedule. The grouped FC2 stage produces one projected row per
|
| 4 |
+
// routed SLOT because a token's slots are spread across different expert tiles; this pass
|
| 5 |
+
// applies each slot's routing weight and collapses the TOP_K slots into the token's output row.
|
| 6 |
+
// The expert's FC2 bias is already inside its slot's row, so it is scaled by that slot's weight
|
| 7 |
+
// exactly as the other schedules scale it.
|
| 8 |
+
const HIDDEN: u32 = {{ hidden }}u;
|
| 9 |
+
const TOP_K: u32 = {{ topK }}u;
|
| 10 |
+
const WG: u32 = {{ workgroupSize }}u;
|
| 11 |
+
|
| 12 |
+
@compute @workgroup_size(WG, 1, 1)
|
| 13 |
+
fn main(@builtin(global_invocation_id) gid: vec3<u32>,
|
| 14 |
+
@builtin(num_workgroups) nwg: vec3<u32>) {
|
| 15 |
+
// 2D-folded flat index: gid.y carries the high bits past the maxComputeWorkgroupsPerDimension
|
| 16 |
+
// workgroup-per-dimension dispatch limit. Reduces to gid.x when nwg.y == 1.
|
| 17 |
+
let index = gid.x + gid.y * nwg.x * WG;
|
| 18 |
+
let total = params.tokenCount * HIDDEN;
|
| 19 |
+
if (index >= total) {
|
| 20 |
+
return;
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
let local_token = index / HIDDEN;
|
| 24 |
+
let token = params.tokenOffset + local_token;
|
| 25 |
+
let out_col = index % HIDDEN;
|
| 26 |
+
|
| 27 |
+
var acc = 0.0;
|
| 28 |
+
for (var j = 0u; j < TOP_K; j = j + 1u) {
|
| 29 |
+
acc = acc + slot_out[(local_token * TOP_K + j) * HIDDEN + out_col] * route_mix[token * TOP_K + j];
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
output[token * HIDDEN + out_col] = acc;
|
| 33 |
+
}
|
build/webgpu/moe-output-gemv.wgsl.jinja
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
+
|
| 3 |
+
// FC2 projection and the routed sum, on the cooperative schedule. A workgroup owns ROWS output
|
| 4 |
+
// columns of one token and LANES lanes split the intermediate axis.
|
| 5 |
+
const HIDDEN: u32 = {{ hidden }}u;
|
| 6 |
+
const INTER: u32 = {{ inter }}u;
|
| 7 |
+
const TOP_K: u32 = {{ topK }}u;
|
| 8 |
+
const LANES: u32 = {{ decodeLanes }}u;
|
| 9 |
+
const ROWS: u32 = {{ decodeRows }}u;
|
| 10 |
+
|
| 11 |
+
{% macro rowlane_fold(arrays, lanes="LANES", lane="lane", slot="slot") %}
|
| 12 |
+
var n = {{ lanes }};
|
| 13 |
+
while (n > 1u) {
|
| 14 |
+
let half = (n + 1u) / 2u;
|
| 15 |
+
if ({{ lane }} + half < n) {
|
| 16 |
+
{% for a in arrays %}
|
| 17 |
+
{{ a }}[{{ slot }}] = {{ a }}[{{ slot }}] + {{ a }}[{{ slot }} + half];
|
| 18 |
+
{% endfor %}
|
| 19 |
+
}
|
| 20 |
+
workgroupBarrier();
|
| 21 |
+
n = half;
|
| 22 |
+
}
|
| 23 |
+
{%- endmacro %}
|
| 24 |
+
|
| 25 |
+
var<workgroup> partial: array<f32, {{ decodeLanes * decodeRows }}>;
|
| 26 |
+
|
| 27 |
+
@compute @workgroup_size(LANES, ROWS, 1)
|
| 28 |
+
fn main(@builtin(workgroup_id) wid: vec3<u32>,
|
| 29 |
+
@builtin(local_invocation_id) lid: vec3<u32>) {
|
| 30 |
+
let out_col = wid.x * ROWS + lid.y;
|
| 31 |
+
let lane = lid.x;
|
| 32 |
+
let local_token = wid.y;
|
| 33 |
+
let token = params.tokenOffset + local_token;
|
| 34 |
+
let in_range = out_col < HIDDEN;
|
| 35 |
+
|
| 36 |
+
var acc = 0.0;
|
| 37 |
+
if (in_range) {
|
| 38 |
+
// route_mix is uniform across a workgroup's lanes, so folding each slot's share into that
|
| 39 |
+
// slot's own partial here equals scaling the reduced sum, and leaves one
|
| 40 |
+
// cross-lane fold covering all TOP_K slots.
|
| 41 |
+
for (var j = 0u; j < TOP_K; j = j + 1u) {
|
| 42 |
+
let route_slot = token * TOP_K + j;
|
| 43 |
+
let expert = route_expert[route_slot];
|
| 44 |
+
let weight_base = (expert * HIDDEN + out_col) * INTER;
|
| 45 |
+
let act_base = (local_token * TOP_K + j) * INTER;
|
| 46 |
+
var part = 0.0;
|
| 47 |
+
for (var i = lane; i < INTER; i = i + LANES) {
|
| 48 |
+
part = part + hidden_act[act_base + i] * fc2_experts_weights[weight_base + i];
|
| 49 |
+
}
|
| 50 |
+
{% if hasFc2Bias %}
|
| 51 |
+
// The FC2 bias belongs to the expert, so it is added inside the expert's own contribution
|
| 52 |
+
// and then scaled by that expert's routing weight -- not once to the routed sum. One lane
|
| 53 |
+
// carries it so the fold adds it exactly once per slot.
|
| 54 |
+
if (lane == 0u) {
|
| 55 |
+
part = part + fc2_experts_bias[expert * HIDDEN + out_col];
|
| 56 |
+
}
|
| 57 |
+
{% endif %}
|
| 58 |
+
acc = acc + part * route_mix[route_slot];
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
let slot = lid.y * LANES + lane;
|
| 63 |
+
partial[slot] = acc;
|
| 64 |
+
workgroupBarrier();
|
| 65 |
+
{{ rowlane_fold(["partial"]) }}
|
| 66 |
+
|
| 67 |
+
if (lane == 0u && in_range) {
|
| 68 |
+
output[token * HIDDEN + out_col] = partial[lid.y * LANES];
|
| 69 |
+
}
|
| 70 |
+
}
|
build/webgpu/moe-output-grouped.wgsl.jinja
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
+
|
| 3 |
+
// FC2 projection on the grouped schedule, sharing the tile loop with the grouped FC1 stage.
|
| 4 |
+
// The reduction is the intermediate axis and the output width is the hidden axis, so the same
|
| 5 |
+
// expert-homogeneous tile of slots amortizes one staged FC2 weight tile.
|
| 6 |
+
//
|
| 7 |
+
// The result is written PER SLOT rather than per token: a token's routed slots land in
|
| 8 |
+
// different expert tiles, so nothing here can sum them. The mix stage that follows applies each
|
| 9 |
+
// slot's routing weight and collapses the K slots into the token's output row.
|
| 10 |
+
const HIDDEN: u32 = {{ hidden }}u;
|
| 11 |
+
const INTER: u32 = {{ inter }}u;
|
| 12 |
+
const MTILE: u32 = {{ groupTileM }}u;
|
| 13 |
+
const NTILE: u32 = {{ groupTileN }}u;
|
| 14 |
+
const KTILE: u32 = {{ groupTileK }}u;
|
| 15 |
+
const THREADS_SIDE: u32 = {{ groupThreads }}u;
|
| 16 |
+
const THREADS: u32 = THREADS_SIDE * THREADS_SIDE;
|
| 17 |
+
|
| 18 |
+
const KVEC: u32 = {{ groupTileKVec }}u;
|
| 19 |
+
{% macro stage_group_tiles(aLoad, bLoad, b2Load, kExtent, nExtent, guarded, bLoadVec4="", b2LoadVec4="", aLoadVec4="") %}
|
| 20 |
+
for (var idx = tid; idx < MTILE * KVEC; idx = idx + THREADS) {
|
| 21 |
+
let m = idx / KVEC;
|
| 22 |
+
let kb = (idx % KVEC) * 4u;
|
| 23 |
+
var a_vec: vec4<f32>;
|
| 24 |
+
{% if aLoadVec4 and not guarded %}
|
| 25 |
+
a_vec = {{ aLoadVec4 }};
|
| 26 |
+
{% else %}
|
| 27 |
+
{% for j in range(4) %}
|
| 28 |
+
{
|
| 29 |
+
let k = kb + {{ j }}u;
|
| 30 |
+
a_vec[{{ j }}] = {{ ("select(0.0, " ~ aLoad ~ ", k_base + k < " ~ kExtent ~ ")") if guarded else aLoad }};
|
| 31 |
+
}
|
| 32 |
+
{% endfor %}
|
| 33 |
+
{% endif %}
|
| 34 |
+
a_tile[idx] = a_vec;
|
| 35 |
+
}
|
| 36 |
+
for (var idx = tid; idx < NTILE * KVEC; idx = idx + THREADS) {
|
| 37 |
+
let n = idx / KVEC;
|
| 38 |
+
let kb = (idx % KVEC) * 4u;
|
| 39 |
+
let col = n_base + n;
|
| 40 |
+
{% if guarded %}
|
| 41 |
+
let col_live = col < {{ nExtent }};
|
| 42 |
+
{% endif %}
|
| 43 |
+
var b_vec: vec4<f32>;
|
| 44 |
+
{% if b2Load %}
|
| 45 |
+
var b2_vec: vec4<f32>;
|
| 46 |
+
{% endif %}
|
| 47 |
+
{% if bLoadVec4 and not guarded %}
|
| 48 |
+
b_vec = {{ bLoadVec4 }};
|
| 49 |
+
{% if b2Load %}
|
| 50 |
+
b2_vec = {{ b2LoadVec4 }};
|
| 51 |
+
{% endif %}
|
| 52 |
+
{% else %}
|
| 53 |
+
{% for j in range(4) %}
|
| 54 |
+
{
|
| 55 |
+
let k = kb + {{ j }}u;
|
| 56 |
+
{% if guarded %}
|
| 57 |
+
let live = col_live && k_base + k < {{ kExtent }};
|
| 58 |
+
{% endif %}
|
| 59 |
+
b_vec[{{ j }}] = {{ ("select(0.0, " ~ bLoad ~ ", live)") if guarded else bLoad }};
|
| 60 |
+
{% if b2Load %}
|
| 61 |
+
b2_vec[{{ j }}] = {{ ("select(0.0, " ~ b2Load ~ ", live)") if guarded else b2Load }};
|
| 62 |
+
{% endif %}
|
| 63 |
+
}
|
| 64 |
+
{% endfor %}
|
| 65 |
+
{% endif %}
|
| 66 |
+
b_tile[idx] = b_vec;
|
| 67 |
+
{% if b2Load %}
|
| 68 |
+
b2_tile[idx] = b2_vec;
|
| 69 |
+
{% endif %}
|
| 70 |
+
}
|
| 71 |
+
{%- endmacro %}
|
| 72 |
+
|
| 73 |
+
{% macro group_tile_loop(aLoad, bLoad, b2Load, kExtent, nExtent, regM, regN, bLoadVec4="", b2LoadVec4="", aLoadVec4="") %}
|
| 74 |
+
{% for r in range(regM) %}
|
| 75 |
+
{% for c in range(regN) %}
|
| 76 |
+
var acc_{{ r }}_{{ c }} = 0.0;
|
| 77 |
+
{% if b2Load %}
|
| 78 |
+
var acc2_{{ r }}_{{ c }} = 0.0;
|
| 79 |
+
{% endif %}
|
| 80 |
+
{% endfor %}
|
| 81 |
+
{% endfor %}
|
| 82 |
+
|
| 83 |
+
// A tile that lies wholly inside both extents needs no per-element bounds check, and
|
| 84 |
+
// that is every tile but the edges: the guards below exist for a reduction axis or an
|
| 85 |
+
// output width the tile size does not divide, yet the interior tiles were paying four
|
| 86 |
+
// comparisons and four selects per staged vec4 -- against 64 fused multiply-adds of
|
| 87 |
+
// actual work. Both arms stage identical values. The test is workgroup-uniform, so the
|
| 88 |
+
// barrier after it is still reached by every invocation together.
|
| 89 |
+
let n_full = n_base + NTILE <= {{ nExtent }};
|
| 90 |
+
var k_base = 0u;
|
| 91 |
+
loop {
|
| 92 |
+
if (k_base >= {{ kExtent }}) {
|
| 93 |
+
break;
|
| 94 |
+
}
|
| 95 |
+
if (n_full && k_base + KTILE <= {{ kExtent }}) {
|
| 96 |
+
{{ stage_group_tiles(aLoad, bLoad, b2Load, kExtent, nExtent, false, bLoadVec4, b2LoadVec4, aLoadVec4) }}
|
| 97 |
+
} else {
|
| 98 |
+
{{ stage_group_tiles(aLoad, bLoad, b2Load, kExtent, nExtent, true) }}
|
| 99 |
+
}
|
| 100 |
+
workgroupBarrier();
|
| 101 |
+
|
| 102 |
+
for (var kv = 0u; kv < KVEC; kv = kv + 1u) {
|
| 103 |
+
{% for r in range(regM) %}
|
| 104 |
+
let a{{ r }} = a_tile[(lid.y * {{ regM }}u + {{ r }}u) * KVEC + kv];
|
| 105 |
+
{% endfor %}
|
| 106 |
+
{% for c in range(regN) %}
|
| 107 |
+
let b{{ c }} = b_tile[(lid.x * {{ regN }}u + {{ c }}u) * KVEC + kv];
|
| 108 |
+
{% if b2Load %}
|
| 109 |
+
let s{{ c }} = b2_tile[(lid.x * {{ regN }}u + {{ c }}u) * KVEC + kv];
|
| 110 |
+
{% endif %}
|
| 111 |
+
{% endfor %}
|
| 112 |
+
{% for r in range(regM) %}
|
| 113 |
+
{% for c in range(regN) %}
|
| 114 |
+
acc_{{ r }}_{{ c }} = acc_{{ r }}_{{ c }} + dot(a{{ r }}, b{{ c }});
|
| 115 |
+
{% if b2Load %}
|
| 116 |
+
acc2_{{ r }}_{{ c }} = acc2_{{ r }}_{{ c }} + dot(a{{ r }}, s{{ c }});
|
| 117 |
+
{% endif %}
|
| 118 |
+
{% endfor %}
|
| 119 |
+
{% endfor %}
|
| 120 |
+
}
|
| 121 |
+
// Orders this step's tile reads before the next step overwrites them.
|
| 122 |
+
workgroupBarrier();
|
| 123 |
+
k_base = k_base + KTILE;
|
| 124 |
+
}
|
| 125 |
+
{%- endmacro %}
|
| 126 |
+
|
| 127 |
+
var<workgroup> row_slot: array<u32, {{ groupTileM }}>;
|
| 128 |
+
var<workgroup> a_tile: array<vec4<f32>, {{ groupTileM * groupTileKVec }}>;
|
| 129 |
+
var<workgroup> b_tile: array<vec4<f32>, {{ groupTileN * groupTileKVec }}>;
|
| 130 |
+
|
| 131 |
+
@compute @workgroup_size(THREADS_SIDE, THREADS_SIDE, 1)
|
| 132 |
+
fn main(@builtin(workgroup_id) wid: vec3<u32>,
|
| 133 |
+
@builtin(local_invocation_id) lid: vec3<u32>) {
|
| 134 |
+
let tile = wid.x;
|
| 135 |
+
if (tile >= tile_meta[0]) {
|
| 136 |
+
return;
|
| 137 |
+
}
|
| 138 |
+
let expert = tile_meta[1u + tile * 3u];
|
| 139 |
+
let slice_base = tile_meta[1u + tile * 3u + 1u];
|
| 140 |
+
let rows = tile_meta[1u + tile * 3u + 2u];
|
| 141 |
+
let n_base = wid.y * NTILE;
|
| 142 |
+
let tid = lid.y * THREADS_SIDE + lid.x;
|
| 143 |
+
|
| 144 |
+
for (var m = tid; m < MTILE; m = m + THREADS) {
|
| 145 |
+
// Rows past this tile's end park on row 0; their results are discarded at the store.
|
| 146 |
+
row_slot[m] = select(0u, slot_list[slice_base + m], m < rows);
|
| 147 |
+
}
|
| 148 |
+
workgroupBarrier();
|
| 149 |
+
{% macro at(buf, idx) %}{% if groupVec4 %}{{ buf }}[({{ idx }}) / 4u][({{ idx }}) % 4u]{% else %}{{ buf }}[{{ idx }}]{% endif %}{% endmacro %}
|
| 150 |
+
{% macro at4(buf, idx) %}{{ buf }}[({{ idx }}) / 4u]{% endmacro %}
|
| 151 |
+
{% set aPre = "row_slot[m] * INTER + k_base + " %}
|
| 152 |
+
{% set bPre = "(expert * HIDDEN + col) * INTER + k_base + " %}
|
| 153 |
+
{{ group_tile_loop(at("hidden_act", aPre ~ "k"),
|
| 154 |
+
at("fc2_experts_weights", bPre ~ "k"),
|
| 155 |
+
"", "INTER", "HIDDEN", regM, regN,
|
| 156 |
+
at4("fc2_experts_weights", bPre ~ "kb") if groupVec4 else "",
|
| 157 |
+
"",
|
| 158 |
+
at4("hidden_act", aPre ~ "kb") if groupVec4 else "") }}
|
| 159 |
+
|
| 160 |
+
{% for r in range(regM) %}
|
| 161 |
+
{% for c in range(regN) %}
|
| 162 |
+
{
|
| 163 |
+
let m = lid.y * {{ regM }}u + {{ r }}u;
|
| 164 |
+
let col = n_base + lid.x * {{ regN }}u + {{ c }}u;
|
| 165 |
+
if (m < rows && col < HIDDEN) {
|
| 166 |
+
{% if hasFc2Bias %}
|
| 167 |
+
// The FC2 bias belongs to the expert, so it joins this slot's own contribution before the
|
| 168 |
+
// mix stage scales it by that slot's routing weight.
|
| 169 |
+
slot_out[row_slot[m] * HIDDEN + col] = acc_{{ r }}_{{ c }} + fc2_experts_bias[expert * HIDDEN + col];
|
| 170 |
+
{% else %}
|
| 171 |
+
slot_out[row_slot[m] * HIDDEN + col] = acc_{{ r }}_{{ c }};
|
| 172 |
+
{% endif %}
|
| 173 |
+
}
|
| 174 |
+
}
|
| 175 |
+
{% endfor %}
|
| 176 |
+
{% endfor %}
|
| 177 |
+
}
|
build/webgpu/moe-output-stage.wgsl.jinja
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
+
|
| 3 |
+
// FC2 projection and the routed sum. One thread owns one output column of one token and walks
|
| 4 |
+
// every routed slot, so the per-slot expert weight is applied to that slot's own projection.
|
| 5 |
+
const HIDDEN: u32 = {{ hidden }}u;
|
| 6 |
+
const INTER: u32 = {{ inter }}u;
|
| 7 |
+
const TOP_K: u32 = {{ topK }}u;
|
| 8 |
+
const WG: u32 = {{ workgroupSize }}u;
|
| 9 |
+
|
| 10 |
+
@compute @workgroup_size(WG, 1, 1)
|
| 11 |
+
fn main(@builtin(global_invocation_id) gid: vec3<u32>,
|
| 12 |
+
@builtin(num_workgroups) nwg: vec3<u32>) {
|
| 13 |
+
// 2D-folded flat index: gid.y carries the high bits past the maxComputeWorkgroupsPerDimension
|
| 14 |
+
// workgroup-per-dimension dispatch limit. Reduces to gid.x when nwg.y == 1.
|
| 15 |
+
let index = gid.x + gid.y * nwg.x * WG;
|
| 16 |
+
let total = params.tokenCount * HIDDEN;
|
| 17 |
+
if (index >= total) {
|
| 18 |
+
return;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
let local_token = index / HIDDEN;
|
| 22 |
+
let token = params.tokenOffset + local_token;
|
| 23 |
+
let out_col = index % HIDDEN;
|
| 24 |
+
|
| 25 |
+
var acc = 0.0;
|
| 26 |
+
for (var j = 0u; j < TOP_K; j = j + 1u) {
|
| 27 |
+
let slot = token * TOP_K + j;
|
| 28 |
+
let expert = route_expert[slot];
|
| 29 |
+
let weight_base = (expert * HIDDEN + out_col) * INTER;
|
| 30 |
+
let act_base = (local_token * TOP_K + j) * INTER;
|
| 31 |
+
var part = 0.0;
|
| 32 |
+
for (var i: u32 = 0u; i < INTER; i = i + 1u) {
|
| 33 |
+
part = part + hidden_act[act_base + i] * fc2_experts_weights[weight_base + i];
|
| 34 |
+
}
|
| 35 |
+
{% if hasFc2Bias %}
|
| 36 |
+
// The FC2 bias belongs to the expert, so it is added inside the expert's own contribution
|
| 37 |
+
// and then scaled by that expert's routing weight -- not once to the routed sum.
|
| 38 |
+
part = part + fc2_experts_bias[expert * HIDDEN + out_col];
|
| 39 |
+
{% endif %}
|
| 40 |
+
acc = acc + part * route_mix[slot];
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
output[token * HIDDEN + out_col] = acc;
|
| 44 |
+
}
|
build/webgpu/moe-route-stage.wgsl.jinja
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
+
|
| 3 |
+
// One thread per token applies softmax to the router logits, selects TOP_K
|
| 4 |
+
// experts, and writes their optionally renormalized probabilities. Selection is
|
| 5 |
+
// O(TOP_K * EXPERTS) with no scratch. Equal probabilities choose the higher
|
| 6 |
+
// expert index.
|
| 7 |
+
const TOKENS: u32 = {{ tokens }}u;
|
| 8 |
+
const EXPERTS: u32 = {{ experts }}u;
|
| 9 |
+
const TOP_K: u32 = {{ topK }}u;
|
| 10 |
+
const WG: u32 = {{ workgroupSize }}u;
|
| 11 |
+
|
| 12 |
+
@compute @workgroup_size(WG, 1, 1)
|
| 13 |
+
fn main(@builtin(global_invocation_id) gid: vec3<u32>,
|
| 14 |
+
@builtin(num_workgroups) nwg: vec3<u32>) {
|
| 15 |
+
// gid.y carries the high bits past the per-dimension dispatch limit.
|
| 16 |
+
let token = gid.x + gid.y * nwg.x * WG;
|
| 17 |
+
if (token >= TOKENS) {
|
| 18 |
+
return;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
let router_base = token * EXPERTS;
|
| 22 |
+
var max_logit = router_probs[router_base];
|
| 23 |
+
for (var e = 1u; e < EXPERTS; e = e + 1u) {
|
| 24 |
+
max_logit = max(max_logit, router_probs[router_base + e]);
|
| 25 |
+
}
|
| 26 |
+
var sum_exp = 0.0;
|
| 27 |
+
for (var e = 0u; e < EXPERTS; e = e + 1u) {
|
| 28 |
+
sum_exp = sum_exp + exp(router_probs[router_base + e] - max_logit);
|
| 29 |
+
}
|
| 30 |
+
let inv_sum_exp = 1.0 / sum_exp;
|
| 31 |
+
|
| 32 |
+
var experts_taken: array<u32, TOP_K>;
|
| 33 |
+
var weights: array<f32, TOP_K>;
|
| 34 |
+
for (var j = 0u; j < TOP_K; j = j + 1u) {
|
| 35 |
+
// EXPERTS is the sentinel. TOP_K <= EXPERTS guarantees that every pass
|
| 36 |
+
// finds an untaken expert.
|
| 37 |
+
var best_expert = EXPERTS;
|
| 38 |
+
var best_weight = 0.0;
|
| 39 |
+
for (var e = 0u; e < EXPERTS; e = e + 1u) {
|
| 40 |
+
var taken = false;
|
| 41 |
+
for (var p = 0u; p < j; p = p + 1u) {
|
| 42 |
+
if (experts_taken[p] == e) {
|
| 43 |
+
taken = true;
|
| 44 |
+
}
|
| 45 |
+
}
|
| 46 |
+
if (!taken) {
|
| 47 |
+
let candidate = exp(router_probs[router_base + e] - max_logit) * inv_sum_exp;
|
| 48 |
+
if (best_expert == EXPERTS || candidate >= best_weight) {
|
| 49 |
+
best_expert = e;
|
| 50 |
+
best_weight = candidate;
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
experts_taken[j] = best_expert;
|
| 55 |
+
weights[j] = best_weight;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
// Optionally rescale selected probabilities to sum to one. At K == 1 the
|
| 59 |
+
// single probability becomes exactly one.
|
| 60 |
+
if (params.normalizeRoutingWeights != 0u) {
|
| 61 |
+
var sum = 0.0;
|
| 62 |
+
for (var j = 0u; j < TOP_K; j = j + 1u) {
|
| 63 |
+
sum = sum + weights[j];
|
| 64 |
+
}
|
| 65 |
+
if (sum != 0.0) {
|
| 66 |
+
for (var j = 0u; j < TOP_K; j = j + 1u) {
|
| 67 |
+
weights[j] = weights[j] / sum;
|
| 68 |
+
}
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
for (var j = 0u; j < TOP_K; j = j + 1u) {
|
| 73 |
+
route_expert[token * TOP_K + j] = experts_taken[j];
|
| 74 |
+
route_mix[token * TOP_K + j] = weights[j];
|
| 75 |
+
}
|
| 76 |
+
}
|
build/webgpu/test.json
ADDED
|
@@ -0,0 +1,2001 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"op": "com.microsoft.MoE",
|
| 3 |
+
"cases": [
|
| 4 |
+
{
|
| 5 |
+
"name": "relu_top1_no_bias",
|
| 6 |
+
"provenance": {
|
| 7 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 8 |
+
"test": "default activation_type (relu), one expert per token",
|
| 9 |
+
"notes": "The schema's default activation and nothing optional: no biases, no FC3. Every other case is a delta from this one."
|
| 10 |
+
},
|
| 11 |
+
"attrs": { "normalize_routing_weights": 1 },
|
| 12 |
+
"inputs": {
|
| 13 |
+
"inputT": {
|
| 14 |
+
"dtype": "float32",
|
| 15 |
+
"shape": [3, 4],
|
| 16 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 17 |
+
},
|
| 18 |
+
"routerT": {
|
| 19 |
+
"dtype": "float32",
|
| 20 |
+
"shape": [3, 3],
|
| 21 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 22 |
+
},
|
| 23 |
+
"fc1T": {
|
| 24 |
+
"dtype": "float32",
|
| 25 |
+
"shape": [3, 5, 4],
|
| 26 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 27 |
+
},
|
| 28 |
+
"fc2T": {
|
| 29 |
+
"dtype": "float32",
|
| 30 |
+
"shape": [3, 4, 5],
|
| 31 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 32 |
+
}
|
| 33 |
+
},
|
| 34 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
"name": "gelu_top1_fc1_bias",
|
| 38 |
+
"provenance": {
|
| 39 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 40 |
+
"test": "activation_type gelu with an FC1 bias",
|
| 41 |
+
"notes": "The tanh-approximate GELU used by ONNX Runtime's MoE kernel, over an FC1 that carries its own per-expert bias. The bias joins the projection before the activation, which is what separates it from a bias on the output side."
|
| 42 |
+
},
|
| 43 |
+
"attrs": { "k": 1, "activation_type": "gelu", "normalize_routing_weights": 0 },
|
| 44 |
+
"inputs": {
|
| 45 |
+
"inputT": {
|
| 46 |
+
"dtype": "float32",
|
| 47 |
+
"shape": [3, 4],
|
| 48 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 49 |
+
},
|
| 50 |
+
"routerT": {
|
| 51 |
+
"dtype": "float32",
|
| 52 |
+
"shape": [3, 3],
|
| 53 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 54 |
+
},
|
| 55 |
+
"fc1T": {
|
| 56 |
+
"dtype": "float32",
|
| 57 |
+
"shape": [3, 5, 4],
|
| 58 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 59 |
+
},
|
| 60 |
+
"fc1BiasT": {
|
| 61 |
+
"dtype": "float32",
|
| 62 |
+
"shape": [3, 5],
|
| 63 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.13, "scale": 0.25 }
|
| 64 |
+
},
|
| 65 |
+
"fc2T": {
|
| 66 |
+
"dtype": "float32",
|
| 67 |
+
"shape": [3, 4, 5],
|
| 68 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 69 |
+
}
|
| 70 |
+
},
|
| 71 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
"name": "silu_topk2_fc2_bias",
|
| 75 |
+
"provenance": {
|
| 76 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 77 |
+
"test": "activation_type silu at k = 2 with an FC2 bias",
|
| 78 |
+
"notes": "The FC2 bias belongs to the expert, so at k = 2 each selected expert contributes its own bias scaled by its own routing weight. Adding it once to the routed sum instead would be wrong by the difference of the two experts' biases."
|
| 79 |
+
},
|
| 80 |
+
"attrs": { "k": 2, "activation_type": "silu", "normalize_routing_weights": 1 },
|
| 81 |
+
"inputs": {
|
| 82 |
+
"inputT": {
|
| 83 |
+
"dtype": "float32",
|
| 84 |
+
"shape": [3, 4],
|
| 85 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 86 |
+
},
|
| 87 |
+
"routerT": {
|
| 88 |
+
"dtype": "float32",
|
| 89 |
+
"shape": [3, 3],
|
| 90 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 91 |
+
},
|
| 92 |
+
"fc1T": {
|
| 93 |
+
"dtype": "float32",
|
| 94 |
+
"shape": [3, 5, 4],
|
| 95 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 96 |
+
},
|
| 97 |
+
"fc2T": {
|
| 98 |
+
"dtype": "float32",
|
| 99 |
+
"shape": [3, 4, 5],
|
| 100 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 101 |
+
},
|
| 102 |
+
"fc2BiasT": {
|
| 103 |
+
"dtype": "float32",
|
| 104 |
+
"shape": [3, 4],
|
| 105 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.43, "cosStep": 0.17, "scale": 0.2 }
|
| 106 |
+
}
|
| 107 |
+
},
|
| 108 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 109 |
+
},
|
| 110 |
+
{
|
| 111 |
+
"name": "silu_gate_fc3_no_bias",
|
| 112 |
+
"provenance": {
|
| 113 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 114 |
+
"test": "activation_type silu with FC3 as a multiplicative linear projection",
|
| 115 |
+
"notes": "The pinned CUDA provider's separate FC3 gated-MLP form computes the FC3 projection times SiLU of the FC1 projection."
|
| 116 |
+
},
|
| 117 |
+
"attrs": { "k": 1, "activation_type": "silu", "normalize_routing_weights": 0 },
|
| 118 |
+
"inputs": {
|
| 119 |
+
"inputT": {
|
| 120 |
+
"dtype": "float32",
|
| 121 |
+
"shape": [3, 4],
|
| 122 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 123 |
+
},
|
| 124 |
+
"routerT": {
|
| 125 |
+
"dtype": "float32",
|
| 126 |
+
"shape": [3, 3],
|
| 127 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 128 |
+
},
|
| 129 |
+
"fc1T": {
|
| 130 |
+
"dtype": "float32",
|
| 131 |
+
"shape": [3, 5, 4],
|
| 132 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 133 |
+
},
|
| 134 |
+
"fc2T": {
|
| 135 |
+
"dtype": "float32",
|
| 136 |
+
"shape": [3, 4, 5],
|
| 137 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 138 |
+
},
|
| 139 |
+
"fc3T": {
|
| 140 |
+
"dtype": "float32",
|
| 141 |
+
"shape": [3, 5, 4],
|
| 142 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.15 }
|
| 143 |
+
}
|
| 144 |
+
},
|
| 145 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 146 |
+
},
|
| 147 |
+
{
|
| 148 |
+
"name": "silu_gate_fc3_every_bias",
|
| 149 |
+
"provenance": {
|
| 150 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 151 |
+
"test": "all three optional biases present at once",
|
| 152 |
+
"notes": "FC1, FC2 and FC3 biases together on the provider-defined SiLU gated path."
|
| 153 |
+
},
|
| 154 |
+
"attrs": { "k": 2, "activation_type": "silu", "normalize_routing_weights": 1 },
|
| 155 |
+
"inputs": {
|
| 156 |
+
"inputT": {
|
| 157 |
+
"dtype": "float32",
|
| 158 |
+
"shape": [3, 4],
|
| 159 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 160 |
+
},
|
| 161 |
+
"routerT": {
|
| 162 |
+
"dtype": "float32",
|
| 163 |
+
"shape": [3, 3],
|
| 164 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 165 |
+
},
|
| 166 |
+
"fc1T": {
|
| 167 |
+
"dtype": "float32",
|
| 168 |
+
"shape": [3, 5, 4],
|
| 169 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 170 |
+
},
|
| 171 |
+
"fc1BiasT": {
|
| 172 |
+
"dtype": "float32",
|
| 173 |
+
"shape": [3, 5],
|
| 174 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.13, "scale": 0.25 }
|
| 175 |
+
},
|
| 176 |
+
"fc2T": {
|
| 177 |
+
"dtype": "float32",
|
| 178 |
+
"shape": [3, 4, 5],
|
| 179 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 180 |
+
},
|
| 181 |
+
"fc2BiasT": {
|
| 182 |
+
"dtype": "float32",
|
| 183 |
+
"shape": [3, 4],
|
| 184 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.43, "cosStep": 0.17, "scale": 0.2 }
|
| 185 |
+
},
|
| 186 |
+
"fc3T": {
|
| 187 |
+
"dtype": "float32",
|
| 188 |
+
"shape": [3, 5, 4],
|
| 189 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.15 }
|
| 190 |
+
},
|
| 191 |
+
"fc3BiasT": {
|
| 192 |
+
"dtype": "float32",
|
| 193 |
+
"shape": [3, 5],
|
| 194 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.23, "scale": 0.2 }
|
| 195 |
+
}
|
| 196 |
+
},
|
| 197 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"name": "swiglu_fusion2_top1",
|
| 201 |
+
"provenance": {
|
| 202 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 203 |
+
"test": "swiglu_fusion 2 (fused, concatenated halves)",
|
| 204 |
+
"notes": "One fused FC1 whose row block holds the gate half then the linear half. inter_size is the FC1 row count halved, which is what fusion_size 2 means in the schema's shape formula."
|
| 205 |
+
},
|
| 206 |
+
"attrs": {
|
| 207 |
+
"k": 1,
|
| 208 |
+
"activation_type": "swiglu",
|
| 209 |
+
"swiglu_fusion": 2,
|
| 210 |
+
"normalize_routing_weights": 1,
|
| 211 |
+
"activation_alpha": 1.702,
|
| 212 |
+
"activation_beta": 0.05
|
| 213 |
+
},
|
| 214 |
+
"inputs": {
|
| 215 |
+
"inputT": {
|
| 216 |
+
"dtype": "float32",
|
| 217 |
+
"shape": [3, 4],
|
| 218 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.33, "scale": 0.5 }
|
| 219 |
+
},
|
| 220 |
+
"routerT": {
|
| 221 |
+
"dtype": "float32",
|
| 222 |
+
"shape": [3, 3],
|
| 223 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.41, "cosStep": 0.23, "scale": 0.7 }
|
| 224 |
+
},
|
| 225 |
+
"fc1T": {
|
| 226 |
+
"dtype": "float32",
|
| 227 |
+
"shape": [3, 6, 4],
|
| 228 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 229 |
+
},
|
| 230 |
+
"fc2T": {
|
| 231 |
+
"dtype": "float32",
|
| 232 |
+
"shape": [3, 4, 3],
|
| 233 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 234 |
+
}
|
| 235 |
+
},
|
| 236 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 237 |
+
},
|
| 238 |
+
{
|
| 239 |
+
"name": "swiglu_fusion1_interleaved_topk2",
|
| 240 |
+
"provenance": {
|
| 241 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 242 |
+
"test": "swiglu_fusion 1 (fused, interleaved rows)",
|
| 243 |
+
"notes": "The same fused FC1 as fusion 2 but with the two operands interleaved: lane i reads rows 2i and 2i+1 rather than i and inter+i. Reading the concatenated layout here still lands on the right gate row for lane 0 and on the wrong linear row for it, and on the wrong row for both operands of every later lane."
|
| 244 |
+
},
|
| 245 |
+
"attrs": {
|
| 246 |
+
"k": 2,
|
| 247 |
+
"activation_type": "swiglu",
|
| 248 |
+
"swiglu_fusion": 1,
|
| 249 |
+
"normalize_routing_weights": 1,
|
| 250 |
+
"activation_alpha": 1.702,
|
| 251 |
+
"activation_beta": 0.05
|
| 252 |
+
},
|
| 253 |
+
"inputs": {
|
| 254 |
+
"inputT": {
|
| 255 |
+
"dtype": "float32",
|
| 256 |
+
"shape": [4, 4],
|
| 257 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.33, "scale": 0.5 }
|
| 258 |
+
},
|
| 259 |
+
"routerT": {
|
| 260 |
+
"dtype": "float32",
|
| 261 |
+
"shape": [4, 3],
|
| 262 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.41, "cosStep": 0.23, "scale": 0.7 }
|
| 263 |
+
},
|
| 264 |
+
"fc1T": {
|
| 265 |
+
"dtype": "float32",
|
| 266 |
+
"shape": [3, 6, 4],
|
| 267 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 268 |
+
},
|
| 269 |
+
"fc1BiasT": {
|
| 270 |
+
"dtype": "float32",
|
| 271 |
+
"shape": [3, 6],
|
| 272 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.13, "scale": 0.25 }
|
| 273 |
+
},
|
| 274 |
+
"fc2T": {
|
| 275 |
+
"dtype": "float32",
|
| 276 |
+
"shape": [3, 4, 3],
|
| 277 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 278 |
+
}
|
| 279 |
+
},
|
| 280 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [4, 4], "tolerance": 0.00002 } }
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"name": "swiglu_fusion0_separate_fc3",
|
| 284 |
+
"provenance": {
|
| 285 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 286 |
+
"test": "swiglu_fusion 0 (two unfused GEMMs)",
|
| 287 |
+
"notes": "With the GEMMs unfused the SwiGLU operands come from separate FC1 and FC3 tensors, so fusion_size is 1 and inter_size is the full FC1 row count. FC3 is required in this form and rejected in the fused ones."
|
| 288 |
+
},
|
| 289 |
+
"attrs": {
|
| 290 |
+
"k": 1,
|
| 291 |
+
"activation_type": "swiglu",
|
| 292 |
+
"swiglu_fusion": 0,
|
| 293 |
+
"normalize_routing_weights": 0,
|
| 294 |
+
"activation_alpha": 1.702,
|
| 295 |
+
"activation_beta": 0.05
|
| 296 |
+
},
|
| 297 |
+
"inputs": {
|
| 298 |
+
"inputT": {
|
| 299 |
+
"dtype": "float32",
|
| 300 |
+
"shape": [3, 4],
|
| 301 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 302 |
+
},
|
| 303 |
+
"routerT": {
|
| 304 |
+
"dtype": "float32",
|
| 305 |
+
"shape": [3, 3],
|
| 306 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 307 |
+
},
|
| 308 |
+
"fc1T": {
|
| 309 |
+
"dtype": "float32",
|
| 310 |
+
"shape": [3, 5, 4],
|
| 311 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 312 |
+
},
|
| 313 |
+
"fc2T": {
|
| 314 |
+
"dtype": "float32",
|
| 315 |
+
"shape": [3, 4, 5],
|
| 316 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 317 |
+
},
|
| 318 |
+
"fc3T": {
|
| 319 |
+
"dtype": "float32",
|
| 320 |
+
"shape": [3, 5, 4],
|
| 321 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.15 }
|
| 322 |
+
}
|
| 323 |
+
},
|
| 324 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 325 |
+
},
|
| 326 |
+
{
|
| 327 |
+
"name": "swiglu_fusion2_limit_clamped",
|
| 328 |
+
"provenance": {
|
| 329 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 330 |
+
"test": "swiglu_limit clamping both operands",
|
| 331 |
+
"notes": "swiglu_limit clamps the gate operand from above and the linear operand into [-limit, limit] before the product. The limit is small enough here that it actually binds; when the attribute is absent no clamp is applied at all."
|
| 332 |
+
},
|
| 333 |
+
"attrs": {
|
| 334 |
+
"k": 1,
|
| 335 |
+
"activation_type": "swiglu",
|
| 336 |
+
"swiglu_fusion": 2,
|
| 337 |
+
"normalize_routing_weights": 1,
|
| 338 |
+
"activation_alpha": 1.702,
|
| 339 |
+
"activation_beta": 0.05,
|
| 340 |
+
"swiglu_limit": 0.35
|
| 341 |
+
},
|
| 342 |
+
"inputs": {
|
| 343 |
+
"inputT": {
|
| 344 |
+
"dtype": "float32",
|
| 345 |
+
"shape": [3, 4],
|
| 346 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.33, "scale": 0.5 }
|
| 347 |
+
},
|
| 348 |
+
"routerT": {
|
| 349 |
+
"dtype": "float32",
|
| 350 |
+
"shape": [3, 3],
|
| 351 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.41, "cosStep": 0.23, "scale": 0.7 }
|
| 352 |
+
},
|
| 353 |
+
"fc1T": {
|
| 354 |
+
"dtype": "float32",
|
| 355 |
+
"shape": [3, 6, 4],
|
| 356 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 357 |
+
},
|
| 358 |
+
"fc2T": {
|
| 359 |
+
"dtype": "float32",
|
| 360 |
+
"shape": [3, 4, 3],
|
| 361 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 362 |
+
},
|
| 363 |
+
"fc2BiasT": {
|
| 364 |
+
"dtype": "float32",
|
| 365 |
+
"shape": [3, 4],
|
| 366 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.43, "cosStep": 0.17, "scale": 0.2 }
|
| 367 |
+
}
|
| 368 |
+
},
|
| 369 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 370 |
+
},
|
| 371 |
+
{
|
| 372 |
+
"name": "rank3_batched_relu",
|
| 373 |
+
"provenance": {
|
| 374 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 375 |
+
"test": "3D input (batch, sequence, hidden)",
|
| 376 |
+
"notes": "num_tokens is the product of every leading dimension, so a [1, 3, 4] input routes exactly like the [3, 4] case while the output keeps the 3D shape."
|
| 377 |
+
},
|
| 378 |
+
"attrs": { "k": 1, "normalize_routing_weights": 1 },
|
| 379 |
+
"inputs": {
|
| 380 |
+
"inputT": {
|
| 381 |
+
"dtype": "float32",
|
| 382 |
+
"shape": [1, 3, 4],
|
| 383 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 384 |
+
},
|
| 385 |
+
"routerT": {
|
| 386 |
+
"dtype": "float32",
|
| 387 |
+
"shape": [3, 3],
|
| 388 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 389 |
+
},
|
| 390 |
+
"fc1T": {
|
| 391 |
+
"dtype": "float32",
|
| 392 |
+
"shape": [3, 5, 4],
|
| 393 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 394 |
+
},
|
| 395 |
+
"fc2T": {
|
| 396 |
+
"dtype": "float32",
|
| 397 |
+
"shape": [3, 4, 5],
|
| 398 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 399 |
+
}
|
| 400 |
+
},
|
| 401 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [1, 3, 4], "tolerance": 0.00002 } }
|
| 402 |
+
},
|
| 403 |
+
{
|
| 404 |
+
"name": "topk_equals_expert_count",
|
| 405 |
+
"provenance": {
|
| 406 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 407 |
+
"test": "k equal to the expert count",
|
| 408 |
+
"notes": "Every expert is selected for every token, which is the upper bound the contract allows and the case where the router's taken-exclusion has to visit every index without repeating one."
|
| 409 |
+
},
|
| 410 |
+
"attrs": { "k": 3, "normalize_routing_weights": 1 },
|
| 411 |
+
"inputs": {
|
| 412 |
+
"inputT": {
|
| 413 |
+
"dtype": "float32",
|
| 414 |
+
"shape": [3, 4],
|
| 415 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31, "scale": 0.5 }
|
| 416 |
+
},
|
| 417 |
+
"routerT": {
|
| 418 |
+
"dtype": "float32",
|
| 419 |
+
"shape": [3, 3],
|
| 420 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 0.7 }
|
| 421 |
+
},
|
| 422 |
+
"fc1T": {
|
| 423 |
+
"dtype": "float32",
|
| 424 |
+
"shape": [3, 5, 4],
|
| 425 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 426 |
+
},
|
| 427 |
+
"fc2T": {
|
| 428 |
+
"dtype": "float32",
|
| 429 |
+
"shape": [3, 4, 5],
|
| 430 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 431 |
+
}
|
| 432 |
+
},
|
| 433 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 434 |
+
},
|
| 435 |
+
{
|
| 436 |
+
"name": "empty_tokens_zero_dim",
|
| 437 |
+
"provenance": {
|
| 438 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 439 |
+
"test": "zero-token input",
|
| 440 |
+
"notes": "A zero-length token axis: every stage dispatches nothing and the output is empty. The route scratch is still allocated at one element so the binding stays well-formed."
|
| 441 |
+
},
|
| 442 |
+
"attrs": { "k": 1, "normalize_routing_weights": 1 },
|
| 443 |
+
"inputs": {
|
| 444 |
+
"inputT": { "dtype": "float32", "shape": [0, 4], "data": { "kind": "values", "values": [] } },
|
| 445 |
+
"routerT": { "dtype": "float32", "shape": [0, 3], "data": { "kind": "values", "values": [] } },
|
| 446 |
+
"fc1T": {
|
| 447 |
+
"dtype": "float32",
|
| 448 |
+
"shape": [3, 5, 4],
|
| 449 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 450 |
+
},
|
| 451 |
+
"fc2T": {
|
| 452 |
+
"dtype": "float32",
|
| 453 |
+
"shape": [3, 4, 5],
|
| 454 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 455 |
+
}
|
| 456 |
+
},
|
| 457 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [0, 4], "tolerance": 0 } }
|
| 458 |
+
},
|
| 459 |
+
{
|
| 460 |
+
"name": "gelu_fc1_bias_fc2_bias",
|
| 461 |
+
"provenance": {
|
| 462 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 463 |
+
"test": "com.microsoft.MoE optional-input combination",
|
| 464 |
+
"notes": "Each optional input changes the binding layout, so every combination of FC1 bias, FC3 (with or without its own bias) and FC2 bias is a distinct variant. This case is the one that selects fc1bias / no FC3 / fc2bias; without it that variant would ship unexercised."
|
| 465 |
+
},
|
| 466 |
+
"attrs": { "k": 1, "activation_type": "gelu", "normalize_routing_weights": 0 },
|
| 467 |
+
"inputs": {
|
| 468 |
+
"inputT": {
|
| 469 |
+
"dtype": "float32",
|
| 470 |
+
"shape": [3, 4],
|
| 471 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.31, "scale": 0.5 }
|
| 472 |
+
},
|
| 473 |
+
"routerT": {
|
| 474 |
+
"dtype": "float32",
|
| 475 |
+
"shape": [3, 3],
|
| 476 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.21, "scale": 0.7 }
|
| 477 |
+
},
|
| 478 |
+
"fc1T": {
|
| 479 |
+
"dtype": "float32",
|
| 480 |
+
"shape": [3, 5, 4],
|
| 481 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 482 |
+
},
|
| 483 |
+
"fc1BiasT": {
|
| 484 |
+
"dtype": "float32",
|
| 485 |
+
"shape": [3, 5],
|
| 486 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.13, "scale": 0.25 }
|
| 487 |
+
},
|
| 488 |
+
"fc2T": {
|
| 489 |
+
"dtype": "float32",
|
| 490 |
+
"shape": [3, 4, 5],
|
| 491 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 492 |
+
},
|
| 493 |
+
"fc2BiasT": {
|
| 494 |
+
"dtype": "float32",
|
| 495 |
+
"shape": [3, 4],
|
| 496 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.43, "cosStep": 0.17, "scale": 0.2 }
|
| 497 |
+
}
|
| 498 |
+
},
|
| 499 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 500 |
+
},
|
| 501 |
+
{
|
| 502 |
+
"name": "deep_reduction_silu_gate_fc3_fc2_bias",
|
| 503 |
+
"provenance": {
|
| 504 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 505 |
+
"test": "com.microsoft.MoE optional-input combination",
|
| 506 |
+
"notes": "This optional-input layout uses a 128-wide reduction so the cooperative GEMV schedule exercises SiLU with a separate, unbiased FC3 projection and FC2 bias."
|
| 507 |
+
},
|
| 508 |
+
"attrs": { "k": 2, "activation_type": "silu", "normalize_routing_weights": 1 },
|
| 509 |
+
"inputs": {
|
| 510 |
+
"inputT": {
|
| 511 |
+
"dtype": "float32",
|
| 512 |
+
"shape": [2, 128],
|
| 513 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.21, "cosStep": 0.31, "scale": 0.5 }
|
| 514 |
+
},
|
| 515 |
+
"routerT": {
|
| 516 |
+
"dtype": "float32",
|
| 517 |
+
"shape": [2, 3],
|
| 518 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.23, "scale": 0.7 }
|
| 519 |
+
},
|
| 520 |
+
"fc1T": {
|
| 521 |
+
"dtype": "float32",
|
| 522 |
+
"shape": [3, 128, 128],
|
| 523 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 524 |
+
},
|
| 525 |
+
"fc2T": {
|
| 526 |
+
"dtype": "float32",
|
| 527 |
+
"shape": [3, 128, 128],
|
| 528 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 529 |
+
},
|
| 530 |
+
"fc2BiasT": {
|
| 531 |
+
"dtype": "float32",
|
| 532 |
+
"shape": [3, 128],
|
| 533 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.43, "cosStep": 0.17, "scale": 0.2 }
|
| 534 |
+
},
|
| 535 |
+
"fc3T": {
|
| 536 |
+
"dtype": "float32",
|
| 537 |
+
"shape": [3, 128, 128],
|
| 538 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.15 }
|
| 539 |
+
}
|
| 540 |
+
},
|
| 541 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 542 |
+
},
|
| 543 |
+
{
|
| 544 |
+
"name": "grouped_prefill_silu_gate_fc3_bias_only",
|
| 545 |
+
"provenance": {
|
| 546 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 547 |
+
"test": "com.microsoft.MoE optional-input combination",
|
| 548 |
+
"notes": "This optional-input layout supplies enough routed slots for the expert-grouped schedule to exercise SiLU with a separately biased FC3 projection and no FC2 bias."
|
| 549 |
+
},
|
| 550 |
+
"attrs": { "k": 1, "activation_type": "silu", "normalize_routing_weights": 0 },
|
| 551 |
+
"inputs": {
|
| 552 |
+
"inputT": {
|
| 553 |
+
"dtype": "float32",
|
| 554 |
+
"shape": [96, 32],
|
| 555 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.23, "cosStep": 0.31, "scale": 0.5 }
|
| 556 |
+
},
|
| 557 |
+
"routerT": {
|
| 558 |
+
"dtype": "float32",
|
| 559 |
+
"shape": [96, 3],
|
| 560 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.25, "scale": 0.7 }
|
| 561 |
+
},
|
| 562 |
+
"fc1T": {
|
| 563 |
+
"dtype": "float32",
|
| 564 |
+
"shape": [3, 32, 32],
|
| 565 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 566 |
+
},
|
| 567 |
+
"fc2T": {
|
| 568 |
+
"dtype": "float32",
|
| 569 |
+
"shape": [3, 32, 32],
|
| 570 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 571 |
+
},
|
| 572 |
+
"fc3T": {
|
| 573 |
+
"dtype": "float32",
|
| 574 |
+
"shape": [3, 32, 32],
|
| 575 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.15 }
|
| 576 |
+
},
|
| 577 |
+
"fc3BiasT": {
|
| 578 |
+
"dtype": "float32",
|
| 579 |
+
"shape": [3, 32],
|
| 580 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.23, "scale": 0.2 }
|
| 581 |
+
}
|
| 582 |
+
},
|
| 583 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 32], "tolerance": 0.00002 } }
|
| 584 |
+
},
|
| 585 |
+
{
|
| 586 |
+
"name": "silu_gate_fc3_bias_fc2_bias",
|
| 587 |
+
"provenance": {
|
| 588 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 589 |
+
"test": "com.microsoft.MoE optional-input combination",
|
| 590 |
+
"notes": "Each optional input changes the binding layout, so every combination of FC1 bias, FC3 (with or without its own bias) and FC2 bias is a distinct variant. This case is the one that selects no FC1 bias / FC3 with bias / fc2bias; without it that variant would ship unexercised."
|
| 591 |
+
},
|
| 592 |
+
"attrs": { "k": 2, "activation_type": "silu", "normalize_routing_weights": 1 },
|
| 593 |
+
"inputs": {
|
| 594 |
+
"inputT": {
|
| 595 |
+
"dtype": "float32",
|
| 596 |
+
"shape": [3, 4],
|
| 597 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.25, "cosStep": 0.31, "scale": 0.5 }
|
| 598 |
+
},
|
| 599 |
+
"routerT": {
|
| 600 |
+
"dtype": "float32",
|
| 601 |
+
"shape": [3, 3],
|
| 602 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.27, "scale": 0.7 }
|
| 603 |
+
},
|
| 604 |
+
"fc1T": {
|
| 605 |
+
"dtype": "float32",
|
| 606 |
+
"shape": [3, 5, 4],
|
| 607 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 608 |
+
},
|
| 609 |
+
"fc2T": {
|
| 610 |
+
"dtype": "float32",
|
| 611 |
+
"shape": [3, 4, 5],
|
| 612 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 613 |
+
},
|
| 614 |
+
"fc2BiasT": {
|
| 615 |
+
"dtype": "float32",
|
| 616 |
+
"shape": [3, 4],
|
| 617 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.43, "cosStep": 0.17, "scale": 0.2 }
|
| 618 |
+
},
|
| 619 |
+
"fc3T": {
|
| 620 |
+
"dtype": "float32",
|
| 621 |
+
"shape": [3, 5, 4],
|
| 622 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.15 }
|
| 623 |
+
},
|
| 624 |
+
"fc3BiasT": {
|
| 625 |
+
"dtype": "float32",
|
| 626 |
+
"shape": [3, 5],
|
| 627 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.23, "scale": 0.2 }
|
| 628 |
+
}
|
| 629 |
+
},
|
| 630 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 631 |
+
},
|
| 632 |
+
{
|
| 633 |
+
"name": "silu_fc1_bias_gate_fc3",
|
| 634 |
+
"provenance": {
|
| 635 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 636 |
+
"test": "com.microsoft.MoE optional-input combination",
|
| 637 |
+
"notes": "Each optional input changes the binding layout, so every combination of FC1 bias, FC3 (with or without its own bias) and FC2 bias is a distinct variant. This case is the one that selects fc1bias / FC3 without bias / no FC2 bias; without it that variant would ship unexercised."
|
| 638 |
+
},
|
| 639 |
+
"attrs": { "k": 1, "activation_type": "silu", "normalize_routing_weights": 0 },
|
| 640 |
+
"inputs": {
|
| 641 |
+
"inputT": {
|
| 642 |
+
"dtype": "float32",
|
| 643 |
+
"shape": [3, 4],
|
| 644 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.27, "cosStep": 0.31, "scale": 0.5 }
|
| 645 |
+
},
|
| 646 |
+
"routerT": {
|
| 647 |
+
"dtype": "float32",
|
| 648 |
+
"shape": [3, 3],
|
| 649 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.29, "scale": 0.7 }
|
| 650 |
+
},
|
| 651 |
+
"fc1T": {
|
| 652 |
+
"dtype": "float32",
|
| 653 |
+
"shape": [3, 5, 4],
|
| 654 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 655 |
+
},
|
| 656 |
+
"fc1BiasT": {
|
| 657 |
+
"dtype": "float32",
|
| 658 |
+
"shape": [3, 5],
|
| 659 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.13, "scale": 0.25 }
|
| 660 |
+
},
|
| 661 |
+
"fc2T": {
|
| 662 |
+
"dtype": "float32",
|
| 663 |
+
"shape": [3, 4, 5],
|
| 664 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 665 |
+
},
|
| 666 |
+
"fc3T": {
|
| 667 |
+
"dtype": "float32",
|
| 668 |
+
"shape": [3, 5, 4],
|
| 669 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.15 }
|
| 670 |
+
}
|
| 671 |
+
},
|
| 672 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 673 |
+
},
|
| 674 |
+
{
|
| 675 |
+
"name": "silu_fc1_bias_gate_fc3_fc2_bias",
|
| 676 |
+
"provenance": {
|
| 677 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 678 |
+
"test": "com.microsoft.MoE optional-input combination",
|
| 679 |
+
"notes": "Each optional input changes the binding layout, so every combination of FC1 bias, FC3 (with or without its own bias) and FC2 bias is a distinct variant. This case is the one that selects fc1bias / FC3 without bias / fc2bias; without it that variant would ship unexercised."
|
| 680 |
+
},
|
| 681 |
+
"attrs": { "k": 2, "activation_type": "silu", "normalize_routing_weights": 1 },
|
| 682 |
+
"inputs": {
|
| 683 |
+
"inputT": {
|
| 684 |
+
"dtype": "float32",
|
| 685 |
+
"shape": [3, 4],
|
| 686 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.31, "scale": 0.5 }
|
| 687 |
+
},
|
| 688 |
+
"routerT": {
|
| 689 |
+
"dtype": "float32",
|
| 690 |
+
"shape": [3, 3],
|
| 691 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.31, "scale": 0.7 }
|
| 692 |
+
},
|
| 693 |
+
"fc1T": {
|
| 694 |
+
"dtype": "float32",
|
| 695 |
+
"shape": [3, 5, 4],
|
| 696 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 697 |
+
},
|
| 698 |
+
"fc1BiasT": {
|
| 699 |
+
"dtype": "float32",
|
| 700 |
+
"shape": [3, 5],
|
| 701 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.13, "scale": 0.25 }
|
| 702 |
+
},
|
| 703 |
+
"fc2T": {
|
| 704 |
+
"dtype": "float32",
|
| 705 |
+
"shape": [3, 4, 5],
|
| 706 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 707 |
+
},
|
| 708 |
+
"fc2BiasT": {
|
| 709 |
+
"dtype": "float32",
|
| 710 |
+
"shape": [3, 4],
|
| 711 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.43, "cosStep": 0.17, "scale": 0.2 }
|
| 712 |
+
},
|
| 713 |
+
"fc3T": {
|
| 714 |
+
"dtype": "float32",
|
| 715 |
+
"shape": [3, 5, 4],
|
| 716 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.15 }
|
| 717 |
+
}
|
| 718 |
+
},
|
| 719 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 720 |
+
},
|
| 721 |
+
{
|
| 722 |
+
"name": "ort_softmax_tie_break_top1",
|
| 723 |
+
"provenance": {
|
| 724 |
+
"source": "onnxruntime/contrib_ops/cpu/moe/moe_cpu.cc",
|
| 725 |
+
"test": "full-softmax routing and equal-probability pair ordering",
|
| 726 |
+
"notes": "Equal zero logits become probabilities [0.5, 0.5]. ONNX Runtime selects the higher expert index on the tie; that expert emits 6, and the non-normalized route probability scales the result to exactly 3. This also exercises the schema defaults k=1, activation_type=relu, and normalize_routing_weights=0."
|
| 727 |
+
},
|
| 728 |
+
"inputs": {
|
| 729 |
+
"inputT": { "dtype": "float32", "shape": [1, 1], "data": { "kind": "values", "values": [1.0] } },
|
| 730 |
+
"routerT": { "dtype": "float32", "shape": [1, 2], "data": { "kind": "values", "values": [0.0, 0.0] } },
|
| 731 |
+
"fc1T": { "dtype": "float32", "shape": [2, 1, 1], "data": { "kind": "values", "values": [1.0, 2.0] } },
|
| 732 |
+
"fc2T": { "dtype": "float32", "shape": [2, 1, 1], "data": { "kind": "values", "values": [1.0, 3.0] } }
|
| 733 |
+
},
|
| 734 |
+
"outputs": {
|
| 735 |
+
"outputT": {
|
| 736 |
+
"dtype": "float32",
|
| 737 |
+
"shape": [1, 1],
|
| 738 |
+
"tolerance": 0,
|
| 739 |
+
"data": { "kind": "values", "values": [3.0] }
|
| 740 |
+
}
|
| 741 |
+
}
|
| 742 |
+
},
|
| 743 |
+
{
|
| 744 |
+
"name": "silu_fc1_bias_gate_fc3_bias",
|
| 745 |
+
"provenance": {
|
| 746 |
+
"source": "onnxruntime/docs/ContribOperators.md#com.microsoft.MoE",
|
| 747 |
+
"test": "com.microsoft.MoE optional-input combination",
|
| 748 |
+
"notes": "Each optional input changes the binding layout, so every combination of FC1 bias, FC3 (with or without its own bias) and FC2 bias is a distinct variant. This case is the one that selects fc1bias / FC3 with bias / no FC2 bias; without it that variant would ship unexercised."
|
| 749 |
+
},
|
| 750 |
+
"attrs": { "k": 1, "activation_type": "silu", "normalize_routing_weights": 0 },
|
| 751 |
+
"inputs": {
|
| 752 |
+
"inputT": {
|
| 753 |
+
"dtype": "float32",
|
| 754 |
+
"shape": [3, 4],
|
| 755 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.31, "scale": 0.5 }
|
| 756 |
+
},
|
| 757 |
+
"routerT": {
|
| 758 |
+
"dtype": "float32",
|
| 759 |
+
"shape": [3, 3],
|
| 760 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.33, "scale": 0.7 }
|
| 761 |
+
},
|
| 762 |
+
"fc1T": {
|
| 763 |
+
"dtype": "float32",
|
| 764 |
+
"shape": [3, 5, 4],
|
| 765 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 766 |
+
},
|
| 767 |
+
"fc1BiasT": {
|
| 768 |
+
"dtype": "float32",
|
| 769 |
+
"shape": [3, 5],
|
| 770 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.13, "scale": 0.25 }
|
| 771 |
+
},
|
| 772 |
+
"fc2T": {
|
| 773 |
+
"dtype": "float32",
|
| 774 |
+
"shape": [3, 4, 5],
|
| 775 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.16 }
|
| 776 |
+
},
|
| 777 |
+
"fc3T": {
|
| 778 |
+
"dtype": "float32",
|
| 779 |
+
"shape": [3, 5, 4],
|
| 780 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.15 }
|
| 781 |
+
},
|
| 782 |
+
"fc3BiasT": {
|
| 783 |
+
"dtype": "float32",
|
| 784 |
+
"shape": [3, 5],
|
| 785 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.23, "scale": 0.2 }
|
| 786 |
+
}
|
| 787 |
+
},
|
| 788 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 789 |
+
},
|
| 790 |
+
{
|
| 791 |
+
"name": "deep_reduction_fc1plain_fc3none_fc2plain_identity",
|
| 792 |
+
"provenance": {
|
| 793 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 794 |
+
},
|
| 795 |
+
"attrs": { "activation_type": "identity", "normalize_routing_weights": 1 },
|
| 796 |
+
"inputs": {
|
| 797 |
+
"inputT": {
|
| 798 |
+
"dtype": "float32",
|
| 799 |
+
"shape": [2, 128],
|
| 800 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.31, "scale": 0.4 }
|
| 801 |
+
},
|
| 802 |
+
"routerT": {
|
| 803 |
+
"dtype": "float32",
|
| 804 |
+
"shape": [2, 3],
|
| 805 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.26, "cosStep": 0.24, "scale": 0.6 }
|
| 806 |
+
},
|
| 807 |
+
"fc1T": {
|
| 808 |
+
"dtype": "float32",
|
| 809 |
+
"shape": [3, 128, 128],
|
| 810 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.36, "scale": 0.12 }
|
| 811 |
+
},
|
| 812 |
+
"fc2T": {
|
| 813 |
+
"dtype": "float32",
|
| 814 |
+
"shape": [3, 128, 128],
|
| 815 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.09, "cosStep": 0.28, "scale": 0.12 }
|
| 816 |
+
}
|
| 817 |
+
},
|
| 818 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 819 |
+
},
|
| 820 |
+
{
|
| 821 |
+
"name": "deep_reduction_fc1plain_fc3none_fc2bias_swiglu2",
|
| 822 |
+
"provenance": {
|
| 823 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 824 |
+
},
|
| 825 |
+
"attrs": {
|
| 826 |
+
"k": 2,
|
| 827 |
+
"activation_type": "swiglu",
|
| 828 |
+
"activation_alpha": 1.702,
|
| 829 |
+
"activation_beta": 0.05,
|
| 830 |
+
"swiglu_fusion": 2,
|
| 831 |
+
"normalize_routing_weights": 1
|
| 832 |
+
},
|
| 833 |
+
"inputs": {
|
| 834 |
+
"inputT": {
|
| 835 |
+
"dtype": "float32",
|
| 836 |
+
"shape": [2, 128],
|
| 837 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.083, "cosStep": 0.299, "scale": 0.4 }
|
| 838 |
+
},
|
| 839 |
+
"routerT": {
|
| 840 |
+
"dtype": "float32",
|
| 841 |
+
"shape": [2, 3],
|
| 842 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.273, "cosStep": 0.229, "scale": 0.6 }
|
| 843 |
+
},
|
| 844 |
+
"fc1T": {
|
| 845 |
+
"dtype": "float32",
|
| 846 |
+
"shape": [3, 256, 128],
|
| 847 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.123, "cosStep": 0.349, "scale": 0.12 }
|
| 848 |
+
},
|
| 849 |
+
"fc2T": {
|
| 850 |
+
"dtype": "float32",
|
| 851 |
+
"shape": [3, 128, 128],
|
| 852 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.103, "cosStep": 0.269, "scale": 0.12 }
|
| 853 |
+
},
|
| 854 |
+
"fc2BiasT": {
|
| 855 |
+
"dtype": "float32",
|
| 856 |
+
"shape": [3, 128],
|
| 857 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.233, "cosStep": 0.319, "scale": 0.2 }
|
| 858 |
+
}
|
| 859 |
+
},
|
| 860 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 861 |
+
},
|
| 862 |
+
{
|
| 863 |
+
"name": "deep_reduction_fc1bias_fc3none_fc2plain_swiglu1",
|
| 864 |
+
"provenance": {
|
| 865 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 866 |
+
},
|
| 867 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 1, "normalize_routing_weights": 1 },
|
| 868 |
+
"inputs": {
|
| 869 |
+
"inputT": {
|
| 870 |
+
"dtype": "float32",
|
| 871 |
+
"shape": [2, 128],
|
| 872 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.096, "cosStep": 0.288, "scale": 0.4 }
|
| 873 |
+
},
|
| 874 |
+
"routerT": {
|
| 875 |
+
"dtype": "float32",
|
| 876 |
+
"shape": [2, 3],
|
| 877 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.286, "cosStep": 0.218, "scale": 0.6 }
|
| 878 |
+
},
|
| 879 |
+
"fc1T": {
|
| 880 |
+
"dtype": "float32",
|
| 881 |
+
"shape": [3, 256, 128],
|
| 882 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.136, "cosStep": 0.338, "scale": 0.12 }
|
| 883 |
+
},
|
| 884 |
+
"fc1BiasT": {
|
| 885 |
+
"dtype": "float32",
|
| 886 |
+
"shape": [3, 256],
|
| 887 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.186, "cosStep": 0.418, "scale": 0.2 }
|
| 888 |
+
},
|
| 889 |
+
"fc2T": {
|
| 890 |
+
"dtype": "float32",
|
| 891 |
+
"shape": [3, 128, 128],
|
| 892 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.116, "cosStep": 0.258, "scale": 0.12 }
|
| 893 |
+
}
|
| 894 |
+
},
|
| 895 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 896 |
+
},
|
| 897 |
+
{
|
| 898 |
+
"name": "deep_reduction_fc1bias_fc3none_fc2bias_swiglu2",
|
| 899 |
+
"provenance": {
|
| 900 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 901 |
+
},
|
| 902 |
+
"attrs": { "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 903 |
+
"inputs": {
|
| 904 |
+
"inputT": {
|
| 905 |
+
"dtype": "float32",
|
| 906 |
+
"shape": [2, 128],
|
| 907 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.109, "cosStep": 0.277, "scale": 0.4 }
|
| 908 |
+
},
|
| 909 |
+
"routerT": {
|
| 910 |
+
"dtype": "float32",
|
| 911 |
+
"shape": [2, 3],
|
| 912 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.299, "cosStep": 0.207, "scale": 0.6 }
|
| 913 |
+
},
|
| 914 |
+
"fc1T": {
|
| 915 |
+
"dtype": "float32",
|
| 916 |
+
"shape": [3, 256, 128],
|
| 917 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.149, "cosStep": 0.327, "scale": 0.12 }
|
| 918 |
+
},
|
| 919 |
+
"fc1BiasT": {
|
| 920 |
+
"dtype": "float32",
|
| 921 |
+
"shape": [3, 256],
|
| 922 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.199, "cosStep": 0.407, "scale": 0.2 }
|
| 923 |
+
},
|
| 924 |
+
"fc2T": {
|
| 925 |
+
"dtype": "float32",
|
| 926 |
+
"shape": [3, 128, 128],
|
| 927 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.129, "cosStep": 0.247, "scale": 0.12 }
|
| 928 |
+
},
|
| 929 |
+
"fc2BiasT": {
|
| 930 |
+
"dtype": "float32",
|
| 931 |
+
"shape": [3, 128],
|
| 932 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.259, "cosStep": 0.297, "scale": 0.2 }
|
| 933 |
+
}
|
| 934 |
+
},
|
| 935 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 936 |
+
},
|
| 937 |
+
{
|
| 938 |
+
"name": "deep_reduction_fc1plain_fc3plain_fc2plain_swiglu0",
|
| 939 |
+
"provenance": {
|
| 940 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 941 |
+
},
|
| 942 |
+
"attrs": { "activation_type": "swiglu", "swiglu_fusion": 0, "normalize_routing_weights": 1 },
|
| 943 |
+
"inputs": {
|
| 944 |
+
"inputT": {
|
| 945 |
+
"dtype": "float32",
|
| 946 |
+
"shape": [2, 128],
|
| 947 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.122, "cosStep": 0.266, "scale": 0.4 }
|
| 948 |
+
},
|
| 949 |
+
"routerT": {
|
| 950 |
+
"dtype": "float32",
|
| 951 |
+
"shape": [2, 3],
|
| 952 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.312, "cosStep": 0.196, "scale": 0.6 }
|
| 953 |
+
},
|
| 954 |
+
"fc1T": {
|
| 955 |
+
"dtype": "float32",
|
| 956 |
+
"shape": [3, 128, 128],
|
| 957 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.162, "cosStep": 0.316, "scale": 0.12 }
|
| 958 |
+
},
|
| 959 |
+
"fc2T": {
|
| 960 |
+
"dtype": "float32",
|
| 961 |
+
"shape": [3, 128, 128],
|
| 962 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.142, "cosStep": 0.236, "scale": 0.12 }
|
| 963 |
+
},
|
| 964 |
+
"fc3T": {
|
| 965 |
+
"dtype": "float32",
|
| 966 |
+
"shape": [3, 128, 128],
|
| 967 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.182, "cosStep": 0.356, "scale": 0.12 }
|
| 968 |
+
}
|
| 969 |
+
},
|
| 970 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 971 |
+
},
|
| 972 |
+
{
|
| 973 |
+
"name": "deep_reduction_fc1plain_fc3plain_fc2bias_swiglu0",
|
| 974 |
+
"provenance": {
|
| 975 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 976 |
+
},
|
| 977 |
+
"attrs": {
|
| 978 |
+
"k": 2,
|
| 979 |
+
"activation_type": "swiglu",
|
| 980 |
+
"activation_alpha": 1.702,
|
| 981 |
+
"activation_beta": 0.05,
|
| 982 |
+
"swiglu_fusion": 0,
|
| 983 |
+
"normalize_routing_weights": 1
|
| 984 |
+
},
|
| 985 |
+
"inputs": {
|
| 986 |
+
"inputT": {
|
| 987 |
+
"dtype": "float32",
|
| 988 |
+
"shape": [2, 128],
|
| 989 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.135, "cosStep": 0.255, "scale": 0.4 }
|
| 990 |
+
},
|
| 991 |
+
"routerT": {
|
| 992 |
+
"dtype": "float32",
|
| 993 |
+
"shape": [2, 3],
|
| 994 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.325, "cosStep": 0.185, "scale": 0.6 }
|
| 995 |
+
},
|
| 996 |
+
"fc1T": {
|
| 997 |
+
"dtype": "float32",
|
| 998 |
+
"shape": [3, 128, 128],
|
| 999 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.175, "cosStep": 0.305, "scale": 0.12 }
|
| 1000 |
+
},
|
| 1001 |
+
"fc2T": {
|
| 1002 |
+
"dtype": "float32",
|
| 1003 |
+
"shape": [3, 128, 128],
|
| 1004 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.155, "cosStep": 0.225, "scale": 0.12 }
|
| 1005 |
+
},
|
| 1006 |
+
"fc2BiasT": {
|
| 1007 |
+
"dtype": "float32",
|
| 1008 |
+
"shape": [3, 128],
|
| 1009 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.285, "cosStep": 0.275, "scale": 0.2 }
|
| 1010 |
+
},
|
| 1011 |
+
"fc3T": {
|
| 1012 |
+
"dtype": "float32",
|
| 1013 |
+
"shape": [3, 128, 128],
|
| 1014 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.195, "cosStep": 0.345, "scale": 0.12 }
|
| 1015 |
+
}
|
| 1016 |
+
},
|
| 1017 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 1018 |
+
},
|
| 1019 |
+
{
|
| 1020 |
+
"name": "deep_reduction_fc1plain_fc3biased_fc2plain_swiglu0",
|
| 1021 |
+
"provenance": {
|
| 1022 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 1023 |
+
},
|
| 1024 |
+
"attrs": {
|
| 1025 |
+
"activation_type": "swiglu",
|
| 1026 |
+
"activation_alpha": 1.702,
|
| 1027 |
+
"activation_beta": 0.05,
|
| 1028 |
+
"swiglu_fusion": 0,
|
| 1029 |
+
"normalize_routing_weights": 1
|
| 1030 |
+
},
|
| 1031 |
+
"inputs": {
|
| 1032 |
+
"inputT": {
|
| 1033 |
+
"dtype": "float32",
|
| 1034 |
+
"shape": [2, 128],
|
| 1035 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.148, "cosStep": 0.244, "scale": 0.4 }
|
| 1036 |
+
},
|
| 1037 |
+
"routerT": {
|
| 1038 |
+
"dtype": "float32",
|
| 1039 |
+
"shape": [2, 3],
|
| 1040 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.338, "cosStep": 0.174, "scale": 0.6 }
|
| 1041 |
+
},
|
| 1042 |
+
"fc1T": {
|
| 1043 |
+
"dtype": "float32",
|
| 1044 |
+
"shape": [3, 128, 128],
|
| 1045 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.188, "cosStep": 0.294, "scale": 0.12 }
|
| 1046 |
+
},
|
| 1047 |
+
"fc2T": {
|
| 1048 |
+
"dtype": "float32",
|
| 1049 |
+
"shape": [3, 128, 128],
|
| 1050 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.168, "cosStep": 0.214, "scale": 0.12 }
|
| 1051 |
+
},
|
| 1052 |
+
"fc3T": {
|
| 1053 |
+
"dtype": "float32",
|
| 1054 |
+
"shape": [3, 128, 128],
|
| 1055 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.208, "cosStep": 0.334, "scale": 0.12 }
|
| 1056 |
+
},
|
| 1057 |
+
"fc3BiasT": {
|
| 1058 |
+
"dtype": "float32",
|
| 1059 |
+
"shape": [3, 128],
|
| 1060 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.258, "cosStep": 0.194, "scale": 0.2 }
|
| 1061 |
+
}
|
| 1062 |
+
},
|
| 1063 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 1064 |
+
},
|
| 1065 |
+
{
|
| 1066 |
+
"name": "deep_reduction_fc1plain_fc3biased_fc2bias_swiglu0",
|
| 1067 |
+
"provenance": {
|
| 1068 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 1069 |
+
},
|
| 1070 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 0, "normalize_routing_weights": 1 },
|
| 1071 |
+
"inputs": {
|
| 1072 |
+
"inputT": {
|
| 1073 |
+
"dtype": "float32",
|
| 1074 |
+
"shape": [2, 128],
|
| 1075 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.161, "cosStep": 0.233, "scale": 0.4 }
|
| 1076 |
+
},
|
| 1077 |
+
"routerT": {
|
| 1078 |
+
"dtype": "float32",
|
| 1079 |
+
"shape": [2, 3],
|
| 1080 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.351, "cosStep": 0.163, "scale": 0.6 }
|
| 1081 |
+
},
|
| 1082 |
+
"fc1T": {
|
| 1083 |
+
"dtype": "float32",
|
| 1084 |
+
"shape": [3, 128, 128],
|
| 1085 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.201, "cosStep": 0.283, "scale": 0.12 }
|
| 1086 |
+
},
|
| 1087 |
+
"fc2T": {
|
| 1088 |
+
"dtype": "float32",
|
| 1089 |
+
"shape": [3, 128, 128],
|
| 1090 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.181, "cosStep": 0.203, "scale": 0.12 }
|
| 1091 |
+
},
|
| 1092 |
+
"fc2BiasT": {
|
| 1093 |
+
"dtype": "float32",
|
| 1094 |
+
"shape": [3, 128],
|
| 1095 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.311, "cosStep": 0.253, "scale": 0.2 }
|
| 1096 |
+
},
|
| 1097 |
+
"fc3T": {
|
| 1098 |
+
"dtype": "float32",
|
| 1099 |
+
"shape": [3, 128, 128],
|
| 1100 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.221, "cosStep": 0.323, "scale": 0.12 }
|
| 1101 |
+
},
|
| 1102 |
+
"fc3BiasT": {
|
| 1103 |
+
"dtype": "float32",
|
| 1104 |
+
"shape": [3, 128],
|
| 1105 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.271, "cosStep": 0.183, "scale": 0.2 }
|
| 1106 |
+
}
|
| 1107 |
+
},
|
| 1108 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 1109 |
+
},
|
| 1110 |
+
{
|
| 1111 |
+
"name": "deep_reduction_fc1bias_fc3plain_fc2plain_swiglu0",
|
| 1112 |
+
"provenance": {
|
| 1113 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 1114 |
+
},
|
| 1115 |
+
"attrs": {
|
| 1116 |
+
"k": 2,
|
| 1117 |
+
"activation_type": "swiglu",
|
| 1118 |
+
"activation_alpha": 1.702,
|
| 1119 |
+
"activation_beta": 0.05,
|
| 1120 |
+
"swiglu_fusion": 0,
|
| 1121 |
+
"normalize_routing_weights": 1
|
| 1122 |
+
},
|
| 1123 |
+
"inputs": {
|
| 1124 |
+
"inputT": {
|
| 1125 |
+
"dtype": "float32",
|
| 1126 |
+
"shape": [2, 128],
|
| 1127 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.174, "cosStep": 0.222, "scale": 0.4 }
|
| 1128 |
+
},
|
| 1129 |
+
"routerT": {
|
| 1130 |
+
"dtype": "float32",
|
| 1131 |
+
"shape": [2, 3],
|
| 1132 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.364, "cosStep": 0.152, "scale": 0.6 }
|
| 1133 |
+
},
|
| 1134 |
+
"fc1T": {
|
| 1135 |
+
"dtype": "float32",
|
| 1136 |
+
"shape": [3, 128, 128],
|
| 1137 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.214, "cosStep": 0.272, "scale": 0.12 }
|
| 1138 |
+
},
|
| 1139 |
+
"fc1BiasT": {
|
| 1140 |
+
"dtype": "float32",
|
| 1141 |
+
"shape": [3, 128],
|
| 1142 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.264, "cosStep": 0.352, "scale": 0.2 }
|
| 1143 |
+
},
|
| 1144 |
+
"fc2T": {
|
| 1145 |
+
"dtype": "float32",
|
| 1146 |
+
"shape": [3, 128, 128],
|
| 1147 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.194, "cosStep": 0.192, "scale": 0.12 }
|
| 1148 |
+
},
|
| 1149 |
+
"fc3T": {
|
| 1150 |
+
"dtype": "float32",
|
| 1151 |
+
"shape": [3, 128, 128],
|
| 1152 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.234, "cosStep": 0.312, "scale": 0.12 }
|
| 1153 |
+
}
|
| 1154 |
+
},
|
| 1155 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 1156 |
+
},
|
| 1157 |
+
{
|
| 1158 |
+
"name": "deep_reduction_fc1bias_fc3plain_fc2bias_swiglu0",
|
| 1159 |
+
"provenance": {
|
| 1160 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 1161 |
+
},
|
| 1162 |
+
"attrs": { "activation_type": "swiglu", "swiglu_fusion": 0, "normalize_routing_weights": 1 },
|
| 1163 |
+
"inputs": {
|
| 1164 |
+
"inputT": {
|
| 1165 |
+
"dtype": "float32",
|
| 1166 |
+
"shape": [2, 128],
|
| 1167 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.187, "cosStep": 0.211, "scale": 0.4 }
|
| 1168 |
+
},
|
| 1169 |
+
"routerT": {
|
| 1170 |
+
"dtype": "float32",
|
| 1171 |
+
"shape": [2, 3],
|
| 1172 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.377, "cosStep": 0.141, "scale": 0.6 }
|
| 1173 |
+
},
|
| 1174 |
+
"fc1T": {
|
| 1175 |
+
"dtype": "float32",
|
| 1176 |
+
"shape": [3, 128, 128],
|
| 1177 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.227, "cosStep": 0.261, "scale": 0.12 }
|
| 1178 |
+
},
|
| 1179 |
+
"fc1BiasT": {
|
| 1180 |
+
"dtype": "float32",
|
| 1181 |
+
"shape": [3, 128],
|
| 1182 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.277, "cosStep": 0.341, "scale": 0.2 }
|
| 1183 |
+
},
|
| 1184 |
+
"fc2T": {
|
| 1185 |
+
"dtype": "float32",
|
| 1186 |
+
"shape": [3, 128, 128],
|
| 1187 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.207, "cosStep": 0.181, "scale": 0.12 }
|
| 1188 |
+
},
|
| 1189 |
+
"fc2BiasT": {
|
| 1190 |
+
"dtype": "float32",
|
| 1191 |
+
"shape": [3, 128],
|
| 1192 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.337, "cosStep": 0.231, "scale": 0.2 }
|
| 1193 |
+
},
|
| 1194 |
+
"fc3T": {
|
| 1195 |
+
"dtype": "float32",
|
| 1196 |
+
"shape": [3, 128, 128],
|
| 1197 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.247, "cosStep": 0.301, "scale": 0.12 }
|
| 1198 |
+
}
|
| 1199 |
+
},
|
| 1200 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 1201 |
+
},
|
| 1202 |
+
{
|
| 1203 |
+
"name": "deep_reduction_fc1bias_fc3biased_fc2plain_swiglu0",
|
| 1204 |
+
"provenance": {
|
| 1205 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 1206 |
+
},
|
| 1207 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 0, "normalize_routing_weights": 1 },
|
| 1208 |
+
"inputs": {
|
| 1209 |
+
"inputT": {
|
| 1210 |
+
"dtype": "float32",
|
| 1211 |
+
"shape": [2, 128],
|
| 1212 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.2, "cosStep": 0.2, "scale": 0.4 }
|
| 1213 |
+
},
|
| 1214 |
+
"routerT": {
|
| 1215 |
+
"dtype": "float32",
|
| 1216 |
+
"shape": [2, 3],
|
| 1217 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.39, "cosStep": 0.13, "scale": 0.6 }
|
| 1218 |
+
},
|
| 1219 |
+
"fc1T": {
|
| 1220 |
+
"dtype": "float32",
|
| 1221 |
+
"shape": [3, 128, 128],
|
| 1222 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.24, "cosStep": 0.25, "scale": 0.12 }
|
| 1223 |
+
},
|
| 1224 |
+
"fc1BiasT": {
|
| 1225 |
+
"dtype": "float32",
|
| 1226 |
+
"shape": [3, 128],
|
| 1227 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.33, "scale": 0.2 }
|
| 1228 |
+
},
|
| 1229 |
+
"fc2T": {
|
| 1230 |
+
"dtype": "float32",
|
| 1231 |
+
"shape": [3, 128, 128],
|
| 1232 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.22, "cosStep": 0.17, "scale": 0.12 }
|
| 1233 |
+
},
|
| 1234 |
+
"fc3T": {
|
| 1235 |
+
"dtype": "float32",
|
| 1236 |
+
"shape": [3, 128, 128],
|
| 1237 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.26, "cosStep": 0.29, "scale": 0.12 }
|
| 1238 |
+
},
|
| 1239 |
+
"fc3BiasT": {
|
| 1240 |
+
"dtype": "float32",
|
| 1241 |
+
"shape": [3, 128],
|
| 1242 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.15, "scale": 0.2 }
|
| 1243 |
+
}
|
| 1244 |
+
},
|
| 1245 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 1246 |
+
},
|
| 1247 |
+
{
|
| 1248 |
+
"name": "deep_reduction_fc1bias_fc3biased_fc2bias_swiglu0",
|
| 1249 |
+
"provenance": {
|
| 1250 |
+
"notes": "A 128-long reduction on both projections, deep enough for the cooperative schedule; the 4-wide cases above stay on the one-thread-per-column schedule."
|
| 1251 |
+
},
|
| 1252 |
+
"attrs": {
|
| 1253 |
+
"activation_type": "swiglu",
|
| 1254 |
+
"activation_alpha": 1.702,
|
| 1255 |
+
"activation_beta": 0.05,
|
| 1256 |
+
"swiglu_fusion": 0,
|
| 1257 |
+
"normalize_routing_weights": 1
|
| 1258 |
+
},
|
| 1259 |
+
"inputs": {
|
| 1260 |
+
"inputT": {
|
| 1261 |
+
"dtype": "float32",
|
| 1262 |
+
"shape": [2, 128],
|
| 1263 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.213, "cosStep": 0.189, "scale": 0.4 }
|
| 1264 |
+
},
|
| 1265 |
+
"routerT": {
|
| 1266 |
+
"dtype": "float32",
|
| 1267 |
+
"shape": [2, 3],
|
| 1268 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.403, "cosStep": 0.119, "scale": 0.6 }
|
| 1269 |
+
},
|
| 1270 |
+
"fc1T": {
|
| 1271 |
+
"dtype": "float32",
|
| 1272 |
+
"shape": [3, 128, 128],
|
| 1273 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.253, "cosStep": 0.239, "scale": 0.12 }
|
| 1274 |
+
},
|
| 1275 |
+
"fc1BiasT": {
|
| 1276 |
+
"dtype": "float32",
|
| 1277 |
+
"shape": [3, 128],
|
| 1278 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.303, "cosStep": 0.319, "scale": 0.2 }
|
| 1279 |
+
},
|
| 1280 |
+
"fc2T": {
|
| 1281 |
+
"dtype": "float32",
|
| 1282 |
+
"shape": [3, 128, 128],
|
| 1283 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.233, "cosStep": 0.159, "scale": 0.12 }
|
| 1284 |
+
},
|
| 1285 |
+
"fc2BiasT": {
|
| 1286 |
+
"dtype": "float32",
|
| 1287 |
+
"shape": [3, 128],
|
| 1288 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.363, "cosStep": 0.209, "scale": 0.2 }
|
| 1289 |
+
},
|
| 1290 |
+
"fc3T": {
|
| 1291 |
+
"dtype": "float32",
|
| 1292 |
+
"shape": [3, 128, 128],
|
| 1293 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.273, "cosStep": 0.279, "scale": 0.12 }
|
| 1294 |
+
},
|
| 1295 |
+
"fc3BiasT": {
|
| 1296 |
+
"dtype": "float32",
|
| 1297 |
+
"shape": [3, 128],
|
| 1298 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.323, "cosStep": 0.139, "scale": 0.2 }
|
| 1299 |
+
}
|
| 1300 |
+
},
|
| 1301 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 1302 |
+
},
|
| 1303 |
+
{
|
| 1304 |
+
"name": "identity_activation_top1",
|
| 1305 |
+
"provenance": {
|
| 1306 |
+
"notes": "activation_type identity passes the FC1 projection through unchanged, which is the only declared activation with no other case."
|
| 1307 |
+
},
|
| 1308 |
+
"attrs": { "activation_type": "identity" },
|
| 1309 |
+
"inputs": {
|
| 1310 |
+
"inputT": {
|
| 1311 |
+
"dtype": "float32",
|
| 1312 |
+
"shape": [3, 4],
|
| 1313 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.29, "scale": 0.5 }
|
| 1314 |
+
},
|
| 1315 |
+
"routerT": {
|
| 1316 |
+
"dtype": "float32",
|
| 1317 |
+
"shape": [3, 3],
|
| 1318 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.17, "scale": 0.7 }
|
| 1319 |
+
},
|
| 1320 |
+
"fc1T": {
|
| 1321 |
+
"dtype": "float32",
|
| 1322 |
+
"shape": [3, 5, 4],
|
| 1323 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23, "scale": 0.18 }
|
| 1324 |
+
},
|
| 1325 |
+
"fc2T": {
|
| 1326 |
+
"dtype": "float32",
|
| 1327 |
+
"shape": [3, 4, 5],
|
| 1328 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41, "scale": 0.18 }
|
| 1329 |
+
}
|
| 1330 |
+
},
|
| 1331 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.00002 } }
|
| 1332 |
+
},
|
| 1333 |
+
{
|
| 1334 |
+
"name": "deep_reduction_gelu_fc2bias",
|
| 1335 |
+
"provenance": {
|
| 1336 |
+
"notes": "GELU over a 128-long reduction makes the cooperative schedule exercise its tanh-approximation activation path."
|
| 1337 |
+
},
|
| 1338 |
+
"attrs": { "k": 2, "activation_type": "gelu", "normalize_routing_weights": 1 },
|
| 1339 |
+
"inputs": {
|
| 1340 |
+
"inputT": {
|
| 1341 |
+
"dtype": "float32",
|
| 1342 |
+
"shape": [2, 128],
|
| 1343 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.23, "cosStep": 0.17, "scale": 0.4 }
|
| 1344 |
+
},
|
| 1345 |
+
"routerT": {
|
| 1346 |
+
"dtype": "float32",
|
| 1347 |
+
"shape": [2, 3],
|
| 1348 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.43, "cosStep": 0.11, "scale": 0.6 }
|
| 1349 |
+
},
|
| 1350 |
+
"fc1T": {
|
| 1351 |
+
"dtype": "float32",
|
| 1352 |
+
"shape": [3, 128, 128],
|
| 1353 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.27, "cosStep": 0.19, "scale": 0.12 }
|
| 1354 |
+
},
|
| 1355 |
+
"fc2T": {
|
| 1356 |
+
"dtype": "float32",
|
| 1357 |
+
"shape": [3, 128, 128],
|
| 1358 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.25, "cosStep": 0.33, "scale": 0.12 }
|
| 1359 |
+
},
|
| 1360 |
+
"fc2BiasT": {
|
| 1361 |
+
"dtype": "float32",
|
| 1362 |
+
"shape": [3, 128],
|
| 1363 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.38, "cosStep": 0.21, "scale": 0.2 }
|
| 1364 |
+
}
|
| 1365 |
+
},
|
| 1366 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [2, 128], "tolerance": 0.00002 } }
|
| 1367 |
+
},
|
| 1368 |
+
{
|
| 1369 |
+
"name": "grouped_prefill_fc1plain_fc3none_fc2plain_relu",
|
| 1370 |
+
"provenance": {
|
| 1371 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1372 |
+
},
|
| 1373 |
+
"attrs": { "k": 2, "activation_type": "relu", "normalize_routing_weights": 1 },
|
| 1374 |
+
"inputs": {
|
| 1375 |
+
"inputT": {
|
| 1376 |
+
"dtype": "float32",
|
| 1377 |
+
"shape": [48, 32],
|
| 1378 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.09, "cosStep": 0.29, "scale": 0.4 }
|
| 1379 |
+
},
|
| 1380 |
+
"routerT": {
|
| 1381 |
+
"dtype": "float32",
|
| 1382 |
+
"shape": [48, 3],
|
| 1383 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.3, "cosStep": 0.24, "scale": 0.7 }
|
| 1384 |
+
},
|
| 1385 |
+
"fc1T": {
|
| 1386 |
+
"dtype": "float32",
|
| 1387 |
+
"shape": [3, 32, 32],
|
| 1388 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.12, "cosStep": 0.36, "scale": 0.15 }
|
| 1389 |
+
},
|
| 1390 |
+
"fc2T": {
|
| 1391 |
+
"dtype": "float32",
|
| 1392 |
+
"shape": [3, 32, 32],
|
| 1393 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.14, "cosStep": 0.26, "scale": 0.15 }
|
| 1394 |
+
}
|
| 1395 |
+
},
|
| 1396 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [48, 32], "tolerance": 0.00002 } }
|
| 1397 |
+
},
|
| 1398 |
+
{
|
| 1399 |
+
"name": "grouped_prefill_fc1plain_fc3none_fc2bias_swiglu2",
|
| 1400 |
+
"provenance": {
|
| 1401 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1402 |
+
},
|
| 1403 |
+
"attrs": {
|
| 1404 |
+
"activation_type": "swiglu",
|
| 1405 |
+
"activation_alpha": 1.702,
|
| 1406 |
+
"activation_beta": 0.05,
|
| 1407 |
+
"swiglu_fusion": 2,
|
| 1408 |
+
"normalize_routing_weights": 1
|
| 1409 |
+
},
|
| 1410 |
+
"inputs": {
|
| 1411 |
+
"inputT": {
|
| 1412 |
+
"dtype": "float32",
|
| 1413 |
+
"shape": [96, 32],
|
| 1414 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.107, "cosStep": 0.281, "scale": 0.4 }
|
| 1415 |
+
},
|
| 1416 |
+
"routerT": {
|
| 1417 |
+
"dtype": "float32",
|
| 1418 |
+
"shape": [96, 3],
|
| 1419 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.317, "cosStep": 0.231, "scale": 0.7 }
|
| 1420 |
+
},
|
| 1421 |
+
"fc1T": {
|
| 1422 |
+
"dtype": "float32",
|
| 1423 |
+
"shape": [3, 64, 32],
|
| 1424 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.137, "cosStep": 0.351, "scale": 0.15 }
|
| 1425 |
+
},
|
| 1426 |
+
"fc2T": {
|
| 1427 |
+
"dtype": "float32",
|
| 1428 |
+
"shape": [3, 32, 32],
|
| 1429 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.157, "cosStep": 0.251, "scale": 0.15 }
|
| 1430 |
+
},
|
| 1431 |
+
"fc2BiasT": {
|
| 1432 |
+
"dtype": "float32",
|
| 1433 |
+
"shape": [3, 32],
|
| 1434 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.277, "cosStep": 0.321, "scale": 0.2 }
|
| 1435 |
+
}
|
| 1436 |
+
},
|
| 1437 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 32], "tolerance": 0.00002 } }
|
| 1438 |
+
},
|
| 1439 |
+
{
|
| 1440 |
+
"name": "grouped_prefill_fc1bias_fc3none_fc2plain_swiglu1",
|
| 1441 |
+
"provenance": {
|
| 1442 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1443 |
+
},
|
| 1444 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 1, "normalize_routing_weights": 1 },
|
| 1445 |
+
"inputs": {
|
| 1446 |
+
"inputT": {
|
| 1447 |
+
"dtype": "float32",
|
| 1448 |
+
"shape": [48, 32],
|
| 1449 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.124, "cosStep": 0.272, "scale": 0.4 }
|
| 1450 |
+
},
|
| 1451 |
+
"routerT": {
|
| 1452 |
+
"dtype": "float32",
|
| 1453 |
+
"shape": [48, 3],
|
| 1454 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.334, "cosStep": 0.222, "scale": 0.7 }
|
| 1455 |
+
},
|
| 1456 |
+
"fc1T": {
|
| 1457 |
+
"dtype": "float32",
|
| 1458 |
+
"shape": [3, 64, 32],
|
| 1459 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.154, "cosStep": 0.342, "scale": 0.15 }
|
| 1460 |
+
},
|
| 1461 |
+
"fc1BiasT": {
|
| 1462 |
+
"dtype": "float32",
|
| 1463 |
+
"shape": [3, 64],
|
| 1464 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.234, "cosStep": 0.422, "scale": 0.2 }
|
| 1465 |
+
},
|
| 1466 |
+
"fc2T": {
|
| 1467 |
+
"dtype": "float32",
|
| 1468 |
+
"shape": [3, 32, 32],
|
| 1469 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.174, "cosStep": 0.242, "scale": 0.15 }
|
| 1470 |
+
}
|
| 1471 |
+
},
|
| 1472 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [48, 32], "tolerance": 0.00002 } }
|
| 1473 |
+
},
|
| 1474 |
+
{
|
| 1475 |
+
"name": "grouped_prefill_fc1bias_fc3none_fc2bias_swiglu2",
|
| 1476 |
+
"provenance": {
|
| 1477 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1478 |
+
},
|
| 1479 |
+
"attrs": { "activation_type": "swiglu", "swiglu_fusion": 2, "normalize_routing_weights": 1 },
|
| 1480 |
+
"inputs": {
|
| 1481 |
+
"inputT": {
|
| 1482 |
+
"dtype": "float32",
|
| 1483 |
+
"shape": [96, 32],
|
| 1484 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.141, "cosStep": 0.263, "scale": 0.4 }
|
| 1485 |
+
},
|
| 1486 |
+
"routerT": {
|
| 1487 |
+
"dtype": "float32",
|
| 1488 |
+
"shape": [96, 3],
|
| 1489 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.351, "cosStep": 0.213, "scale": 0.7 }
|
| 1490 |
+
},
|
| 1491 |
+
"fc1T": {
|
| 1492 |
+
"dtype": "float32",
|
| 1493 |
+
"shape": [3, 64, 32],
|
| 1494 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.171, "cosStep": 0.333, "scale": 0.15 }
|
| 1495 |
+
},
|
| 1496 |
+
"fc1BiasT": {
|
| 1497 |
+
"dtype": "float32",
|
| 1498 |
+
"shape": [3, 64],
|
| 1499 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.251, "cosStep": 0.413, "scale": 0.2 }
|
| 1500 |
+
},
|
| 1501 |
+
"fc2T": {
|
| 1502 |
+
"dtype": "float32",
|
| 1503 |
+
"shape": [3, 32, 32],
|
| 1504 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.191, "cosStep": 0.233, "scale": 0.15 }
|
| 1505 |
+
},
|
| 1506 |
+
"fc2BiasT": {
|
| 1507 |
+
"dtype": "float32",
|
| 1508 |
+
"shape": [3, 32],
|
| 1509 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.311, "cosStep": 0.303, "scale": 0.2 }
|
| 1510 |
+
}
|
| 1511 |
+
},
|
| 1512 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 32], "tolerance": 0.00002 } }
|
| 1513 |
+
},
|
| 1514 |
+
{
|
| 1515 |
+
"name": "grouped_prefill_partial_tiles_gelu",
|
| 1516 |
+
"provenance": {
|
| 1517 |
+
"notes": "Half the routed slots the grouped schedule used to demand, so most of every expert's tile is padding: the tiles are 32 rows and 3 experts share only 64 slots. Covers the band the slot threshold opened, where the store guard drops more rows than it keeps."
|
| 1518 |
+
},
|
| 1519 |
+
"attrs": { "activation_type": "gelu", "normalize_routing_weights": 1, "k": 2 },
|
| 1520 |
+
"inputs": {
|
| 1521 |
+
"inputT": {
|
| 1522 |
+
"dtype": "float32",
|
| 1523 |
+
"shape": [32, 32],
|
| 1524 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.173, "cosStep": 0.229, "scale": 0.4 }
|
| 1525 |
+
},
|
| 1526 |
+
"routerT": {
|
| 1527 |
+
"dtype": "float32",
|
| 1528 |
+
"shape": [32, 3],
|
| 1529 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.347, "cosStep": 0.163, "scale": 0.7 }
|
| 1530 |
+
},
|
| 1531 |
+
"fc1T": {
|
| 1532 |
+
"dtype": "float32",
|
| 1533 |
+
"shape": [3, 32, 32],
|
| 1534 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.199, "cosStep": 0.271, "scale": 0.15 }
|
| 1535 |
+
},
|
| 1536 |
+
"fc1BiasT": {
|
| 1537 |
+
"dtype": "float32",
|
| 1538 |
+
"shape": [3, 32],
|
| 1539 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.251, "cosStep": 0.413, "scale": 0.2 }
|
| 1540 |
+
},
|
| 1541 |
+
"fc2T": {
|
| 1542 |
+
"dtype": "float32",
|
| 1543 |
+
"shape": [3, 32, 32],
|
| 1544 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.241, "cosStep": 0.179, "scale": 0.15 }
|
| 1545 |
+
},
|
| 1546 |
+
"fc2BiasT": {
|
| 1547 |
+
"dtype": "float32",
|
| 1548 |
+
"shape": [3, 32],
|
| 1549 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.311, "cosStep": 0.303, "scale": 0.2 }
|
| 1550 |
+
}
|
| 1551 |
+
},
|
| 1552 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [32, 32], "tolerance": 0.00002 } }
|
| 1553 |
+
},
|
| 1554 |
+
{
|
| 1555 |
+
"name": "grouped_prefill_fc1plain_fc3plain_fc2plain_swiglu0",
|
| 1556 |
+
"provenance": {
|
| 1557 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1558 |
+
},
|
| 1559 |
+
"attrs": { "activation_type": "swiglu", "swiglu_fusion": 0, "normalize_routing_weights": 1 },
|
| 1560 |
+
"inputs": {
|
| 1561 |
+
"inputT": {
|
| 1562 |
+
"dtype": "float32",
|
| 1563 |
+
"shape": [96, 32],
|
| 1564 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.158, "cosStep": 0.254, "scale": 0.4 }
|
| 1565 |
+
},
|
| 1566 |
+
"routerT": {
|
| 1567 |
+
"dtype": "float32",
|
| 1568 |
+
"shape": [96, 3],
|
| 1569 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.368, "cosStep": 0.204, "scale": 0.7 }
|
| 1570 |
+
},
|
| 1571 |
+
"fc1T": {
|
| 1572 |
+
"dtype": "float32",
|
| 1573 |
+
"shape": [3, 32, 32],
|
| 1574 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.188, "cosStep": 0.324, "scale": 0.15 }
|
| 1575 |
+
},
|
| 1576 |
+
"fc2T": {
|
| 1577 |
+
"dtype": "float32",
|
| 1578 |
+
"shape": [3, 32, 32],
|
| 1579 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.208, "cosStep": 0.224, "scale": 0.15 }
|
| 1580 |
+
},
|
| 1581 |
+
"fc3T": {
|
| 1582 |
+
"dtype": "float32",
|
| 1583 |
+
"shape": [3, 32, 32],
|
| 1584 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.228, "cosStep": 0.364, "scale": 0.15 }
|
| 1585 |
+
}
|
| 1586 |
+
},
|
| 1587 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 32], "tolerance": 0.00002 } }
|
| 1588 |
+
},
|
| 1589 |
+
{
|
| 1590 |
+
"name": "grouped_prefill_fc1plain_fc3plain_fc2bias_swiglu0",
|
| 1591 |
+
"provenance": {
|
| 1592 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1593 |
+
},
|
| 1594 |
+
"attrs": {
|
| 1595 |
+
"k": 2,
|
| 1596 |
+
"activation_type": "swiglu",
|
| 1597 |
+
"activation_alpha": 1.702,
|
| 1598 |
+
"activation_beta": 0.05,
|
| 1599 |
+
"swiglu_fusion": 0,
|
| 1600 |
+
"normalize_routing_weights": 1
|
| 1601 |
+
},
|
| 1602 |
+
"inputs": {
|
| 1603 |
+
"inputT": {
|
| 1604 |
+
"dtype": "float32",
|
| 1605 |
+
"shape": [48, 32],
|
| 1606 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.175, "cosStep": 0.245, "scale": 0.4 }
|
| 1607 |
+
},
|
| 1608 |
+
"routerT": {
|
| 1609 |
+
"dtype": "float32",
|
| 1610 |
+
"shape": [48, 3],
|
| 1611 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.385, "cosStep": 0.195, "scale": 0.7 }
|
| 1612 |
+
},
|
| 1613 |
+
"fc1T": {
|
| 1614 |
+
"dtype": "float32",
|
| 1615 |
+
"shape": [3, 32, 32],
|
| 1616 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.205, "cosStep": 0.315, "scale": 0.15 }
|
| 1617 |
+
},
|
| 1618 |
+
"fc2T": {
|
| 1619 |
+
"dtype": "float32",
|
| 1620 |
+
"shape": [3, 32, 32],
|
| 1621 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.225, "cosStep": 0.215, "scale": 0.15 }
|
| 1622 |
+
},
|
| 1623 |
+
"fc2BiasT": {
|
| 1624 |
+
"dtype": "float32",
|
| 1625 |
+
"shape": [3, 32],
|
| 1626 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.345, "cosStep": 0.285, "scale": 0.2 }
|
| 1627 |
+
},
|
| 1628 |
+
"fc3T": {
|
| 1629 |
+
"dtype": "float32",
|
| 1630 |
+
"shape": [3, 32, 32],
|
| 1631 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.245, "cosStep": 0.355, "scale": 0.15 }
|
| 1632 |
+
}
|
| 1633 |
+
},
|
| 1634 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [48, 32], "tolerance": 0.00002 } }
|
| 1635 |
+
},
|
| 1636 |
+
{
|
| 1637 |
+
"name": "grouped_prefill_fc1plain_fc3biased_fc2plain_swiglu0",
|
| 1638 |
+
"provenance": {
|
| 1639 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1640 |
+
},
|
| 1641 |
+
"attrs": {
|
| 1642 |
+
"activation_type": "swiglu",
|
| 1643 |
+
"activation_alpha": 1.702,
|
| 1644 |
+
"activation_beta": 0.05,
|
| 1645 |
+
"swiglu_fusion": 0,
|
| 1646 |
+
"normalize_routing_weights": 1
|
| 1647 |
+
},
|
| 1648 |
+
"inputs": {
|
| 1649 |
+
"inputT": {
|
| 1650 |
+
"dtype": "float32",
|
| 1651 |
+
"shape": [96, 32],
|
| 1652 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.192, "cosStep": 0.236, "scale": 0.4 }
|
| 1653 |
+
},
|
| 1654 |
+
"routerT": {
|
| 1655 |
+
"dtype": "float32",
|
| 1656 |
+
"shape": [96, 3],
|
| 1657 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.402, "cosStep": 0.186, "scale": 0.7 }
|
| 1658 |
+
},
|
| 1659 |
+
"fc1T": {
|
| 1660 |
+
"dtype": "float32",
|
| 1661 |
+
"shape": [3, 32, 32],
|
| 1662 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.222, "cosStep": 0.306, "scale": 0.15 }
|
| 1663 |
+
},
|
| 1664 |
+
"fc2T": {
|
| 1665 |
+
"dtype": "float32",
|
| 1666 |
+
"shape": [3, 32, 32],
|
| 1667 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.242, "cosStep": 0.206, "scale": 0.15 }
|
| 1668 |
+
},
|
| 1669 |
+
"fc3T": {
|
| 1670 |
+
"dtype": "float32",
|
| 1671 |
+
"shape": [3, 32, 32],
|
| 1672 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.262, "cosStep": 0.346, "scale": 0.15 }
|
| 1673 |
+
},
|
| 1674 |
+
"fc3BiasT": {
|
| 1675 |
+
"dtype": "float32",
|
| 1676 |
+
"shape": [3, 32],
|
| 1677 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.322, "cosStep": 0.176, "scale": 0.2 }
|
| 1678 |
+
}
|
| 1679 |
+
},
|
| 1680 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 32], "tolerance": 0.00002 } }
|
| 1681 |
+
},
|
| 1682 |
+
{
|
| 1683 |
+
"name": "grouped_prefill_fc1plain_fc3biased_fc2bias_swiglu0",
|
| 1684 |
+
"provenance": {
|
| 1685 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1686 |
+
},
|
| 1687 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 0, "normalize_routing_weights": 1 },
|
| 1688 |
+
"inputs": {
|
| 1689 |
+
"inputT": {
|
| 1690 |
+
"dtype": "float32",
|
| 1691 |
+
"shape": [48, 32],
|
| 1692 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.209, "cosStep": 0.227, "scale": 0.4 }
|
| 1693 |
+
},
|
| 1694 |
+
"routerT": {
|
| 1695 |
+
"dtype": "float32",
|
| 1696 |
+
"shape": [48, 3],
|
| 1697 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.419, "cosStep": 0.177, "scale": 0.7 }
|
| 1698 |
+
},
|
| 1699 |
+
"fc1T": {
|
| 1700 |
+
"dtype": "float32",
|
| 1701 |
+
"shape": [3, 32, 32],
|
| 1702 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.239, "cosStep": 0.297, "scale": 0.15 }
|
| 1703 |
+
},
|
| 1704 |
+
"fc2T": {
|
| 1705 |
+
"dtype": "float32",
|
| 1706 |
+
"shape": [3, 32, 32],
|
| 1707 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.259, "cosStep": 0.197, "scale": 0.15 }
|
| 1708 |
+
},
|
| 1709 |
+
"fc2BiasT": {
|
| 1710 |
+
"dtype": "float32",
|
| 1711 |
+
"shape": [3, 32],
|
| 1712 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.379, "cosStep": 0.267, "scale": 0.2 }
|
| 1713 |
+
},
|
| 1714 |
+
"fc3T": {
|
| 1715 |
+
"dtype": "float32",
|
| 1716 |
+
"shape": [3, 32, 32],
|
| 1717 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.279, "cosStep": 0.337, "scale": 0.15 }
|
| 1718 |
+
},
|
| 1719 |
+
"fc3BiasT": {
|
| 1720 |
+
"dtype": "float32",
|
| 1721 |
+
"shape": [3, 32],
|
| 1722 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.339, "cosStep": 0.167, "scale": 0.2 }
|
| 1723 |
+
}
|
| 1724 |
+
},
|
| 1725 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [48, 32], "tolerance": 0.00002 } }
|
| 1726 |
+
},
|
| 1727 |
+
{
|
| 1728 |
+
"name": "grouped_prefill_fc1bias_fc3plain_fc2plain_swiglu0",
|
| 1729 |
+
"provenance": {
|
| 1730 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1731 |
+
},
|
| 1732 |
+
"attrs": {
|
| 1733 |
+
"k": 2,
|
| 1734 |
+
"activation_type": "swiglu",
|
| 1735 |
+
"activation_alpha": 1.702,
|
| 1736 |
+
"activation_beta": 0.05,
|
| 1737 |
+
"swiglu_fusion": 0,
|
| 1738 |
+
"normalize_routing_weights": 1
|
| 1739 |
+
},
|
| 1740 |
+
"inputs": {
|
| 1741 |
+
"inputT": {
|
| 1742 |
+
"dtype": "float32",
|
| 1743 |
+
"shape": [48, 32],
|
| 1744 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.226, "cosStep": 0.218, "scale": 0.4 }
|
| 1745 |
+
},
|
| 1746 |
+
"routerT": {
|
| 1747 |
+
"dtype": "float32",
|
| 1748 |
+
"shape": [48, 3],
|
| 1749 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.436, "cosStep": 0.168, "scale": 0.7 }
|
| 1750 |
+
},
|
| 1751 |
+
"fc1T": {
|
| 1752 |
+
"dtype": "float32",
|
| 1753 |
+
"shape": [3, 32, 32],
|
| 1754 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.256, "cosStep": 0.288, "scale": 0.15 }
|
| 1755 |
+
},
|
| 1756 |
+
"fc1BiasT": {
|
| 1757 |
+
"dtype": "float32",
|
| 1758 |
+
"shape": [3, 32],
|
| 1759 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.336, "cosStep": 0.368, "scale": 0.2 }
|
| 1760 |
+
},
|
| 1761 |
+
"fc2T": {
|
| 1762 |
+
"dtype": "float32",
|
| 1763 |
+
"shape": [3, 32, 32],
|
| 1764 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.276, "cosStep": 0.188, "scale": 0.15 }
|
| 1765 |
+
},
|
| 1766 |
+
"fc3T": {
|
| 1767 |
+
"dtype": "float32",
|
| 1768 |
+
"shape": [3, 32, 32],
|
| 1769 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.296, "cosStep": 0.328, "scale": 0.15 }
|
| 1770 |
+
}
|
| 1771 |
+
},
|
| 1772 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [48, 32], "tolerance": 0.00002 } }
|
| 1773 |
+
},
|
| 1774 |
+
{
|
| 1775 |
+
"name": "grouped_prefill_fc1bias_fc3plain_fc2bias_swiglu0",
|
| 1776 |
+
"provenance": {
|
| 1777 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1778 |
+
},
|
| 1779 |
+
"attrs": { "activation_type": "swiglu", "swiglu_fusion": 0, "normalize_routing_weights": 1 },
|
| 1780 |
+
"inputs": {
|
| 1781 |
+
"inputT": {
|
| 1782 |
+
"dtype": "float32",
|
| 1783 |
+
"shape": [96, 32],
|
| 1784 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.243, "cosStep": 0.209, "scale": 0.4 }
|
| 1785 |
+
},
|
| 1786 |
+
"routerT": {
|
| 1787 |
+
"dtype": "float32",
|
| 1788 |
+
"shape": [96, 3],
|
| 1789 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.453, "cosStep": 0.159, "scale": 0.7 }
|
| 1790 |
+
},
|
| 1791 |
+
"fc1T": {
|
| 1792 |
+
"dtype": "float32",
|
| 1793 |
+
"shape": [3, 32, 32],
|
| 1794 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.273, "cosStep": 0.279, "scale": 0.15 }
|
| 1795 |
+
},
|
| 1796 |
+
"fc1BiasT": {
|
| 1797 |
+
"dtype": "float32",
|
| 1798 |
+
"shape": [3, 32],
|
| 1799 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.353, "cosStep": 0.359, "scale": 0.2 }
|
| 1800 |
+
},
|
| 1801 |
+
"fc2T": {
|
| 1802 |
+
"dtype": "float32",
|
| 1803 |
+
"shape": [3, 32, 32],
|
| 1804 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.293, "cosStep": 0.179, "scale": 0.15 }
|
| 1805 |
+
},
|
| 1806 |
+
"fc2BiasT": {
|
| 1807 |
+
"dtype": "float32",
|
| 1808 |
+
"shape": [3, 32],
|
| 1809 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.413, "cosStep": 0.249, "scale": 0.2 }
|
| 1810 |
+
},
|
| 1811 |
+
"fc3T": {
|
| 1812 |
+
"dtype": "float32",
|
| 1813 |
+
"shape": [3, 32, 32],
|
| 1814 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.313, "cosStep": 0.319, "scale": 0.15 }
|
| 1815 |
+
}
|
| 1816 |
+
},
|
| 1817 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 32], "tolerance": 0.00002 } }
|
| 1818 |
+
},
|
| 1819 |
+
{
|
| 1820 |
+
"name": "grouped_prefill_fc1bias_fc3biased_fc2plain_swiglu0",
|
| 1821 |
+
"provenance": {
|
| 1822 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1823 |
+
},
|
| 1824 |
+
"attrs": { "k": 2, "activation_type": "swiglu", "swiglu_fusion": 0, "normalize_routing_weights": 1 },
|
| 1825 |
+
"inputs": {
|
| 1826 |
+
"inputT": {
|
| 1827 |
+
"dtype": "float32",
|
| 1828 |
+
"shape": [48, 32],
|
| 1829 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.26, "cosStep": 0.2, "scale": 0.4 }
|
| 1830 |
+
},
|
| 1831 |
+
"routerT": {
|
| 1832 |
+
"dtype": "float32",
|
| 1833 |
+
"shape": [48, 3],
|
| 1834 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.47, "cosStep": 0.15, "scale": 0.7 }
|
| 1835 |
+
},
|
| 1836 |
+
"fc1T": {
|
| 1837 |
+
"dtype": "float32",
|
| 1838 |
+
"shape": [3, 32, 32],
|
| 1839 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.27, "scale": 0.15 }
|
| 1840 |
+
},
|
| 1841 |
+
"fc1BiasT": {
|
| 1842 |
+
"dtype": "float32",
|
| 1843 |
+
"shape": [3, 32],
|
| 1844 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.35, "scale": 0.2 }
|
| 1845 |
+
},
|
| 1846 |
+
"fc2T": {
|
| 1847 |
+
"dtype": "float32",
|
| 1848 |
+
"shape": [3, 32, 32],
|
| 1849 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.17, "scale": 0.15 }
|
| 1850 |
+
},
|
| 1851 |
+
"fc3T": {
|
| 1852 |
+
"dtype": "float32",
|
| 1853 |
+
"shape": [3, 32, 32],
|
| 1854 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.33, "cosStep": 0.31, "scale": 0.15 }
|
| 1855 |
+
},
|
| 1856 |
+
"fc3BiasT": {
|
| 1857 |
+
"dtype": "float32",
|
| 1858 |
+
"shape": [3, 32],
|
| 1859 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.39, "cosStep": 0.14, "scale": 0.2 }
|
| 1860 |
+
}
|
| 1861 |
+
},
|
| 1862 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [48, 32], "tolerance": 0.00002 } }
|
| 1863 |
+
},
|
| 1864 |
+
{
|
| 1865 |
+
"name": "grouped_prefill_fc1bias_fc3biased_fc2bias_swiglu0",
|
| 1866 |
+
"provenance": {
|
| 1867 |
+
"notes": "Enough routed slots per expert to fill grouped tiles, so the expert-grouped schedule reuses one staged weight tile across a tile of slots."
|
| 1868 |
+
},
|
| 1869 |
+
"attrs": {
|
| 1870 |
+
"activation_type": "swiglu",
|
| 1871 |
+
"activation_alpha": 1.702,
|
| 1872 |
+
"activation_beta": 0.05,
|
| 1873 |
+
"swiglu_fusion": 0,
|
| 1874 |
+
"normalize_routing_weights": 1
|
| 1875 |
+
},
|
| 1876 |
+
"inputs": {
|
| 1877 |
+
"inputT": {
|
| 1878 |
+
"dtype": "float32",
|
| 1879 |
+
"shape": [96, 32],
|
| 1880 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.277, "cosStep": 0.191, "scale": 0.4 }
|
| 1881 |
+
},
|
| 1882 |
+
"routerT": {
|
| 1883 |
+
"dtype": "float32",
|
| 1884 |
+
"shape": [96, 3],
|
| 1885 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.487, "cosStep": 0.141, "scale": 0.7 }
|
| 1886 |
+
},
|
| 1887 |
+
"fc1T": {
|
| 1888 |
+
"dtype": "float32",
|
| 1889 |
+
"shape": [3, 32, 32],
|
| 1890 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.307, "cosStep": 0.261, "scale": 0.15 }
|
| 1891 |
+
},
|
| 1892 |
+
"fc1BiasT": {
|
| 1893 |
+
"dtype": "float32",
|
| 1894 |
+
"shape": [3, 32],
|
| 1895 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.387, "cosStep": 0.341, "scale": 0.2 }
|
| 1896 |
+
},
|
| 1897 |
+
"fc2T": {
|
| 1898 |
+
"dtype": "float32",
|
| 1899 |
+
"shape": [3, 32, 32],
|
| 1900 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.327, "cosStep": 0.161, "scale": 0.15 }
|
| 1901 |
+
},
|
| 1902 |
+
"fc2BiasT": {
|
| 1903 |
+
"dtype": "float32",
|
| 1904 |
+
"shape": [3, 32],
|
| 1905 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.447, "cosStep": 0.231, "scale": 0.2 }
|
| 1906 |
+
},
|
| 1907 |
+
"fc3T": {
|
| 1908 |
+
"dtype": "float32",
|
| 1909 |
+
"shape": [3, 32, 32],
|
| 1910 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.347, "cosStep": 0.301, "scale": 0.15 }
|
| 1911 |
+
},
|
| 1912 |
+
"fc3BiasT": {
|
| 1913 |
+
"dtype": "float32",
|
| 1914 |
+
"shape": [3, 32],
|
| 1915 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.407, "cosStep": 0.131, "scale": 0.2 }
|
| 1916 |
+
}
|
| 1917 |
+
},
|
| 1918 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 32], "tolerance": 0.00002 } }
|
| 1919 |
+
},
|
| 1920 |
+
{
|
| 1921 |
+
"name": "grouped_prefill_identity_no_fc3",
|
| 1922 |
+
"provenance": {
|
| 1923 |
+
"notes": "The smallest default-tile prefill that meets the grouped schedule's routed-slot threshold, and exercises identity activation without FC3 after expert grouping."
|
| 1924 |
+
},
|
| 1925 |
+
"attrs": { "k": 2, "activation_type": "identity", "normalize_routing_weights": 1 },
|
| 1926 |
+
"inputs": {
|
| 1927 |
+
"inputT": {
|
| 1928 |
+
"dtype": "float32",
|
| 1929 |
+
"shape": [48, 16],
|
| 1930 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.181, "cosStep": 0.217, "scale": 0.4 }
|
| 1931 |
+
},
|
| 1932 |
+
"routerT": {
|
| 1933 |
+
"dtype": "float32",
|
| 1934 |
+
"shape": [48, 3],
|
| 1935 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.391, "cosStep": 0.127, "scale": 0.7 }
|
| 1936 |
+
},
|
| 1937 |
+
"fc1T": {
|
| 1938 |
+
"dtype": "float32",
|
| 1939 |
+
"shape": [3, 16, 16],
|
| 1940 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.211, "cosStep": 0.287, "scale": 0.15 }
|
| 1941 |
+
},
|
| 1942 |
+
"fc2T": {
|
| 1943 |
+
"dtype": "float32",
|
| 1944 |
+
"shape": [3, 16, 16],
|
| 1945 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.231, "cosStep": 0.187, "scale": 0.15 }
|
| 1946 |
+
}
|
| 1947 |
+
},
|
| 1948 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [48, 16], "tolerance": 0.00002 } }
|
| 1949 |
+
},
|
| 1950 |
+
{
|
| 1951 |
+
"name": "grouped_prefill_unaligned_hidden_inter",
|
| 1952 |
+
"provenance": {
|
| 1953 |
+
"notes": "Hidden 34 and intermediate 30 are not divisible by four, so grouped staging uses scalar activation and weight reads. The gated FC3 stream adds a second scalar weight stream, and every K tile is partial against the 16-wide tile."
|
| 1954 |
+
},
|
| 1955 |
+
"attrs": { "activation_type": "silu", "normalize_routing_weights": 1, "k": 2 },
|
| 1956 |
+
"inputs": {
|
| 1957 |
+
"inputT": {
|
| 1958 |
+
"dtype": "float32",
|
| 1959 |
+
"shape": [96, 34],
|
| 1960 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.163, "cosStep": 0.239, "scale": 0.4 }
|
| 1961 |
+
},
|
| 1962 |
+
"routerT": {
|
| 1963 |
+
"dtype": "float32",
|
| 1964 |
+
"shape": [96, 3],
|
| 1965 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.337, "cosStep": 0.173, "scale": 0.7 }
|
| 1966 |
+
},
|
| 1967 |
+
"fc1T": {
|
| 1968 |
+
"dtype": "float32",
|
| 1969 |
+
"shape": [3, 30, 34],
|
| 1970 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.209, "cosStep": 0.281, "scale": 0.15 }
|
| 1971 |
+
},
|
| 1972 |
+
"fc1BiasT": {
|
| 1973 |
+
"dtype": "float32",
|
| 1974 |
+
"shape": [3, 30],
|
| 1975 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.261, "cosStep": 0.423, "scale": 0.2 }
|
| 1976 |
+
},
|
| 1977 |
+
"fc2T": {
|
| 1978 |
+
"dtype": "float32",
|
| 1979 |
+
"shape": [3, 34, 30],
|
| 1980 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.251, "cosStep": 0.189, "scale": 0.15 }
|
| 1981 |
+
},
|
| 1982 |
+
"fc2BiasT": {
|
| 1983 |
+
"dtype": "float32",
|
| 1984 |
+
"shape": [3, 34],
|
| 1985 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.321, "cosStep": 0.313, "scale": 0.2 }
|
| 1986 |
+
},
|
| 1987 |
+
"fc3T": {
|
| 1988 |
+
"dtype": "float32",
|
| 1989 |
+
"shape": [3, 30, 34],
|
| 1990 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.227, "cosStep": 0.197, "scale": 0.15 }
|
| 1991 |
+
},
|
| 1992 |
+
"fc3BiasT": {
|
| 1993 |
+
"dtype": "float32",
|
| 1994 |
+
"shape": [3, 30],
|
| 1995 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.283, "cosStep": 0.359, "scale": 0.2 }
|
| 1996 |
+
}
|
| 1997 |
+
},
|
| 1998 |
+
"outputs": { "outputT": { "dtype": "float32", "shape": [96, 34], "tolerance": 0.00002 } }
|
| 1999 |
+
}
|
| 2000 |
+
]
|
| 2001 |
+
}
|