sync c928d21e6cc1
Browse files- README.md +3 -1
- build/webgpu/attn-materialized-rowstats-combine-f32.wgsl.jinja +72 -0
- build/webgpu/attn-materialized-sgmat-f32.wgsl.jinja +562 -0
- build/webgpu/bench.json +23 -0
- build/webgpu/gqa-qprep.wgsl.jinja +11 -4
- build/webgpu/manifest.json +1343 -2
- build/webgpu/metadata.json +8 -6
- build/webgpu/test.json +719 -0
README.md
CHANGED
|
@@ -75,7 +75,7 @@ Attributes and default values (overridable per request):
|
|
| 75 |
|
| 76 |
## Device requirements
|
| 77 |
|
| 78 |
-
Some implementation variants require `shader-f16` and `subgroups`. These are route-specific capabilities, not package-wide requirements; availability also depends on the request shape and dtype.
|
| 79 |
|
| 80 |
## Files
|
| 81 |
|
|
@@ -89,6 +89,8 @@ Some implementation variants require `shader-f16` and `subgroups`. These are rou
|
|
| 89 |
- [`attn-flash-online.wgsl.jinja`](build/webgpu/attn-flash-online.wgsl.jinja)
|
| 90 |
- [`attn-flash-prefill-cluster.wgsl.jinja`](build/webgpu/attn-flash-prefill-cluster.wgsl.jinja)
|
| 91 |
- [`attn-flash-q32-broadcast.wgsl.jinja`](build/webgpu/attn-flash-q32-broadcast.wgsl.jinja)
|
|
|
|
|
|
|
| 92 |
- [`attn-online-scalar.wgsl.jinja`](build/webgpu/attn-online-scalar.wgsl.jinja)
|
| 93 |
- [`gqa-attention.wgsl.jinja`](build/webgpu/gqa-attention.wgsl.jinja)
|
| 94 |
- [`gqa-present.wgsl.jinja`](build/webgpu/gqa-present.wgsl.jinja)
|
|
|
|
| 75 |
|
| 76 |
## Device requirements
|
| 77 |
|
| 78 |
+
Some implementation variants require `subgroup-matrix`, `shader-f16`, and `subgroups`. These are route-specific capabilities, not package-wide requirements; availability also depends on the request shape and dtype.
|
| 79 |
|
| 80 |
## Files
|
| 81 |
|
|
|
|
| 89 |
- [`attn-flash-online.wgsl.jinja`](build/webgpu/attn-flash-online.wgsl.jinja)
|
| 90 |
- [`attn-flash-prefill-cluster.wgsl.jinja`](build/webgpu/attn-flash-prefill-cluster.wgsl.jinja)
|
| 91 |
- [`attn-flash-q32-broadcast.wgsl.jinja`](build/webgpu/attn-flash-q32-broadcast.wgsl.jinja)
|
| 92 |
+
- [`attn-materialized-rowstats-combine-f32.wgsl.jinja`](build/webgpu/attn-materialized-rowstats-combine-f32.wgsl.jinja)
|
| 93 |
+
- [`attn-materialized-sgmat-f32.wgsl.jinja`](build/webgpu/attn-materialized-sgmat-f32.wgsl.jinja)
|
| 94 |
- [`attn-online-scalar.wgsl.jinja`](build/webgpu/attn-online-scalar.wgsl.jinja)
|
| 95 |
- [`gqa-attention.wgsl.jinja`](build/webgpu/gqa-attention.wgsl.jinja)
|
| 96 |
- [`gqa-present.wgsl.jinja`](build/webgpu/gqa-present.wgsl.jinja)
|
build/webgpu/attn-materialized-rowstats-combine-f32.wgsl.jinja
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Folds the per-tile softmax constants the score pass emitted into one (m, d)
|
| 2 |
+
// pair per query row, for the apply pass to normalize with.
|
| 3 |
+
//
|
| 4 |
+
// The score pass publishes one partial per row, key tile, and subgroup column,
|
| 5 |
+
// so this pass can combine the constants without rescanning the materialized
|
| 6 |
+
// score matrix. It uses the same online merge rule as the row-local reduction.
|
| 7 |
+
//
|
| 8 |
+
// One thread per row. Each row's partials are contiguous along the row axis, so
|
| 9 |
+
// consecutive threads read consecutive pairs; the fold walks slots in index
|
| 10 |
+
// order, which is fixed for a given shape, so the result does not depend on how
|
| 11 |
+
// the GPU schedules anything.
|
| 12 |
+
// `maxOnly` means the producer published only a row max per slot because
|
| 13 |
+
// computing the denominator there would double the exp count. Fold maxima and
|
| 14 |
+
// leave the denominator to the apply pass, which sees every row element anyway.
|
| 15 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 16 |
+
|
| 17 |
+
const SLOTS: u32 = {{ statSlots }}u;
|
| 18 |
+
const Q_SEQ: u32 = {{ statQuerySeq }}u;
|
| 19 |
+
const WG: u32 = {{ materializedRowStatsWg }}u;
|
| 20 |
+
|
| 21 |
+
// FLT_MAX, not -inf, as the online (m, d) accumulator init: merges must keep
|
| 22 |
+
// `m - m` finite so an empty lane / all--inf row contributes the exact
|
| 23 |
+
// accumulator identity (m, d) = (-FLT_MAX, 0). Operator epilogues interpret
|
| 24 |
+
// a zero final denominator according to their public semantics. Using -inf
|
| 25 |
+
// here changes +inf-row behavior.
|
| 26 |
+
const FLT_MAX: f32 = 3.4028234663852886e38;
|
| 27 |
+
|
| 28 |
+
fn is_finite_f32(value: f32) -> bool {
|
| 29 |
+
return select(false, value <= FLT_MAX, value >= -FLT_MAX);
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
// x - m that is exactly 0 when x equals a finite m, so exp(shifted) == 1
|
| 33 |
+
// exactly at the row max. `x - x` on an infinite max is a legal fast-math
|
| 34 |
+
// fold to 0, which would silently turn +inf rows finite — the explicit
|
| 35 |
+
// equality test keeps the NaN propagation of the serial kernels.
|
| 36 |
+
fn shifted_value(value: f32, maxValue: f32) -> f32 {
|
| 37 |
+
let equalFiniteMax = select(false, value == maxValue, is_finite_f32(maxValue));
|
| 38 |
+
return select(value - maxValue, 0.0, equalFiniteMax);
|
| 39 |
+
}
|
| 40 |
+
fn exp_shift(value: f32, maxValue: f32) -> f32 {
|
| 41 |
+
return exp(shifted_value(value, maxValue));
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
@compute @workgroup_size(WG, 1, 1)
|
| 45 |
+
fn main(
|
| 46 |
+
@builtin(global_invocation_id) gid: vec3<u32>,
|
| 47 |
+
@builtin(num_workgroups) nwg: vec3<u32>
|
| 48 |
+
) {
|
| 49 |
+
let row = gid.x + gid.y * nwg.x * WG;
|
| 50 |
+
if (row >= params.rows) { return; }
|
| 51 |
+
|
| 52 |
+
// `row` already runs over (batch, head, query) together, and the partial
|
| 53 |
+
// layout puts that same product one axis out from the slot, so the stride
|
| 54 |
+
// between a row's slots is the number of rows in its (batch, head) plane.
|
| 55 |
+
let plane = row / Q_SEQ;
|
| 56 |
+
let inPlane = row % Q_SEQ;
|
| 57 |
+
let base = ((plane * SLOTS) * Q_SEQ + inPlane) * 2u;
|
| 58 |
+
|
| 59 |
+
var m = -FLT_MAX;
|
| 60 |
+
var d = 0.0;
|
| 61 |
+
for (var slot = 0u; slot < SLOTS; slot = slot + 1u) {
|
| 62 |
+
let index = base + slot * Q_SEQ * 2u;
|
| 63 |
+
let slotM = scorePartials[index];
|
| 64 |
+
let slotD = scorePartials[index + 1u];
|
| 65 |
+
let merged = max(m, slotM);
|
| 66 |
+
d = d * exp_shift(m, merged) + slotD * exp_shift(slotM, merged);
|
| 67 |
+
m = merged;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
rowStats[row * 2u] = m;
|
| 71 |
+
rowStats[row * 2u + 1u] = d;
|
| 72 |
+
}
|
build/webgpu/attn-materialized-sgmat-f32.wgsl.jinja
ADDED
|
@@ -0,0 +1,562 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{% set MT = "f16" if (operandF16 is defined and operandF16) else "f32" %}
|
| 2 |
+
{% if MT == "f16" %}
|
| 3 |
+
enable f16;
|
| 4 |
+
{% endif %}
|
| 5 |
+
enable subgroups;
|
| 6 |
+
{% if pinSubgroupSize32 %}
|
| 7 |
+
enable subgroup_size_control;
|
| 8 |
+
{% endif %}
|
| 9 |
+
enable chromium_experimental_subgroup_matrix;
|
| 10 |
+
diagnostic(off, chromium.subgroup_matrix_uniformity);
|
| 11 |
+
|
| 12 |
+
{{ env.wgsl.resourceDeclarations }}
|
| 13 |
+
|
| 14 |
+
{% set layout = source.layout | default("bsh") %}
|
| 15 |
+
{% set headMajor = layout == "bhsd" %}
|
| 16 |
+
{% set kvHeadMajor = (source.kvLayout | default(layout)) == "bhsd" %}
|
| 17 |
+
{% set CAUSAL_UPPER_LEFT = source.causalUpperLeft is defined and source.causalUpperLeft %}
|
| 18 |
+
{% set CAUSAL = (source.causalRightAlign is defined and source.causalRightAlign) or CAUSAL_UPPER_LEFT %}
|
| 19 |
+
{% macro q_index(row, d) %}(b * params.qSeq + {{ row }}) * HIDDEN + h * HEAD_DIM + {{ d }}{% endmacro %}
|
| 20 |
+
{% macro kv_index(seq, d) %}{% if kvHeadMajor %}((b * KV_HEADS + h_kv) * params.kvSeq + {{ seq }}) * HEAD_DIM + {{ d }}{% else %}(b * params.kvSeq + {{ seq }}) * KV_HIDDEN + h_kv * HEAD_DIM + {{ d }}{% endif %}{% endmacro %}
|
| 21 |
+
{% set OUT_ROW_STRIDE = "HEAD_DIM" if headMajor else "HIDDEN" %}
|
| 22 |
+
{% set KV_ROW_STRIDE = "HEAD_DIM" if kvHeadMajor else "KV_HIDDEN" %}
|
| 23 |
+
{% set scorePhase = source.phase == "score" %}
|
| 24 |
+
{% set SCORE_BIAS = scorePhase and source.scoreBias is defined and source.scoreBias %}
|
| 25 |
+
{% set SCORE_WINDOW = CAUSAL and source.scoreWindow is defined and source.scoreWindow %}
|
| 26 |
+
{% set USE_SEQLENS = source.useSeqlens is defined and source.useSeqlens %}
|
| 27 |
+
{% set FUSED_SOFTMAX = source.fusedSoftmax is defined and source.fusedSoftmax %}
|
| 28 |
+
{% set PRIVATE_ROW_STATS = FUSED_SOFTMAX and (materializedSgmatPrivateRowStats is defined and materializedSgmatPrivateRowStats) %}
|
| 29 |
+
{% macro score_value(index, guard) %}
|
| 30 |
+
{% if FUSED_SOFTMAX %}
|
| 31 |
+
{% if PRIVATE_ROW_STATS %}
|
| 32 |
+
select(0.0, exp_shift(scores[{{ index }}], private_softmax_m) / private_softmax_d, {{ guard[1] }})
|
| 33 |
+
{%- else %}
|
| 34 |
+
select(0.0, exp_shift(scores[{{ index }}], softmax_m[{{ guard[0] }}]) / softmax_d[{{ guard[0] }}], {{ guard[1] }})
|
| 35 |
+
{%- endif %}
|
| 36 |
+
{% else %}
|
| 37 |
+
select(0.0, scores[{{ index }}], {{ guard[1] }})
|
| 38 |
+
{%- endif %}
|
| 39 |
+
{% endmacro %}
|
| 40 |
+
{% set TILE_M_VALUE = materializedSgmatQueryTile %}
|
| 41 |
+
{% set TILE_N_VALUE = materializedSgmatKeyTile %}
|
| 42 |
+
{% set TILE_K_VALUE = materializedSgmatInnerTile %}
|
| 43 |
+
{% set SUB_ROWS_VALUE = materializedSgmatSubgroupTileRows if materializedSgmatSubgroupTileRows is defined else 16 %}
|
| 44 |
+
{% set SUB_COLS_VALUE = materializedSgmatSubgroupTileCols if materializedSgmatSubgroupTileCols is defined else 32 %}
|
| 45 |
+
{% set ROW_BLOCKS = (SUB_ROWS_VALUE / 8)|int %}
|
| 46 |
+
{% set COL_BLOCKS = (SUB_COLS_VALUE / 8)|int %}
|
| 47 |
+
{% set SUBGROUP_ROWS = (TILE_M_VALUE / SUB_ROWS_VALUE)|int %}
|
| 48 |
+
{% set SUBGROUP_COLS = (TILE_N_VALUE / SUB_COLS_VALUE)|int %}
|
| 49 |
+
{% set SUBGROUP_COUNT = SUBGROUP_ROWS * SUBGROUP_COLS %}
|
| 50 |
+
{% set WORKGROUP_THREADS = SUBGROUP_COUNT * 32 %}
|
| 51 |
+
{% if hasBias is not defined %}{% set hasBias = false %}{% endif %}
|
| 52 |
+
{% set EMIT_ROW_STATS = source.emitRowStats is defined and source.emitRowStats %}
|
| 53 |
+
{% set DIRECT_SCORE_STORE = materializedSgmatDirectScoreStore and not EMIT_ROW_STATS %}
|
| 54 |
+
{% set DIRECT_APPLY_STORE = materializedSgmatDirectApplyStore and not hasBias and MT == "f32" %}
|
| 55 |
+
{% set DIRECT_OUTPUT_STORE = DIRECT_SCORE_STORE if scorePhase else DIRECT_APPLY_STORE %}
|
| 56 |
+
{% set RUNTIME_DIRECT_STORE = (not DIRECT_OUTPUT_STORE)
|
| 57 |
+
and materializedSgmatRuntimeDirectStore
|
| 58 |
+
and (scorePhase or (not hasBias and MT == "f32"))
|
| 59 |
+
and not EMIT_ROW_STATS %}
|
| 60 |
+
{% set ANY_DIRECT_STORE = DIRECT_OUTPUT_STORE or RUNTIME_DIRECT_STORE %}
|
| 61 |
+
{% set SCALE_IN_Q = DIRECT_SCORE_STORE or (RUNTIME_DIRECT_STORE and scorePhase) %}
|
| 62 |
+
{% macro q_tile_value(index) %}{% if hasBias %}(query[{{ index }}] + bias[h * HEAD_DIM + k]){% else %}query[{{ index }}]{% endif %}{% if SCALE_IN_Q %} * score_scale{% endif %}{% endmacro %}
|
| 63 |
+
|
| 64 |
+
const HEADS: u32 = {{ qNumHeads }}u;
|
| 65 |
+
{% if kvNumHeads is defined %}
|
| 66 |
+
const KV_HEADS: u32 = {{ kvNumHeads }}u;
|
| 67 |
+
{% else %}
|
| 68 |
+
const KV_HEADS: u32 = HEADS;
|
| 69 |
+
{% endif %}
|
| 70 |
+
const HEAD_DIM: u32 = {{ headDim }}u;
|
| 71 |
+
const HIDDEN: u32 = {{ qHidden }}u;
|
| 72 |
+
{% if hasBias %}
|
| 73 |
+
/* Packed [Q; K; V] bias. Q folds into the query tile before the GEMM. K is
|
| 74 |
+
* omitted: expanding (q + bq).(k + bk) leaves a (q + bq).bk term that is
|
| 75 |
+
* constant across every key in the row, and softmax is invariant under that
|
| 76 |
+
* constant. V is token-independent, so sum_k p[k] * bv = bv after
|
| 77 |
+
* normalization; it is added after the apply GEMM. */
|
| 78 |
+
{% endif %}
|
| 79 |
+
{% if not kvHeadMajor %}
|
| 80 |
+
// Packed K/V rows span KV_HEADS heads, so they are narrower than the query
|
| 81 |
+
// row whenever queries are grouped. Q and the output keep HIDDEN.
|
| 82 |
+
const KV_HIDDEN: u32 = KV_HEADS * HEAD_DIM;
|
| 83 |
+
{% endif %}
|
| 84 |
+
{% if EMIT_ROW_STATS %}
|
| 85 |
+
const STAT_SLOTS: u32 = {{ statSlots }}u;
|
| 86 |
+
{% endif %}
|
| 87 |
+
const TILE_M: u32 = {{ TILE_M_VALUE }}u;
|
| 88 |
+
const TILE_N: u32 = {{ TILE_N_VALUE }}u;
|
| 89 |
+
const TILE_K: u32 = {{ TILE_K_VALUE }}u;
|
| 90 |
+
const SUB_ROWS: u32 = {{ SUB_ROWS_VALUE }}u;
|
| 91 |
+
const SUB_COLS: u32 = {{ SUB_COLS_VALUE }}u;
|
| 92 |
+
const SUBGROUP_ROWS: u32 = {{ SUBGROUP_ROWS }}u;
|
| 93 |
+
{% if (FUSED_SOFTMAX and not PRIVATE_ROW_STATS)
|
| 94 |
+
or not (TILE_M_VALUE == 64 and TILE_N_VALUE == 64 and TILE_K_VALUE == 32 and WORKGROUP_THREADS == 256) %}
|
| 95 |
+
const WORKGROUP_THREADS: u32 = {{ WORKGROUP_THREADS }}u;
|
| 96 |
+
{% endif %}
|
| 97 |
+
|
| 98 |
+
var<workgroup> tile_A: array<{{ MT }}, {{ TILE_M_VALUE * TILE_K_VALUE }}>;
|
| 99 |
+
var<workgroup> tile_B: array<{{ MT }}, {{ TILE_N_VALUE * TILE_K_VALUE }}>;
|
| 100 |
+
{% set SCRATCH = "tile_A" if MT == "f32" else "store_scratch" %}
|
| 101 |
+
{% if MT == "f16" %}
|
| 102 |
+
// The compact epilogue banks f32 result fragments; an f16 operand tile cannot
|
| 103 |
+
// alias them, so the f16 build carries a dedicated store scratch.
|
| 104 |
+
var<workgroup> store_scratch: array<f32, {{ TILE_M_VALUE * TILE_K_VALUE }}>;
|
| 105 |
+
{% endif %}
|
| 106 |
+
{% if FUSED_SOFTMAX and not PRIVATE_ROW_STATS %}
|
| 107 |
+
// The tile's rows own their softmax constants for the whole k loop, so they are
|
| 108 |
+
// read once per workgroup rather than once per staged element.
|
| 109 |
+
var<workgroup> softmax_m: array<f32, {{ TILE_M_VALUE }}>;
|
| 110 |
+
var<workgroup> softmax_d: array<f32, {{ TILE_M_VALUE }}>;
|
| 111 |
+
{% endif %}
|
| 112 |
+
{% if FUSED_SOFTMAX or EMIT_ROW_STATS %}
|
| 113 |
+
{% set stableUsage = stableHelperUsage if stableHelperUsage is defined else "all" %}
|
| 114 |
+
// FLT_MAX, not -inf, as the online (m, d) accumulator init: merges must keep
|
| 115 |
+
// `m - m` finite so an empty lane / all--inf row contributes the exact
|
| 116 |
+
// accumulator identity (m, d) = (-FLT_MAX, 0). Operator epilogues interpret
|
| 117 |
+
// a zero final denominator according to their public semantics. Using -inf
|
| 118 |
+
// here changes +inf-row behavior.
|
| 119 |
+
const FLT_MAX: f32 = 3.4028234663852886e38;
|
| 120 |
+
{% if stableUsage != "constant" %}
|
| 121 |
+
|
| 122 |
+
fn is_finite_f32(value: f32) -> bool {
|
| 123 |
+
return select(false, value <= FLT_MAX, value >= -FLT_MAX);
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
// x - m that is exactly 0 when x equals a finite m, so exp(shifted) == 1
|
| 127 |
+
// exactly at the row max. `x - x` on an infinite max is a legal fast-math
|
| 128 |
+
// fold to 0, which would silently turn +inf rows finite — the explicit
|
| 129 |
+
// equality test keeps the NaN propagation of the serial kernels.
|
| 130 |
+
fn shifted_value(value: f32, maxValue: f32) -> f32 {
|
| 131 |
+
let equalFiniteMax = select(false, value == maxValue, is_finite_f32(maxValue));
|
| 132 |
+
return select(value - maxValue, 0.0, equalFiniteMax);
|
| 133 |
+
}
|
| 134 |
+
{%- endif %}
|
| 135 |
+
{% if stableUsage == "all" %}
|
| 136 |
+
|
| 137 |
+
fn exp_shift(value: f32, maxValue: f32) -> f32 {
|
| 138 |
+
return exp(shifted_value(value, maxValue));
|
| 139 |
+
}
|
| 140 |
+
{%- endif %}
|
| 141 |
+
|
| 142 |
+
{% endif %}
|
| 143 |
+
|
| 144 |
+
@compute @workgroup_size({{ WORKGROUP_THREADS }}, 1, 1){{ " @subgroup_size(32)" if pinSubgroupSize32 else "" }}
|
| 145 |
+
fn main(
|
| 146 |
+
@builtin(workgroup_id) wg: vec3<u32>,
|
| 147 |
+
@builtin(local_invocation_index) li: u32{% if not DIRECT_OUTPUT_STORE %},
|
| 148 |
+
@builtin(subgroup_invocation_id) lane: u32{% endif %}
|
| 149 |
+
) {
|
| 150 |
+
let h = wg.z % HEADS;
|
| 151 |
+
let b = wg.z / HEADS;
|
| 152 |
+
let h_kv = h / (HEADS / KV_HEADS);
|
| 153 |
+
let m_base = wg.y * TILE_M;
|
| 154 |
+
let n_base = wg.x * TILE_N;
|
| 155 |
+
let subgroup = li / 32u;
|
| 156 |
+
let subtile_idy = subgroup % SUBGROUP_ROWS;
|
| 157 |
+
let subtile_idx = subgroup / SUBGROUP_ROWS;
|
| 158 |
+
let base_A = subtile_idy * SUB_ROWS;
|
| 159 |
+
let base_B = subtile_idx * SUB_COLS;
|
| 160 |
+
{% if USE_SEQLENS %}
|
| 161 |
+
// Rows the cache-update pass left resident: the survivors live in
|
| 162 |
+
// [0, kv_active), and every causal/window bound below uses this live length
|
| 163 |
+
// while params.kvSeq keeps the allocated capacity for strides.
|
| 164 |
+
let kv_active = min(params.kvSeq, u32(seqlens_k[b]) + 1u);
|
| 165 |
+
{% endif %}
|
| 166 |
+
{% if CAUSAL and scorePhase %}
|
| 167 |
+
// Workgroup-uniform causal skip: a key tile starting past the last row's
|
| 168 |
+
// bound holds no valid column. Publish the stats identity for its slots so
|
| 169 |
+
// the combine pass reads initialized pairs, then leave before any loads.
|
| 170 |
+
{% if SCORE_WINDOW %}
|
| 171 |
+
// A tile whose last column sits behind the FIRST row's window floor is dead
|
| 172 |
+
// the same way: later rows only move the floor further right.
|
| 173 |
+
{% endif %}
|
| 174 |
+
let kv_causal_off = i32({% if USE_SEQLENS %}kv_active{% else %}params.kvSeq{% endif %}) - i32(params.qSeq);
|
| 175 |
+
if (i32(n_base) > kv_causal_off + i32(m_base + TILE_M) - 1{% if SCORE_WINDOW %}
|
| 176 |
+
|| i32(n_base + TILE_N) <= kv_causal_off + i32(m_base) + 1 - i32(params.windowSize){% endif %}) {
|
| 177 |
+
for (var idx = li; idx < TILE_M * {{ SUBGROUP_COLS }}u; idx += {{ WORKGROUP_THREADS }}u) {
|
| 178 |
+
let stat_row = m_base + idx / {{ SUBGROUP_COLS }}u;
|
| 179 |
+
if (stat_row < params.qSeq) {
|
| 180 |
+
let slot = wg.x * {{ SUBGROUP_COLS }}u + idx % {{ SUBGROUP_COLS }}u;
|
| 181 |
+
let out_index = (((b * HEADS + h) * STAT_SLOTS + slot) * params.qSeq + stat_row) * 2u;
|
| 182 |
+
scorePartials[out_index] = -FLT_MAX;
|
| 183 |
+
scorePartials[out_index + 1u] = 0.0;
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
return;
|
| 187 |
+
}
|
| 188 |
+
{% endif %}
|
| 189 |
+
|
| 190 |
+
{% for row_block in range(ROW_BLOCKS) %}
|
| 191 |
+
{% for col_block in range(COL_BLOCKS) %}
|
| 192 |
+
var matC{{ row_block }}{{ col_block }}: subgroup_matrix_result<f32, 8, 8>;
|
| 193 |
+
{% endfor %}
|
| 194 |
+
{% endfor %}
|
| 195 |
+
|
| 196 |
+
{% if scorePhase %}
|
| 197 |
+
let inner = HEAD_DIM;
|
| 198 |
+
{% if SCALE_IN_Q %}
|
| 199 |
+
// The direct store has no epilogue, so apply the score scale to Q. Direct and
|
| 200 |
+
// guarded store paths then share one pre-scaled query tile.
|
| 201 |
+
let score_scale = {{ attentionScaleExpression }};
|
| 202 |
+
{% endif %}
|
| 203 |
+
{% else %}
|
| 204 |
+
let inner = {% if USE_SEQLENS %}kv_active{% else %}params.kvSeq{% endif %};
|
| 205 |
+
{% if CAUSAL %}
|
| 206 |
+
// Score tiles past this query tile's causal bound were never written; stop
|
| 207 |
+
// the reduction at the last written key column for the tile's rows.
|
| 208 |
+
let kv_causal_off = i32({% if USE_SEQLENS %}inner{% else %}params.kvSeq{% endif %}) - i32(params.qSeq);
|
| 209 |
+
let inner_bound = u32(clamp(kv_causal_off + i32(m_base + TILE_M), 0, i32(inner)));
|
| 210 |
+
{% if SCORE_WINDOW %}
|
| 211 |
+
// Score tiles behind every row's window floor were never written either. The
|
| 212 |
+
// floor of this tile's FIRST row is the leftmost any of its rows can reach,
|
| 213 |
+
// and rounding it down to a tile boundary only re-reads columns the score
|
| 214 |
+
// phase did write (its skip test uses whole key tiles).
|
| 215 |
+
let inner_start = (u32(max(kv_causal_off + i32(m_base) + 1 - i32(params.windowSize), 0)) / TILE_K) * TILE_K;
|
| 216 |
+
{% endif %}
|
| 217 |
+
{% endif %}
|
| 218 |
+
{% endif %}
|
| 219 |
+
{% if FUSED_SOFTMAX %}
|
| 220 |
+
{% if PRIVATE_ROW_STATS %}
|
| 221 |
+
// In the admitted BM64/BN64/BK32/WG256 loader, four adjacent lanes own the
|
| 222 |
+
// same query row for every reduction tile. Keep that row's constants private:
|
| 223 |
+
// this removes both 512 bytes of workgroup storage and the initialization
|
| 224 |
+
// barrier while preserving the exact exp/divide sequence of the shared-memory
|
| 225 |
+
// row-stats arm.
|
| 226 |
+
let private_stat_row =
|
| 227 |
+
(b * HEADS + h) * params.qSeq + min(m_base + li / 4u, params.qSeq - 1u);
|
| 228 |
+
let private_softmax_m = rowStats[private_stat_row * 2u];
|
| 229 |
+
let private_softmax_d = rowStats[private_stat_row * 2u + 1u];
|
| 230 |
+
{% else %}
|
| 231 |
+
// One row-stats pair per query row of the tile. A query tail clamps to the last
|
| 232 |
+
// real row rather than reading past the buffer; those lanes are discarded by the
|
| 233 |
+
// staging guard anyway, and the clamp keeps the denominator non-zero.
|
| 234 |
+
for (var r = li; r < TILE_M; r += WORKGROUP_THREADS) {
|
| 235 |
+
let stat_row = (b * HEADS + h) * params.qSeq + min(m_base + r, params.qSeq - 1u);
|
| 236 |
+
softmax_m[r] = rowStats[stat_row * 2u];
|
| 237 |
+
softmax_d[r] = rowStats[stat_row * 2u + 1u];
|
| 238 |
+
}
|
| 239 |
+
workgroupBarrier();
|
| 240 |
+
{% endif %}
|
| 241 |
+
{% endif %}
|
| 242 |
+
for (var k_base = {% if SCORE_WINDOW and not scorePhase %}inner_start{% else %}0u{% endif %}; k_base < {% if CAUSAL and not scorePhase %}inner_bound{% else %}inner{% endif %}; k_base += TILE_K) {
|
| 243 |
+
{% if source.phase == "apply" and not FUSED_SOFTMAX and MT == "f32" %}
|
| 244 |
+
// Full interior PV tiles can be loaded directly from storage. Query,
|
| 245 |
+
// reduction, and output-dimension tails use the guarded shared path below.
|
| 246 |
+
if (
|
| 247 |
+
k_base + TILE_K <= inner &&
|
| 248 |
+
m_base + TILE_M <= params.qSeq &&
|
| 249 |
+
n_base + TILE_N <= HEAD_DIM
|
| 250 |
+
) {
|
| 251 |
+
for (var step = 0u; step < TILE_K; step += 8u) {
|
| 252 |
+
{% for row_block in range(ROW_BLOCKS) %}
|
| 253 |
+
let score_offset{{ row_block }} = (b * HEADS + h) * params.qSeq * params.kvSeq
|
| 254 |
+
+ (m_base + base_A + {{ row_block * 8 }}u) * params.kvSeq + k_base + step;
|
| 255 |
+
var matA{{ row_block }}: subgroup_matrix_left<f32, 8, 8> =
|
| 256 |
+
subgroupMatrixLoad<subgroup_matrix_left<f32, 8, 8>, row_major>(
|
| 257 |
+
&scores, score_offset{{ row_block }}, params.kvSeq
|
| 258 |
+
);
|
| 259 |
+
{% endfor %}
|
| 260 |
+
{% for col_block in range(COL_BLOCKS) %}
|
| 261 |
+
let value_offset{{ col_block }} =
|
| 262 |
+
{{ kv_index("k_base + step", "n_base + base_B + " ~ (col_block * 8) ~ "u") }};
|
| 263 |
+
var matB{{ col_block }}: subgroup_matrix_right<f32, 8, 8> =
|
| 264 |
+
subgroupMatrixLoad<subgroup_matrix_right<f32, 8, 8>, row_major>(
|
| 265 |
+
&value, value_offset{{ col_block }}, {{ KV_ROW_STRIDE }}
|
| 266 |
+
);
|
| 267 |
+
{% endfor %}
|
| 268 |
+
{% for row_block in range(ROW_BLOCKS) %}
|
| 269 |
+
{% for col_block in range(COL_BLOCKS) %}
|
| 270 |
+
matC{{ row_block }}{{ col_block }} = subgroupMatrixMultiplyAccumulate(
|
| 271 |
+
matA{{ row_block }}, matB{{ col_block }}, matC{{ row_block }}{{ col_block }}
|
| 272 |
+
);
|
| 273 |
+
{% endfor %}
|
| 274 |
+
{% endfor %}
|
| 275 |
+
}
|
| 276 |
+
continue;
|
| 277 |
+
}
|
| 278 |
+
{% endif %}
|
| 279 |
+
|
| 280 |
+
{% if TILE_M_VALUE == 64 and TILE_N_VALUE == 64 and TILE_K_VALUE == 32 and WORKGROUP_THREADS == 256 %}
|
| 281 |
+
// BM64/BN64/WG256 is the high-throughput geometry on wide devices. Four
|
| 282 |
+
// adjacent threads each own one contiguous eight-element segment of a
|
| 283 |
+
// row, preserving the original coalesced load schedule while retaining
|
| 284 |
+
// the generalized K-tail guards.
|
| 285 |
+
let a_row = li / 4u;
|
| 286 |
+
let a_col = (li % 4u) * 8u;
|
| 287 |
+
for (var i = 0u; i < 8u; i++) {
|
| 288 |
+
let row = m_base + a_row;
|
| 289 |
+
let k = k_base + a_col + i;
|
| 290 |
+
{% if scorePhase %}
|
| 291 |
+
{% if headDim % 32 == 0 %}
|
| 292 |
+
tile_A[a_row * TILE_K + a_col + i] = select(
|
| 293 |
+
{{ "0.0h" if MT == "f16" else "0.0" }},
|
| 294 |
+
{{ q_tile_value(q_index("row", "k")) }},
|
| 295 |
+
row < params.qSeq
|
| 296 |
+
);
|
| 297 |
+
{% else %}
|
| 298 |
+
var loaded = {{ "0.0h" if MT == "f16" else "0.0" }};
|
| 299 |
+
if (row < params.qSeq && k < HEAD_DIM) {
|
| 300 |
+
loaded = {{ q_tile_value(q_index("row", "k")) }};
|
| 301 |
+
}
|
| 302 |
+
tile_A[a_row * TILE_K + a_col + i] = loaded;
|
| 303 |
+
{% endif %}
|
| 304 |
+
{% else %}
|
| 305 |
+
let score_base = (b * HEADS + h) * params.qSeq * params.kvSeq;
|
| 306 |
+
tile_A[a_row * TILE_K + a_col + i] =
|
| 307 |
+
{{ "f16(" if MT == "f16" else "" }}{{ score_value("score_base + row * params.kvSeq + k", ["a_row", "row < params.qSeq && k < params.kvSeq"]) }}{{ ")" if MT == "f16" else "" }};
|
| 308 |
+
{% endif %}
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
let b_row = li / 4u;
|
| 312 |
+
let b_col = (li % 4u) * 8u;
|
| 313 |
+
for (var i = 0u; i < 8u; i++) {
|
| 314 |
+
let col = n_base + b_row;
|
| 315 |
+
let k = k_base + b_col + i;
|
| 316 |
+
{% if scorePhase %}
|
| 317 |
+
{% if headDim % 32 == 0 %}
|
| 318 |
+
tile_B[b_row * TILE_K + b_col + i] = select(
|
| 319 |
+
{{ "0.0h" if MT == "f16" else "0.0" }},
|
| 320 |
+
key[{{ kv_index("col", "k") }}],
|
| 321 |
+
col < params.kvSeq
|
| 322 |
+
);
|
| 323 |
+
{% else %}
|
| 324 |
+
var loaded = {{ "0.0h" if MT == "f16" else "0.0" }};
|
| 325 |
+
if (col < params.kvSeq && k < HEAD_DIM) {
|
| 326 |
+
loaded = key[{{ kv_index("col", "k") }}];
|
| 327 |
+
}
|
| 328 |
+
tile_B[b_row * TILE_K + b_col + i] = loaded;
|
| 329 |
+
{% endif %}
|
| 330 |
+
{% else %}
|
| 331 |
+
tile_B[b_row * TILE_K + b_col + i] = select(
|
| 332 |
+
{{ "0.0h" if MT == "f16" else "0.0" }},
|
| 333 |
+
value[{{ kv_index("k", "col") }}],
|
| 334 |
+
k < params.kvSeq && col < HEAD_DIM
|
| 335 |
+
);
|
| 336 |
+
{% endif %}
|
| 337 |
+
}
|
| 338 |
+
{% else %}
|
| 339 |
+
// Cooperative linear loads make smaller tile dimensions independent of
|
| 340 |
+
// the selected workgroup size.
|
| 341 |
+
for (var idx = li; idx < TILE_M * TILE_K; idx += WORKGROUP_THREADS) {
|
| 342 |
+
let tile_row = idx / TILE_K;
|
| 343 |
+
let tile_k = idx % TILE_K;
|
| 344 |
+
let row = m_base + tile_row;
|
| 345 |
+
let k = k_base + tile_k;
|
| 346 |
+
{% if scorePhase %}
|
| 347 |
+
var loaded = {{ "0.0h" if MT == "f16" else "0.0" }};
|
| 348 |
+
if (row < params.qSeq && k < HEAD_DIM) {
|
| 349 |
+
loaded = {{ q_tile_value(q_index("row", "k")) }};
|
| 350 |
+
}
|
| 351 |
+
{% elif FUSED_SOFTMAX %}
|
| 352 |
+
let score_base = (b * HEADS + h) * params.qSeq * params.kvSeq;
|
| 353 |
+
let loaded =
|
| 354 |
+
{{ "f16(" if MT == "f16" else "" }}{{ score_value("score_base + row * params.kvSeq + k", ["tile_row", "row < params.qSeq && k < params.kvSeq"]) }}{{ ")" if MT == "f16" else "" }};
|
| 355 |
+
{% else %}
|
| 356 |
+
var loaded = {{ "0.0h" if MT == "f16" else "0.0" }};
|
| 357 |
+
if (row < params.qSeq && k < params.kvSeq) {
|
| 358 |
+
let score_base = (b * HEADS + h) * params.qSeq * params.kvSeq;
|
| 359 |
+
loaded = {{ "f16(" if MT == "f16" else "" }}scores[score_base + row * params.kvSeq + k]{{ ")" if MT == "f16" else "" }};
|
| 360 |
+
}
|
| 361 |
+
{% endif %}
|
| 362 |
+
tile_A[idx] = loaded;
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
for (var idx = li; idx < TILE_N * TILE_K; idx += WORKGROUP_THREADS) {
|
| 366 |
+
let tile_col = idx / TILE_K;
|
| 367 |
+
let tile_k = idx % TILE_K;
|
| 368 |
+
let col = n_base + tile_col;
|
| 369 |
+
let k = k_base + tile_k;
|
| 370 |
+
{% if scorePhase %}
|
| 371 |
+
var loaded = {{ "0.0h" if MT == "f16" else "0.0" }};
|
| 372 |
+
if (col < params.kvSeq && k < HEAD_DIM) {
|
| 373 |
+
loaded = key[{{ kv_index("col", "k") }}];
|
| 374 |
+
}
|
| 375 |
+
{% else %}
|
| 376 |
+
var loaded = {{ "0.0h" if MT == "f16" else "0.0" }};
|
| 377 |
+
if (k < params.kvSeq && col < HEAD_DIM) {
|
| 378 |
+
loaded = value[{{ kv_index("k", "col") }}];
|
| 379 |
+
}
|
| 380 |
+
{% endif %}
|
| 381 |
+
tile_B[idx] = loaded;
|
| 382 |
+
}
|
| 383 |
+
{% endif %}
|
| 384 |
+
workgroupBarrier();
|
| 385 |
+
|
| 386 |
+
for (var step = 0u; step < TILE_K; step += 8u) {
|
| 387 |
+
{% for row_block in range(ROW_BLOCKS) %}
|
| 388 |
+
let matrix_a_offset{{ row_block }} =
|
| 389 |
+
(subtile_idy * SUB_ROWS + {{ row_block * 8 }}u) * TILE_K + step;
|
| 390 |
+
var matA{{ row_block }}: subgroup_matrix_left<{{ MT }}, 8, 8> =
|
| 391 |
+
subgroupMatrixLoad<subgroup_matrix_left<{{ MT }}, 8, 8>, row_major>(
|
| 392 |
+
&tile_A, matrix_a_offset{{ row_block }}, TILE_K
|
| 393 |
+
);
|
| 394 |
+
{% endfor %}
|
| 395 |
+
{% for col_block in range(COL_BLOCKS) %}
|
| 396 |
+
let matrix_b_offset{{ col_block }} =
|
| 397 |
+
(subtile_idx * SUB_COLS + {{ col_block * 8 }}u) * TILE_K + step;
|
| 398 |
+
var matB{{ col_block }}: subgroup_matrix_right<{{ MT }}, 8, 8> =
|
| 399 |
+
subgroupMatrixLoad<subgroup_matrix_right<{{ MT }}, 8, 8>, col_major>(
|
| 400 |
+
&tile_B, matrix_b_offset{{ col_block }}, TILE_K
|
| 401 |
+
);
|
| 402 |
+
{% endfor %}
|
| 403 |
+
{% for row_block in range(ROW_BLOCKS) %}
|
| 404 |
+
{% for col_block in range(COL_BLOCKS) %}
|
| 405 |
+
matC{{ row_block }}{{ col_block }} = subgroupMatrixMultiplyAccumulate(
|
| 406 |
+
matA{{ row_block }}, matB{{ col_block }}, matC{{ row_block }}{{ col_block }}
|
| 407 |
+
);
|
| 408 |
+
{% endfor %}
|
| 409 |
+
{% endfor %}
|
| 410 |
+
}
|
| 411 |
+
workgroupBarrier();
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
{% if ANY_DIRECT_STORE %}
|
| 415 |
+
{% if RUNTIME_DIRECT_STORE %}
|
| 416 |
+
// Workgroup-uniform (both bases come from workgroup_id alone): an interior tile
|
| 417 |
+
// publishes through the subgroup-matrix collectives and is done; only an edge
|
| 418 |
+
// tile falls through to the scratch round trip and its barriers.
|
| 419 |
+
if (
|
| 420 |
+
m_base + TILE_M <= params.qSeq &&
|
| 421 |
+
n_base + TILE_N <= {% if scorePhase %}params.kvSeq{% else %}HEAD_DIM{% endif %}
|
| 422 |
+
) {
|
| 423 |
+
{% else %}
|
| 424 |
+
// Every dispatched tile is interior, so the matrices can go straight to
|
| 425 |
+
// storage without the compact scratch/readback epilogue.
|
| 426 |
+
{% endif %}
|
| 427 |
+
{% for row_block in range(ROW_BLOCKS) %}
|
| 428 |
+
{% for col_block in range(COL_BLOCKS) %}
|
| 429 |
+
{% if scorePhase %}
|
| 430 |
+
let output_offset{{ row_block }}{{ col_block }} =
|
| 431 |
+
(b * HEADS + h) * params.qSeq * params.kvSeq
|
| 432 |
+
+ (m_base + base_A + {{ row_block * 8 }}u) * params.kvSeq
|
| 433 |
+
+ n_base + base_B + {{ col_block * 8 }}u;
|
| 434 |
+
subgroupMatrixStore<row_major>(
|
| 435 |
+
&scores, output_offset{{ row_block }}{{ col_block }},
|
| 436 |
+
matC{{ row_block }}{{ col_block }}, params.kvSeq
|
| 437 |
+
);
|
| 438 |
+
{% else %}
|
| 439 |
+
let output_offset{{ row_block }}{{ col_block }} =
|
| 440 |
+
{{ q_index("m_base + base_A + " ~ (row_block * 8) ~ "u", "n_base + base_B + " ~ (col_block * 8) ~ "u") }};
|
| 441 |
+
subgroupMatrixStore<row_major>(
|
| 442 |
+
&output, output_offset{{ row_block }}{{ col_block }},
|
| 443 |
+
matC{{ row_block }}{{ col_block }}, {{ OUT_ROW_STRIDE }}
|
| 444 |
+
);
|
| 445 |
+
{% endif %}
|
| 446 |
+
{% endfor %}
|
| 447 |
+
{% endfor %}
|
| 448 |
+
{% if RUNTIME_DIRECT_STORE %}
|
| 449 |
+
return;
|
| 450 |
+
}
|
| 451 |
+
{% endif %}
|
| 452 |
+
{% endif %}
|
| 453 |
+
{% if not DIRECT_OUTPUT_STORE %}
|
| 454 |
+
let row_in_block = lane / 4u;
|
| 455 |
+
let col_in_block = (lane % 4u) * 2u;
|
| 456 |
+
{% for row_block in range(ROW_BLOCKS) %}
|
| 457 |
+
{% if row_block > 0 %}
|
| 458 |
+
// The compact path aliases the input tile as matrix-store scratch, so every
|
| 459 |
+
// lane must finish reading the preceding row block before it is overwritten.
|
| 460 |
+
workgroupBarrier();
|
| 461 |
+
{% endif %}
|
| 462 |
+
{% if EMIT_ROW_STATS %}
|
| 463 |
+
// All four lanes of this quad carry the same row (row_in_block is lane / 4),
|
| 464 |
+
// so the accumulator below is a partial over one row and the butterfly that
|
| 465 |
+
// merges it is quad-uniform — no divergent shuffle even on a query tail.
|
| 466 |
+
var stat_m{{ row_block }} = -FLT_MAX;
|
| 467 |
+
var stat_d{{ row_block }} = 0.0;
|
| 468 |
+
{% endif %}
|
| 469 |
+
{% for col_block in range(COL_BLOCKS) %}
|
| 470 |
+
subgroupMatrixStore<row_major>(
|
| 471 |
+
&{{ SCRATCH }},
|
| 472 |
+
(subgroup * {{ COL_BLOCKS }}u + {{ col_block }}u) * 64u,
|
| 473 |
+
matC{{ row_block }}{{ col_block }},
|
| 474 |
+
8u
|
| 475 |
+
);
|
| 476 |
+
{% endfor %}
|
| 477 |
+
workgroupBarrier();
|
| 478 |
+
|
| 479 |
+
{% for col_block in range(COL_BLOCKS) %}
|
| 480 |
+
for (var pair = 0u; pair < 2u; pair++) {
|
| 481 |
+
let row = m_base + base_A + {{ row_block * 8 }}u + row_in_block;
|
| 482 |
+
let col = n_base + base_B + {{ col_block * 8 }}u + col_in_block + pair;
|
| 483 |
+
if (
|
| 484 |
+
row < params.qSeq &&
|
| 485 |
+
col < {% if scorePhase %}params.kvSeq{% else %}HEAD_DIM{% endif %}
|
| 486 |
+
) {
|
| 487 |
+
let result = {{ SCRATCH }}[
|
| 488 |
+
(subgroup * {{ COL_BLOCKS }}u + {{ col_block }}u) * 64u
|
| 489 |
+
+ row_in_block * 8u + col_in_block + pair
|
| 490 |
+
];
|
| 491 |
+
{% if scorePhase %}
|
| 492 |
+
{% if not SCALE_IN_Q %}
|
| 493 |
+
let scale = {{ attentionScaleExpression }};
|
| 494 |
+
{% endif %}
|
| 495 |
+
{% if CAUSAL %}
|
| 496 |
+
var scored = result * scale;
|
| 497 |
+
{% if SCORE_BIAS %}
|
| 498 |
+
let bias_b = select(b, 0u, params.biasBatch == 1u);
|
| 499 |
+
let bias_h = select(h, 0u, params.biasHeads == 1u);
|
| 500 |
+
scored += attention_bias[
|
| 501 |
+
((bias_b * params.biasHeads + bias_h) * params.qSeq + row) * params.kvSeq + col
|
| 502 |
+
];
|
| 503 |
+
{% endif %}
|
| 504 |
+
if (i32(col) > kv_causal_off + i32(row)) { scored = -FLT_MAX; }
|
| 505 |
+
{% if SCORE_WINDOW %}
|
| 506 |
+
if (i32(col) + i32(params.windowSize) <= kv_causal_off + i32(row)) { scored = -FLT_MAX; }
|
| 507 |
+
{% endif %}
|
| 508 |
+
{% else %}
|
| 509 |
+
let scored = result{% if not SCALE_IN_Q %} * scale{% endif %};
|
| 510 |
+
{% endif %}
|
| 511 |
+
scores[
|
| 512 |
+
(b * HEADS + h) * params.qSeq * params.kvSeq + row * params.kvSeq + col
|
| 513 |
+
] = scored;
|
| 514 |
+
{% if EMIT_ROW_STATS %}
|
| 515 |
+
// Softmax sees the STORED value, so the statistics have to be taken on it
|
| 516 |
+
// and not on the raw accumulator.
|
| 517 |
+
let stat_prev = stat_m{{ row_block }};
|
| 518 |
+
stat_m{{ row_block }} = max(stat_m{{ row_block }}, scored);
|
| 519 |
+
stat_d{{ row_block }} = stat_d{{ row_block }} * exp_shift(stat_prev, stat_m{{ row_block }})
|
| 520 |
+
+ exp_shift(scored, stat_m{{ row_block }});
|
| 521 |
+
{% endif %}
|
| 522 |
+
{% else %}
|
| 523 |
+
{% if hasBias %}
|
| 524 |
+
// V bias row base: skip the packed Q and K blocks, then index this head.
|
| 525 |
+
{% endif %}
|
| 526 |
+
output[{{ q_index("row", "col") }}] = {{ "f16(" if MT == "f16" else "" }}result{{ ")" if MT == "f16" else "" }}{% if hasBias %} + bias[2u * HIDDEN + h * HEAD_DIM + col]{% endif %};
|
| 527 |
+
{% endif %}
|
| 528 |
+
}
|
| 529 |
+
}
|
| 530 |
+
{% endfor %}
|
| 531 |
+
{% if EMIT_ROW_STATS %}
|
| 532 |
+
// Butterfly the quad UNCONDITIONALLY. A lane whose row ran past the query tail
|
| 533 |
+
// never entered the guard above and still carries the exact identity
|
| 534 |
+
// (-FLT_MAX, 0), which merges to a no-op — that is cheaper than making the
|
| 535 |
+
// shuffle conditional, and a subgroup operation under a guard that only some
|
| 536 |
+
// quads of the subgroup satisfy would not be uniform.
|
| 537 |
+
{% for xor in [1, 2] %}
|
| 538 |
+
{
|
| 539 |
+
let other_m = subgroupShuffleXor(stat_m{{ row_block }}, {{ xor }}u);
|
| 540 |
+
let other_d = subgroupShuffleXor(stat_d{{ row_block }}, {{ xor }}u);
|
| 541 |
+
let merged_m = max(stat_m{{ row_block }}, other_m);
|
| 542 |
+
stat_d{{ row_block }} = stat_d{{ row_block }} * exp_shift(stat_m{{ row_block }}, merged_m)
|
| 543 |
+
+ other_d * exp_shift(other_m, merged_m);
|
| 544 |
+
stat_m{{ row_block }} = merged_m;
|
| 545 |
+
}
|
| 546 |
+
{% endfor %}
|
| 547 |
+
{
|
| 548 |
+
let stat_row = m_base + base_A + {{ row_block * 8 }}u + row_in_block;
|
| 549 |
+
if (lane % 4u == 0u && stat_row < params.qSeq) {
|
| 550 |
+
// Row is the FASTEST axis so the eight writing lanes of a subgroup land on
|
| 551 |
+
// eight consecutive pairs, and the combine pass reads a slot's whole column
|
| 552 |
+
// of rows contiguously.
|
| 553 |
+
let slot = wg.x * {{ SUBGROUP_COLS }}u + subtile_idx;
|
| 554 |
+
let out_index = (((b * HEADS + h) * STAT_SLOTS + slot) * params.qSeq + stat_row) * 2u;
|
| 555 |
+
scorePartials[out_index] = stat_m{{ row_block }};
|
| 556 |
+
scorePartials[out_index + 1u] = stat_d{{ row_block }};
|
| 557 |
+
}
|
| 558 |
+
}
|
| 559 |
+
{% endif %}
|
| 560 |
+
{% endfor %}
|
| 561 |
+
{% endif %}
|
| 562 |
+
}
|
build/webgpu/bench.json
CHANGED
|
@@ -1560,6 +1560,29 @@
|
|
| 1560 |
"source": "register-geometry gate asymmetry",
|
| 1561 |
"notes": "Cached f32 prefill at headDim 256, above the shared-memory cluster's register-geometry boundary. This guards consistent route admission between no-past and cached prefill families."
|
| 1562 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1563 |
}
|
| 1564 |
]
|
| 1565 |
}
|
|
|
|
| 1560 |
"source": "register-geometry gate asymmetry",
|
| 1561 |
"notes": "Cached f32 prefill at headDim 256, above the shared-memory cluster's register-geometry boundary. This guards consistent route admission between no-past and cached prefill families."
|
| 1562 |
}
|
| 1563 |
+
},
|
| 1564 |
+
{
|
| 1565 |
+
"name": "qwen3-prefill-32h8kv-d128-s256",
|
| 1566 |
+
"preset": "smoke",
|
| 1567 |
+
"vars": { "batch": 1, "qSeq": 256, "kvSeq": 256, "heads": 32, "kvHeads": 8, "headDim": 128 },
|
| 1568 |
+
"attrs": { "num_heads": 32, "kv_num_heads": 8, "scale": 0.08838834764831845, "causal": 0 },
|
| 1569 |
+
"inputs": {
|
| 1570 |
+
"queryT": { "shape": [1, 256, 4096], "dtype": "float32", "dist": "normal", "seed": 960, "scale": 0.2 },
|
| 1571 |
+
"keyT": { "shape": [1, 256, 1024], "dtype": "float32", "dist": "normal", "seed": 961, "scale": 0.2 },
|
| 1572 |
+
"valueT": { "shape": [1, 256, 1024], "dtype": "float32", "dist": "normal", "seed": 962, "scale": 0.2 },
|
| 1573 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [255] } },
|
| 1574 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [256] } }
|
| 1575 |
+
},
|
| 1576 |
+
"outputs": {
|
| 1577 |
+
"outputT": { "shape": [1, 256, 4096], "dtype": "float32" },
|
| 1578 |
+
"presentKeyT": { "shape": [1, 8, 256, 128], "dtype": "float32" },
|
| 1579 |
+
"presentValueT": { "shape": [1, 8, 256, 128], "dtype": "float32" }
|
| 1580 |
+
},
|
| 1581 |
+
"bench": {
|
| 1582 |
+
"metrics": [
|
| 1583 |
+
{ "type": "gflops", "value": "4 * args.batch * args.qSeq * args.kvSeq * args.heads * args.headDim" }
|
| 1584 |
+
]
|
| 1585 |
+
}
|
| 1586 |
}
|
| 1587 |
]
|
| 1588 |
}
|
build/webgpu/gqa-qprep.wgsl.jinja
CHANGED
|
@@ -8,17 +8,22 @@
|
|
| 8 |
// exactly (the present-cache K is already norm/rotary-applied, so only Q is touched),
|
| 9 |
// so the flash result is bit-identical to the cooperative/threaded path.
|
| 10 |
//
|
| 11 |
-
// f16 queries are widened before cos/sin and norm/rotary arithmetic
|
| 12 |
-
//
|
| 13 |
-
//
|
|
|
|
|
|
|
| 14 |
const HEAD_DIM: u32 = {{ headDim }}u;
|
| 15 |
const HEAD_DIM_V4: u32 = {{ headDim }}u / 4u;
|
| 16 |
const Q_HEADS: u32 = {{ qHeads }}u;
|
| 17 |
const Q_HIDDEN: u32 = {{ qHidden }}u;
|
| 18 |
const Q_HIDDEN_V4: u32 = {{ qHidden }}u / 4u;
|
| 19 |
const WG: u32 = {{ copyWorkgroupSize }}u;
|
|
|
|
| 20 |
const HALF: u32 = {{ half }}u;
|
|
|
|
| 21 |
const QK_EPS: f32 = {{ qkEps }};
|
|
|
|
| 22 |
|
| 23 |
@compute @workgroup_size(WG)
|
| 24 |
fn main(@builtin(global_invocation_id) gid: vec3<u32>,
|
|
@@ -37,10 +42,12 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>,
|
|
| 37 |
|
| 38 |
var q: array<f32, HEAD_DIM>;
|
| 39 |
for (var d = 0u; d < HEAD_DIM; d = d + 1u) { q[d] = f32(query[base + d]); }
|
|
|
|
| 40 |
var ss = 0.0;
|
| 41 |
for (var d = 0u; d < HEAD_DIM; d = d + 1u) { ss = ss + q[d] * q[d]; }
|
| 42 |
let invRms = inverseSqrt(ss / f32(HEAD_DIM) + QK_EPS);
|
| 43 |
for (var d = 0u; d < HEAD_DIM; d = d + 1u) { q[d] = q[d] * invRms * f32(q_norm_weight[d]); }
|
|
|
|
| 44 |
for (var d = 0u; d < HALF; d = d + 1u) {
|
| 45 |
let cs = f32(cos_cache[absPos * HALF + d]);
|
| 46 |
let sn = f32(sin_cache[absPos * HALF + d]);
|
|
@@ -52,6 +59,6 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>,
|
|
| 52 |
|
| 53 |
let base4 = (b * params.qSeq + s) * Q_HIDDEN_V4 + h * HEAD_DIM_V4;
|
| 54 |
for (var c = 0u; c < HEAD_DIM_V4; c = c + 1u) {
|
| 55 |
-
qout[base4 + c] = vec4<f32>(q[c * 4u], q[c * 4u + 1u], q[c * 4u + 2u], q[c * 4u + 3u]);
|
| 56 |
}
|
| 57 |
}
|
|
|
|
| 8 |
// exactly (the present-cache K is already norm/rotary-applied, so only Q is touched),
|
| 9 |
// so the flash result is bit-identical to the cooperative/threaded path.
|
| 10 |
//
|
| 11 |
+
// f16 queries are widened before cos/sin and norm/rotary arithmetic, and the
|
| 12 |
+
// rotation itself always runs in f32 — RoPE precision matters at large
|
| 13 |
+
// positions. The store narrows only for a consumer whose operand tiles are
|
| 14 |
+
// f16 anyway (the subgroup-matrix route), where a wider intermediate would be
|
| 15 |
+
// narrowed at staging regardless; every other consumer keeps the f32 output.
|
| 16 |
const HEAD_DIM: u32 = {{ headDim }}u;
|
| 17 |
const HEAD_DIM_V4: u32 = {{ headDim }}u / 4u;
|
| 18 |
const Q_HEADS: u32 = {{ qHeads }}u;
|
| 19 |
const Q_HIDDEN: u32 = {{ qHidden }}u;
|
| 20 |
const Q_HIDDEN_V4: u32 = {{ qHidden }}u / 4u;
|
| 21 |
const WG: u32 = {{ copyWorkgroupSize }}u;
|
| 22 |
+
{% set HAS_QNORM = hasQNorm is not defined or hasQNorm %}
|
| 23 |
const HALF: u32 = {{ half }}u;
|
| 24 |
+
{% if HAS_QNORM %}
|
| 25 |
const QK_EPS: f32 = {{ qkEps }};
|
| 26 |
+
{% endif %}
|
| 27 |
|
| 28 |
@compute @workgroup_size(WG)
|
| 29 |
fn main(@builtin(global_invocation_id) gid: vec3<u32>,
|
|
|
|
| 42 |
|
| 43 |
var q: array<f32, HEAD_DIM>;
|
| 44 |
for (var d = 0u; d < HEAD_DIM; d = d + 1u) { q[d] = f32(query[base + d]); }
|
| 45 |
+
{% if HAS_QNORM %}
|
| 46 |
var ss = 0.0;
|
| 47 |
for (var d = 0u; d < HEAD_DIM; d = d + 1u) { ss = ss + q[d] * q[d]; }
|
| 48 |
let invRms = inverseSqrt(ss / f32(HEAD_DIM) + QK_EPS);
|
| 49 |
for (var d = 0u; d < HEAD_DIM; d = d + 1u) { q[d] = q[d] * invRms * f32(q_norm_weight[d]); }
|
| 50 |
+
{% endif %}
|
| 51 |
for (var d = 0u; d < HALF; d = d + 1u) {
|
| 52 |
let cs = f32(cos_cache[absPos * HALF + d]);
|
| 53 |
let sn = f32(sin_cache[absPos * HALF + d]);
|
|
|
|
| 59 |
|
| 60 |
let base4 = (b * params.qSeq + s) * Q_HIDDEN_V4 + h * HEAD_DIM_V4;
|
| 61 |
for (var c = 0u; c < HEAD_DIM_V4; c = c + 1u) {
|
| 62 |
+
qout[base4 + c] = {{ "vec4<f16>(" if (qPrepF16 is defined and qPrepF16) else "" }}vec4<f32>(q[c * 4u], q[c * 4u + 1u], q[c * 4u + 2u], q[c * 4u + 3u]){{ ")" if (qPrepF16 is defined and qPrepF16) else "" }};
|
| 63 |
}
|
| 64 |
}
|
build/webgpu/manifest.json
CHANGED
|
@@ -210,13 +210,23 @@
|
|
| 210 |
"CLUSTER_TILE_K_F16": 8,
|
| 211 |
"NO_SG_TILE_K_MAX": 16,
|
| 212 |
"COOPERATIVE_WORKGROUP_SIZE": 32,
|
| 213 |
-
"CLUSTER_MAX_SLICE": 8
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
},
|
| 215 |
"derive": {
|
| 216 |
"deviceWorkgroupCap": "min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)",
|
| 217 |
"wave32Adapter": "has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize == 32 and device.adapterInfo.subgroupMaxSize == 32",
|
| 218 |
"subgroupsWave32": "device.features.has(\"subgroups\") and wave32Adapter",
|
| 219 |
"narrowSubgroupRange": "has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize < device.adapterInfo.subgroupMaxSize and device.adapterInfo.subgroupMaxSize <= 16",
|
|
|
|
|
|
|
|
|
|
| 220 |
"windowCacheRequested": "attrs.sliding_window_cache == 1",
|
| 221 |
"headDim": "dim(shapes.query, 2) / attrs.num_heads if (ranks.query == 3 and attrs.num_heads > 0) else 0",
|
| 222 |
"copyWorkgroupSize": "min(tunables.COPY_WORKGROUP_SIZE, min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX))",
|
|
@@ -310,7 +320,41 @@
|
|
| 310 |
"cachedNoSgTileBytes": "gqaHeadDim * (8 if tensorDtypes.queryT == \"float32\" else 4) + cachedNoSgReductionBytesPerKey",
|
| 311 |
"cachedNoSgTileK": "min(tunables.NO_SG_TILE_K_MAX, max(1, floor(device.limits.maxComputeWorkgroupStorageSize / cachedNoSgTileBytes)))",
|
| 312 |
"cachedNoSgWorkgroupBytes": "cachedNoSgTileK * cachedNoSgTileBytes",
|
| 313 |
-
"cachedNoSgClusterStorageOk": "cachedNoSgWorkgroupBytes <= device.limits.maxComputeWorkgroupStorageSize"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 314 |
},
|
| 315 |
"bindingSets": {
|
| 316 |
"splitAttention": [
|
|
@@ -1895,9 +1939,1306 @@
|
|
| 1895 |
]
|
| 1896 |
}
|
| 1897 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1898 |
]
|
| 1899 |
},
|
| 1900 |
"variants": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1901 |
{
|
| 1902 |
"id": "new_kv_share_append_split",
|
| 1903 |
"description": "Retains the existing cache and appends new key/value rows in separate passes before portable attention. It avoids rebuilding unchanged cache positions when the past and present allocations share capacity.",
|
|
|
|
| 210 |
"CLUSTER_TILE_K_F16": 8,
|
| 211 |
"NO_SG_TILE_K_MAX": 16,
|
| 212 |
"COOPERATIVE_WORKGROUP_SIZE": 32,
|
| 213 |
+
"CLUSTER_MAX_SLICE": 8,
|
| 214 |
+
"MATERIALIZED_SGMAT_QUERY_TILE": 64,
|
| 215 |
+
"MATERIALIZED_SGMAT_KEY_TILE": 64,
|
| 216 |
+
"MATERIALIZED_SGMAT_INNER_TILE": 32,
|
| 217 |
+
"MATERIALIZED_SOFTMAX_WORKGROUP_SIZE": 256,
|
| 218 |
+
"MATERIALIZED_SGMAT_MIN_SEQ": 256,
|
| 219 |
+
"MATERIALIZED_SGMAT_PAST_MIN_SEQ": 256,
|
| 220 |
+
"MATERIALIZED_SGMAT_WINDOW_MIN_QSEQ": 128
|
| 221 |
},
|
| 222 |
"derive": {
|
| 223 |
"deviceWorkgroupCap": "min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)",
|
| 224 |
"wave32Adapter": "has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize == 32 and device.adapterInfo.subgroupMaxSize == 32",
|
| 225 |
"subgroupsWave32": "device.features.has(\"subgroups\") and wave32Adapter",
|
| 226 |
"narrowSubgroupRange": "has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize < device.adapterInfo.subgroupMaxSize and device.adapterInfo.subgroupMaxSize <= 16",
|
| 227 |
+
"canPinSubgroupSize32": "device.features.has(\"subgroups\") and device.features.has(\"subgroup-size-control\") and has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize <= 32 and device.adapterInfo.subgroupMaxSize >= 32",
|
| 228 |
+
"pinSubgroupSize32": "canPinSubgroupSize32 and not wave32Adapter",
|
| 229 |
+
"wave32Effective": "wave32Adapter or pinSubgroupSize32",
|
| 230 |
"windowCacheRequested": "attrs.sliding_window_cache == 1",
|
| 231 |
"headDim": "dim(shapes.query, 2) / attrs.num_heads if (ranks.query == 3 and attrs.num_heads > 0) else 0",
|
| 232 |
"copyWorkgroupSize": "min(tunables.COPY_WORKGROUP_SIZE, min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX))",
|
|
|
|
| 320 |
"cachedNoSgTileBytes": "gqaHeadDim * (8 if tensorDtypes.queryT == \"float32\" else 4) + cachedNoSgReductionBytesPerKey",
|
| 321 |
"cachedNoSgTileK": "min(tunables.NO_SG_TILE_K_MAX, max(1, floor(device.limits.maxComputeWorkgroupStorageSize / cachedNoSgTileBytes)))",
|
| 322 |
"cachedNoSgWorkgroupBytes": "cachedNoSgTileK * cachedNoSgTileBytes",
|
| 323 |
+
"cachedNoSgClusterStorageOk": "cachedNoSgWorkgroupBytes <= device.limits.maxComputeWorkgroupStorageSize",
|
| 324 |
+
"gqaMatQueryTile": "tunables.MATERIALIZED_SGMAT_QUERY_TILE",
|
| 325 |
+
"gqaMatKeyTile": "tunables.MATERIALIZED_SGMAT_KEY_TILE",
|
| 326 |
+
"gqaMatInnerTile": "tunables.MATERIALIZED_SGMAT_INNER_TILE",
|
| 327 |
+
"gqaMatSubgroupRows": "floor(gqaMatQueryTile / 16)",
|
| 328 |
+
"gqaMatSubgroupCols": "floor(gqaMatKeyTile / 32)",
|
| 329 |
+
"gqaMatWorkgroupSize": "gqaMatSubgroupRows * gqaMatSubgroupCols * 32",
|
| 330 |
+
"gqaMatCompactStorageBytes": "(gqaMatQueryTile + gqaMatKeyTile) * gqaMatInnerTile * 4",
|
| 331 |
+
"gqaMatGeometryOk": "gqaMatQueryTile >= 16 and gqaMatQueryTile % 16 == 0 and gqaMatKeyTile >= 32 and gqaMatKeyTile <= 64 and gqaMatKeyTile % 32 == 0 and gqaMatInnerTile == 32 and gqaMatQueryTile >= 64 and gqaMatKeyTile >= 64",
|
| 332 |
+
"gqaMatResourcesFit": "gqaMatGeometryOk and gqaMatWorkgroupSize <= deviceWorkgroupCap and gqaMatCompactStorageBytes <= device.limits.maxComputeWorkgroupStorageSize",
|
| 333 |
+
"gqaMatScoreBytes": "dim(shapes.query, 0) * attrs.num_heads * dim(shapes.query, 1) * dim(shapes.key, 1) * 4",
|
| 334 |
+
"gqaMatScoreFits": "gqaMatScoreBytes <= device.limits.maxStorageBufferBindingSize and gqaMatScoreBytes <= device.limits.maxBufferSize",
|
| 335 |
+
"gqaMatBuffersFit": "numel(shapes.query) * 4 <= device.limits.maxStorageBufferBindingSize and numel(shapes.key) * 4 <= device.limits.maxStorageBufferBindingSize and numel(shapes.value) * 4 <= device.limits.maxStorageBufferBindingSize",
|
| 336 |
+
"gqaMatDispatchFits": "ceilDiv(dim(shapes.key, 1), gqaMatKeyTile) <= device.limits.maxComputeWorkgroupsPerDimension and ceilDiv(dim(shapes.query, 1), gqaMatQueryTile) <= device.limits.maxComputeWorkgroupsPerDimension and dim(shapes.query, 0) * attrs.num_heads <= device.limits.maxComputeWorkgroupsPerDimension",
|
| 337 |
+
"gqaMatStatSlots": "ceilDiv(dim(shapes.key, 1), gqaMatKeyTile) * gqaMatSubgroupCols",
|
| 338 |
+
"gqaMatRowStatsWg": "min(tunables.MATERIALIZED_SOFTMAX_WORKGROUP_SIZE, deviceWorkgroupCap)",
|
| 339 |
+
"gqaMatRowStatsElements": "dim(shapes.query, 0) * attrs.num_heads * dim(shapes.query, 1) * 2",
|
| 340 |
+
"gqaMatScorePartialElements": "dim(shapes.query, 0) * attrs.num_heads * gqaMatStatSlots * dim(shapes.query, 1) * 2",
|
| 341 |
+
"gqaMatCoreOk": "qkvContractOk and attrs.causal == 0 and tensorDtypes.query == \"float32\" and attrs.local_window_size == -1 and headDim >= 64 and headDim <= 256 and headDim % 16 == 0 and dim(shapes.query, 1) >= tunables.MATERIALIZED_SGMAT_MIN_SEQ and dim(shapes.key, 1) >= tunables.MATERIALIZED_SGMAT_MIN_SEQ and device.features.has(\"subgroups\") and wave32Effective and device.features.has(\"chromium-experimental-subgroup-matrix\") and gqaMatScoreFits and gqaMatBuffersFit and gqaMatResourcesFit and gqaMatDispatchFits",
|
| 342 |
+
"gqaMatPastQSeq": "dim(shapes.queryT, 1)",
|
| 343 |
+
"gqaMatPastKvSeq": "dim(shapes.presentKeyT, 2)",
|
| 344 |
+
"gqaMatPastScoreBytes": "dim(shapes.queryT, 0) * attrs.num_heads * gqaMatPastQSeq * gqaMatPastKvSeq * 4",
|
| 345 |
+
"gqaMatPastScoreFits": "gqaMatPastScoreBytes <= device.limits.maxStorageBufferBindingSize and gqaMatPastScoreBytes <= device.limits.maxBufferSize",
|
| 346 |
+
"gqaMatPastBuffersFit": "numel(shapes.queryT) * 4 <= device.limits.maxStorageBufferBindingSize and numel(shapes.presentKeyT) * 4 <= device.limits.maxStorageBufferBindingSize and numel(shapes.presentValueT) * 4 <= device.limits.maxStorageBufferBindingSize",
|
| 347 |
+
"gqaMatPastStatSlots": "ceilDiv(gqaMatPastKvSeq, gqaMatKeyTile) * gqaMatSubgroupCols",
|
| 348 |
+
"gqaMatPastRowStatsElements": "dim(shapes.queryT, 0) * attrs.num_heads * gqaMatPastQSeq * 2",
|
| 349 |
+
"gqaMatPastScorePartialElements": "dim(shapes.queryT, 0) * attrs.num_heads * gqaMatPastStatSlots * gqaMatPastQSeq * 2",
|
| 350 |
+
"gqaMatPastDispatchFits": "ceilDiv(gqaMatPastKvSeq, gqaMatKeyTile) <= device.limits.maxComputeWorkgroupsPerDimension and ceilDiv(gqaMatPastQSeq, gqaMatQueryTile) <= device.limits.maxComputeWorkgroupsPerDimension and dim(shapes.queryT, 0) * attrs.num_heads <= device.limits.maxComputeWorkgroupsPerDimension",
|
| 351 |
+
"gqaMatWindowOk": "windowShiftOk and plainAttentionOptions and tensorDtypes.queryT == \"float32\" and attrs.local_window_size > 0 and dim(shapes.queryT, 1) == dim(shapes.keyT, 1) and gqaHeadDim >= 64 and gqaHeadDim <= 256 and gqaHeadDim % 16 == 0 and dim(shapes.queryT, 1) >= tunables.MATERIALIZED_SGMAT_WINDOW_MIN_QSEQ and windowCapacity >= dim(shapes.queryT, 1) and attrs.local_window_size + dim(shapes.queryT, 1) >= windowCapacity and device.features.has(\"subgroups\") and wave32Effective and device.features.has(\"chromium-experimental-subgroup-matrix\") and gqaMatPastScoreFits and gqaMatPastBuffersFit and gqaMatResourcesFit and gqaMatPastDispatchFits",
|
| 352 |
+
"gqaMatPastCoreOk": "sharedKvFloatOk and plainAttentionOptions and tensorDtypes.queryT == \"float32\" and attrs.local_window_size == -1 and gqaHeadDim >= 64 and gqaHeadDim <= 256 and gqaHeadDim % 16 == 0 and gqaMatPastQSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= gqaMatPastQSeq and device.features.has(\"subgroups\") and wave32Effective and device.features.has(\"chromium-experimental-subgroup-matrix\") and gqaMatPastScoreFits and gqaMatPastBuffersFit and gqaMatResourcesFit and gqaMatPastDispatchFits",
|
| 353 |
+
"gqaMatPastRotaryOk": "sharedKvFloatOk and standardSoftmax and present.cosCacheT and rotaryRequested and not present.qNormWeightT and not present.attentionBiasT and not present.headSinkT and tensorDtypes.queryT == \"float32\" and attrs.local_window_size == -1 and gqaHeadDim >= 64 and gqaHeadDim <= 256 and gqaHeadDim % 16 == 0 and gqaHeadDim % 8 == 0 and gqaMatPastQSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= gqaMatPastQSeq and device.features.has(\"subgroups\") and wave32Effective and device.features.has(\"chromium-experimental-subgroup-matrix\") and gqaMatPastScoreFits and gqaMatPastBuffersFit and gqaMatResourcesFit and gqaMatPastDispatchFits",
|
| 354 |
+
"gqaMatNewPastOk": "newKvPastOk and plainAttentionOptions and tensorDtypes.queryT == \"float32\" and attrs.local_window_size == -1 and gqaHeadDim >= 64 and gqaHeadDim <= 256 and gqaHeadDim % 16 == 0 and gqaMatPastQSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= gqaMatPastQSeq and device.features.has(\"subgroups\") and wave32Effective and device.features.has(\"chromium-experimental-subgroup-matrix\") and gqaMatPastScoreFits and gqaMatPastBuffersFit and gqaMatResourcesFit and gqaMatPastDispatchFits",
|
| 355 |
+
"gqaMatPastCoreF16Ok": "sharedKvFloatOk and plainAttentionOptions and tensorDtypes.queryT == \"float16\" and device.features.has(\"shader-f16\") and attrs.local_window_size == -1 and gqaHeadDim >= 64 and gqaHeadDim <= 256 and gqaHeadDim % 16 == 0 and gqaMatPastQSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= gqaMatPastQSeq and device.features.has(\"subgroups\") and wave32Effective and device.features.has(\"chromium-experimental-subgroup-matrix\") and gqaMatPastScoreFits and gqaMatPastBuffersFit and gqaMatResourcesFit and gqaMatPastDispatchFits",
|
| 356 |
+
"gqaMatPastRotaryF16Ok": "sharedKvFloatOk and standardSoftmax and present.cosCacheT and rotaryRequested and not present.qNormWeightT and not present.attentionBiasT and not present.headSinkT and tensorDtypes.queryT == \"float16\" and device.features.has(\"shader-f16\") and attrs.local_window_size == -1 and gqaHeadDim >= 64 and gqaHeadDim <= 256 and gqaHeadDim % 16 == 0 and gqaHeadDim % 8 == 0 and gqaMatPastQSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= gqaMatPastQSeq and device.features.has(\"subgroups\") and wave32Effective and device.features.has(\"chromium-experimental-subgroup-matrix\") and gqaMatPastScoreFits and gqaMatPastBuffersFit and gqaMatResourcesFit and gqaMatPastDispatchFits",
|
| 357 |
+
"gqaMatPastBiasOk": "sharedKvFloatOk and standardSoftmax and not present.cosCacheT and not rotaryRequested and not present.qNormWeightT and not present.headSinkT and present.attentionBiasT and ranks.attentionBiasT == 4 and tensorDtypes.attentionBiasT == \"float32\" and (dim(shapes.attentionBiasT, 0) == dim(shapes.queryT, 0) or dim(shapes.attentionBiasT, 0) == 1) and (dim(shapes.attentionBiasT, 1) == attrs.num_heads or dim(shapes.attentionBiasT, 1) == 1) and dim(shapes.attentionBiasT, 2) == dim(shapes.queryT, 1) and dim(shapes.attentionBiasT, 3) == dim(shapes.presentKeyT, 2) and tensorDtypes.queryT == \"float32\" and attrs.local_window_size == -1 and gqaHeadDim >= 64 and gqaHeadDim <= 256 and gqaHeadDim % 16 == 0 and gqaMatPastQSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= tunables.MATERIALIZED_SGMAT_PAST_MIN_SEQ and gqaMatPastKvSeq >= gqaMatPastQSeq and device.features.has(\"subgroups\") and wave32Effective and device.features.has(\"chromium-experimental-subgroup-matrix\") and gqaMatPastScoreFits and gqaMatPastBuffersFit and gqaMatResourcesFit and gqaMatPastDispatchFits"
|
| 358 |
},
|
| 359 |
"bindingSets": {
|
| 360 |
"splitAttention": [
|
|
|
|
| 1939 |
]
|
| 1940 |
}
|
| 1941 |
}
|
| 1942 |
+
],
|
| 1943 |
+
"gqaMatScoreStats": [
|
| 1944 |
+
{
|
| 1945 |
+
"name": "query",
|
| 1946 |
+
"arg": "queryT",
|
| 1947 |
+
"semantic": "query",
|
| 1948 |
+
"buffer": { "type": "read-only-storage" },
|
| 1949 |
+
"elementType": "f32"
|
| 1950 |
+
},
|
| 1951 |
+
{
|
| 1952 |
+
"name": "key",
|
| 1953 |
+
"arg": "keyT",
|
| 1954 |
+
"semantic": "key",
|
| 1955 |
+
"buffer": { "type": "read-only-storage" },
|
| 1956 |
+
"elementType": "f32"
|
| 1957 |
+
},
|
| 1958 |
+
{ "name": "scores", "semantic": "materializedScores", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 1959 |
+
{
|
| 1960 |
+
"name": "scorePartials",
|
| 1961 |
+
"semantic": "materializedScorePartials",
|
| 1962 |
+
"buffer": { "type": "storage" },
|
| 1963 |
+
"elementType": "f32"
|
| 1964 |
+
},
|
| 1965 |
+
{
|
| 1966 |
+
"name": "params",
|
| 1967 |
+
"semantic": "kernel.params",
|
| 1968 |
+
"buffer": { "type": "uniform" },
|
| 1969 |
+
"struct": {
|
| 1970 |
+
"name": "Params",
|
| 1971 |
+
"fields": [
|
| 1972 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.query, 1)" },
|
| 1973 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.key, 1)" },
|
| 1974 |
+
{ "name": "scale", "type": "f32", "value": "attrs.scale if has(attrs, \"scale\") else 0" }
|
| 1975 |
+
]
|
| 1976 |
+
}
|
| 1977 |
+
}
|
| 1978 |
+
],
|
| 1979 |
+
"gqaMatRowStatsCombine": [
|
| 1980 |
+
{
|
| 1981 |
+
"name": "scorePartials",
|
| 1982 |
+
"semantic": "materializedScorePartials",
|
| 1983 |
+
"buffer": { "type": "read-only-storage" },
|
| 1984 |
+
"elementType": "f32"
|
| 1985 |
+
},
|
| 1986 |
+
{ "name": "rowStats", "semantic": "materializedRowStats", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 1987 |
+
{
|
| 1988 |
+
"name": "params",
|
| 1989 |
+
"semantic": "kernel.params",
|
| 1990 |
+
"buffer": { "type": "uniform" },
|
| 1991 |
+
"struct": {
|
| 1992 |
+
"name": "Params",
|
| 1993 |
+
"fields": [
|
| 1994 |
+
{ "name": "rows", "type": "u32", "value": "dim(shapes.query, 0) * attrs.num_heads * dim(shapes.query, 1)" }
|
| 1995 |
+
]
|
| 1996 |
+
}
|
| 1997 |
+
}
|
| 1998 |
+
],
|
| 1999 |
+
"gqaMatApplyFused": [
|
| 2000 |
+
{
|
| 2001 |
+
"name": "scores",
|
| 2002 |
+
"semantic": "materializedScores",
|
| 2003 |
+
"buffer": { "type": "read-only-storage" },
|
| 2004 |
+
"elementType": "f32"
|
| 2005 |
+
},
|
| 2006 |
+
{
|
| 2007 |
+
"name": "value",
|
| 2008 |
+
"arg": "valueT",
|
| 2009 |
+
"semantic": "value",
|
| 2010 |
+
"buffer": { "type": "read-only-storage" },
|
| 2011 |
+
"elementType": "f32"
|
| 2012 |
+
},
|
| 2013 |
+
{
|
| 2014 |
+
"name": "rowStats",
|
| 2015 |
+
"semantic": "materializedRowStats",
|
| 2016 |
+
"buffer": { "type": "read-only-storage" },
|
| 2017 |
+
"elementType": "f32"
|
| 2018 |
+
},
|
| 2019 |
+
{
|
| 2020 |
+
"name": "output",
|
| 2021 |
+
"arg": "outputT",
|
| 2022 |
+
"semantic": "output",
|
| 2023 |
+
"buffer": { "type": "storage" },
|
| 2024 |
+
"elementType": "f32"
|
| 2025 |
+
},
|
| 2026 |
+
{
|
| 2027 |
+
"name": "params",
|
| 2028 |
+
"semantic": "kernel.params",
|
| 2029 |
+
"buffer": { "type": "uniform" },
|
| 2030 |
+
"struct": {
|
| 2031 |
+
"name": "Params",
|
| 2032 |
+
"fields": [
|
| 2033 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.query, 1)" },
|
| 2034 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.key, 1)" }
|
| 2035 |
+
]
|
| 2036 |
+
}
|
| 2037 |
+
}
|
| 2038 |
+
],
|
| 2039 |
+
"gqaMatPastScoreStats": [
|
| 2040 |
+
{ "name": "query", "arg": "queryT", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2041 |
+
{ "name": "key", "arg": "presentKeyT", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2042 |
+
{ "name": "scores", "semantic": "materializedScores", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 2043 |
+
{
|
| 2044 |
+
"name": "scorePartials",
|
| 2045 |
+
"semantic": "materializedScorePartials",
|
| 2046 |
+
"buffer": { "type": "storage" },
|
| 2047 |
+
"elementType": "f32"
|
| 2048 |
+
},
|
| 2049 |
+
{
|
| 2050 |
+
"name": "params",
|
| 2051 |
+
"semantic": "kernel.params",
|
| 2052 |
+
"buffer": { "type": "uniform" },
|
| 2053 |
+
"struct": {
|
| 2054 |
+
"name": "Params",
|
| 2055 |
+
"fields": [
|
| 2056 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2057 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.presentKeyT, 2)" },
|
| 2058 |
+
{ "name": "scale", "type": "f32", "value": "attrs.scale if attrs.scale else 0" }
|
| 2059 |
+
]
|
| 2060 |
+
}
|
| 2061 |
+
}
|
| 2062 |
+
],
|
| 2063 |
+
"gqaMatWindowScoreStats": [
|
| 2064 |
+
{ "name": "query", "arg": "queryT", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2065 |
+
{ "name": "key", "arg": "presentKeyT", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2066 |
+
{ "name": "scores", "semantic": "materializedScores", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 2067 |
+
{
|
| 2068 |
+
"name": "scorePartials",
|
| 2069 |
+
"semantic": "materializedScorePartials",
|
| 2070 |
+
"buffer": { "type": "storage" },
|
| 2071 |
+
"elementType": "f32"
|
| 2072 |
+
},
|
| 2073 |
+
{ "name": "seqlens_k", "arg": "seqlensKT", "buffer": { "type": "read-only-storage" }, "elementType": "i32" },
|
| 2074 |
+
{
|
| 2075 |
+
"name": "params",
|
| 2076 |
+
"semantic": "kernel.params",
|
| 2077 |
+
"buffer": { "type": "uniform" },
|
| 2078 |
+
"struct": {
|
| 2079 |
+
"name": "Params",
|
| 2080 |
+
"fields": [
|
| 2081 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2082 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.presentKeyT, 2)" },
|
| 2083 |
+
{ "name": "windowSize", "type": "u32", "value": "attrs.local_window_size" },
|
| 2084 |
+
{ "name": "scale", "type": "f32", "value": "attrs.scale if attrs.scale else 0" }
|
| 2085 |
+
]
|
| 2086 |
+
}
|
| 2087 |
+
}
|
| 2088 |
+
],
|
| 2089 |
+
"gqaMatWindowApplyFused": [
|
| 2090 |
+
{
|
| 2091 |
+
"name": "scores",
|
| 2092 |
+
"semantic": "materializedScores",
|
| 2093 |
+
"buffer": { "type": "read-only-storage" },
|
| 2094 |
+
"elementType": "f32"
|
| 2095 |
+
},
|
| 2096 |
+
{ "name": "value", "arg": "presentValueT", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2097 |
+
{
|
| 2098 |
+
"name": "rowStats",
|
| 2099 |
+
"semantic": "materializedRowStats",
|
| 2100 |
+
"buffer": { "type": "read-only-storage" },
|
| 2101 |
+
"elementType": "f32"
|
| 2102 |
+
},
|
| 2103 |
+
{ "name": "output", "arg": "outputT", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 2104 |
+
{ "name": "seqlens_k", "arg": "seqlensKT", "buffer": { "type": "read-only-storage" }, "elementType": "i32" },
|
| 2105 |
+
{
|
| 2106 |
+
"name": "params",
|
| 2107 |
+
"semantic": "kernel.params",
|
| 2108 |
+
"buffer": { "type": "uniform" },
|
| 2109 |
+
"struct": {
|
| 2110 |
+
"name": "Params",
|
| 2111 |
+
"fields": [
|
| 2112 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2113 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.presentKeyT, 2)" },
|
| 2114 |
+
{ "name": "windowSize", "type": "u32", "value": "attrs.local_window_size" }
|
| 2115 |
+
]
|
| 2116 |
+
}
|
| 2117 |
+
}
|
| 2118 |
+
],
|
| 2119 |
+
"gqaMatPastRotaryScoreStats": [
|
| 2120 |
+
{ "name": "query", "semantic": "qPrep", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2121 |
+
{ "name": "key", "arg": "presentKeyT", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2122 |
+
{ "name": "scores", "semantic": "materializedScores", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 2123 |
+
{
|
| 2124 |
+
"name": "scorePartials",
|
| 2125 |
+
"semantic": "materializedScorePartials",
|
| 2126 |
+
"buffer": { "type": "storage" },
|
| 2127 |
+
"elementType": "f32"
|
| 2128 |
+
},
|
| 2129 |
+
{
|
| 2130 |
+
"name": "params",
|
| 2131 |
+
"semantic": "kernel.params",
|
| 2132 |
+
"buffer": { "type": "uniform" },
|
| 2133 |
+
"struct": {
|
| 2134 |
+
"name": "Params",
|
| 2135 |
+
"fields": [
|
| 2136 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2137 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.presentKeyT, 2)" },
|
| 2138 |
+
{ "name": "scale", "type": "f32", "value": "attrs.scale if attrs.scale else 0" }
|
| 2139 |
+
]
|
| 2140 |
+
}
|
| 2141 |
+
}
|
| 2142 |
+
],
|
| 2143 |
+
"rotaryQprep": [
|
| 2144 |
+
{ "name": "query", "arg": "queryT", "buffer": { "type": "read-only-storage" }, "elementType": "$inputScalar" },
|
| 2145 |
+
{
|
| 2146 |
+
"name": "cos_cache",
|
| 2147 |
+
"arg": "cosCacheT",
|
| 2148 |
+
"buffer": { "type": "read-only-storage" },
|
| 2149 |
+
"elementType": "$cosScalar"
|
| 2150 |
+
},
|
| 2151 |
+
{
|
| 2152 |
+
"name": "sin_cache",
|
| 2153 |
+
"arg": "sinCacheT",
|
| 2154 |
+
"buffer": { "type": "read-only-storage" },
|
| 2155 |
+
"elementType": "$cosScalar"
|
| 2156 |
+
},
|
| 2157 |
+
{ "name": "qout", "semantic": "qPrep", "buffer": { "type": "storage" }, "elementType": "vec4<f32>" },
|
| 2158 |
+
{
|
| 2159 |
+
"name": "params",
|
| 2160 |
+
"semantic": "kernel.params",
|
| 2161 |
+
"buffer": { "type": "uniform" },
|
| 2162 |
+
"struct": {
|
| 2163 |
+
"name": "Params",
|
| 2164 |
+
"fields": [
|
| 2165 |
+
{ "name": "batch", "type": "u32", "value": "dim(shapes.queryT, 0)" },
|
| 2166 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2167 |
+
{ "name": "totalSeq", "type": "u32", "value": "dim(shapes.pastKeyT, 2)" }
|
| 2168 |
+
]
|
| 2169 |
+
}
|
| 2170 |
+
}
|
| 2171 |
+
],
|
| 2172 |
+
"gqaMatPastRowStatsCombine": [
|
| 2173 |
+
{
|
| 2174 |
+
"name": "scorePartials",
|
| 2175 |
+
"semantic": "materializedScorePartials",
|
| 2176 |
+
"buffer": { "type": "read-only-storage" },
|
| 2177 |
+
"elementType": "f32"
|
| 2178 |
+
},
|
| 2179 |
+
{ "name": "rowStats", "semantic": "materializedRowStats", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 2180 |
+
{
|
| 2181 |
+
"name": "params",
|
| 2182 |
+
"semantic": "kernel.params",
|
| 2183 |
+
"buffer": { "type": "uniform" },
|
| 2184 |
+
"struct": {
|
| 2185 |
+
"name": "Params",
|
| 2186 |
+
"fields": [
|
| 2187 |
+
{
|
| 2188 |
+
"name": "rows",
|
| 2189 |
+
"type": "u32",
|
| 2190 |
+
"value": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)"
|
| 2191 |
+
}
|
| 2192 |
+
]
|
| 2193 |
+
}
|
| 2194 |
+
}
|
| 2195 |
+
],
|
| 2196 |
+
"gqaMatPastApplyFused": [
|
| 2197 |
+
{
|
| 2198 |
+
"name": "scores",
|
| 2199 |
+
"semantic": "materializedScores",
|
| 2200 |
+
"buffer": { "type": "read-only-storage" },
|
| 2201 |
+
"elementType": "f32"
|
| 2202 |
+
},
|
| 2203 |
+
{ "name": "value", "arg": "presentValueT", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2204 |
+
{
|
| 2205 |
+
"name": "rowStats",
|
| 2206 |
+
"semantic": "materializedRowStats",
|
| 2207 |
+
"buffer": { "type": "read-only-storage" },
|
| 2208 |
+
"elementType": "f32"
|
| 2209 |
+
},
|
| 2210 |
+
{ "name": "output", "arg": "outputT", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 2211 |
+
{
|
| 2212 |
+
"name": "params",
|
| 2213 |
+
"semantic": "kernel.params",
|
| 2214 |
+
"buffer": { "type": "uniform" },
|
| 2215 |
+
"struct": {
|
| 2216 |
+
"name": "Params",
|
| 2217 |
+
"fields": [
|
| 2218 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2219 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.presentKeyT, 2)" }
|
| 2220 |
+
]
|
| 2221 |
+
}
|
| 2222 |
+
}
|
| 2223 |
+
],
|
| 2224 |
+
"gqaMatPastScoreStatsF16": [
|
| 2225 |
+
{ "name": "query", "arg": "queryT", "buffer": { "type": "read-only-storage" }, "elementType": "f16" },
|
| 2226 |
+
{ "name": "key", "arg": "presentKeyT", "buffer": { "type": "read-only-storage" }, "elementType": "f16" },
|
| 2227 |
+
{ "name": "scores", "semantic": "materializedScores", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 2228 |
+
{
|
| 2229 |
+
"name": "scorePartials",
|
| 2230 |
+
"semantic": "materializedScorePartials",
|
| 2231 |
+
"buffer": { "type": "storage" },
|
| 2232 |
+
"elementType": "f32"
|
| 2233 |
+
},
|
| 2234 |
+
{
|
| 2235 |
+
"name": "params",
|
| 2236 |
+
"semantic": "kernel.params",
|
| 2237 |
+
"buffer": { "type": "uniform" },
|
| 2238 |
+
"struct": {
|
| 2239 |
+
"name": "Params",
|
| 2240 |
+
"fields": [
|
| 2241 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2242 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.presentKeyT, 2)" },
|
| 2243 |
+
{ "name": "scale", "type": "f32", "value": "attrs.scale if attrs.scale else 0" }
|
| 2244 |
+
]
|
| 2245 |
+
}
|
| 2246 |
+
}
|
| 2247 |
+
],
|
| 2248 |
+
"gqaMatPastApplyFusedF16": [
|
| 2249 |
+
{
|
| 2250 |
+
"name": "scores",
|
| 2251 |
+
"semantic": "materializedScores",
|
| 2252 |
+
"buffer": { "type": "read-only-storage" },
|
| 2253 |
+
"elementType": "f32"
|
| 2254 |
+
},
|
| 2255 |
+
{ "name": "value", "arg": "presentValueT", "buffer": { "type": "read-only-storage" }, "elementType": "f16" },
|
| 2256 |
+
{
|
| 2257 |
+
"name": "rowStats",
|
| 2258 |
+
"semantic": "materializedRowStats",
|
| 2259 |
+
"buffer": { "type": "read-only-storage" },
|
| 2260 |
+
"elementType": "f32"
|
| 2261 |
+
},
|
| 2262 |
+
{ "name": "output", "arg": "outputT", "buffer": { "type": "storage" }, "elementType": "f16" },
|
| 2263 |
+
{
|
| 2264 |
+
"name": "params",
|
| 2265 |
+
"semantic": "kernel.params",
|
| 2266 |
+
"buffer": { "type": "uniform" },
|
| 2267 |
+
"struct": {
|
| 2268 |
+
"name": "Params",
|
| 2269 |
+
"fields": [
|
| 2270 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2271 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.presentKeyT, 2)" }
|
| 2272 |
+
]
|
| 2273 |
+
}
|
| 2274 |
+
}
|
| 2275 |
+
],
|
| 2276 |
+
"gqaMatPastRotaryScoreStatsF16": [
|
| 2277 |
+
{ "name": "query", "semantic": "qPrep", "buffer": { "type": "read-only-storage" }, "elementType": "f16" },
|
| 2278 |
+
{ "name": "key", "arg": "presentKeyT", "buffer": { "type": "read-only-storage" }, "elementType": "f16" },
|
| 2279 |
+
{ "name": "scores", "semantic": "materializedScores", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 2280 |
+
{
|
| 2281 |
+
"name": "scorePartials",
|
| 2282 |
+
"semantic": "materializedScorePartials",
|
| 2283 |
+
"buffer": { "type": "storage" },
|
| 2284 |
+
"elementType": "f32"
|
| 2285 |
+
},
|
| 2286 |
+
{
|
| 2287 |
+
"name": "params",
|
| 2288 |
+
"semantic": "kernel.params",
|
| 2289 |
+
"buffer": { "type": "uniform" },
|
| 2290 |
+
"struct": {
|
| 2291 |
+
"name": "Params",
|
| 2292 |
+
"fields": [
|
| 2293 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2294 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.presentKeyT, 2)" },
|
| 2295 |
+
{ "name": "scale", "type": "f32", "value": "attrs.scale if attrs.scale else 0" }
|
| 2296 |
+
]
|
| 2297 |
+
}
|
| 2298 |
+
}
|
| 2299 |
+
],
|
| 2300 |
+
"rotaryQprepF16": [
|
| 2301 |
+
{ "name": "query", "arg": "queryT", "buffer": { "type": "read-only-storage" }, "elementType": "$inputScalar" },
|
| 2302 |
+
{
|
| 2303 |
+
"name": "cos_cache",
|
| 2304 |
+
"arg": "cosCacheT",
|
| 2305 |
+
"buffer": { "type": "read-only-storage" },
|
| 2306 |
+
"elementType": "$cosScalar"
|
| 2307 |
+
},
|
| 2308 |
+
{
|
| 2309 |
+
"name": "sin_cache",
|
| 2310 |
+
"arg": "sinCacheT",
|
| 2311 |
+
"buffer": { "type": "read-only-storage" },
|
| 2312 |
+
"elementType": "$cosScalar"
|
| 2313 |
+
},
|
| 2314 |
+
{ "name": "qout", "semantic": "qPrep", "buffer": { "type": "storage" }, "elementType": "vec4<f16>" },
|
| 2315 |
+
{
|
| 2316 |
+
"name": "params",
|
| 2317 |
+
"semantic": "kernel.params",
|
| 2318 |
+
"buffer": { "type": "uniform" },
|
| 2319 |
+
"struct": {
|
| 2320 |
+
"name": "Params",
|
| 2321 |
+
"fields": [
|
| 2322 |
+
{ "name": "batch", "type": "u32", "value": "dim(shapes.queryT, 0)" },
|
| 2323 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2324 |
+
{ "name": "totalSeq", "type": "u32", "value": "dim(shapes.pastKeyT, 2)" }
|
| 2325 |
+
]
|
| 2326 |
+
}
|
| 2327 |
+
}
|
| 2328 |
+
],
|
| 2329 |
+
"gqaMatPastBiasScoreStats": [
|
| 2330 |
+
{ "name": "query", "arg": "queryT", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2331 |
+
{ "name": "key", "arg": "presentKeyT", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 2332 |
+
{
|
| 2333 |
+
"name": "attention_bias",
|
| 2334 |
+
"arg": "attentionBiasT",
|
| 2335 |
+
"buffer": { "type": "read-only-storage" },
|
| 2336 |
+
"elementType": "f32"
|
| 2337 |
+
},
|
| 2338 |
+
{ "name": "scores", "semantic": "materializedScores", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 2339 |
+
{
|
| 2340 |
+
"name": "scorePartials",
|
| 2341 |
+
"semantic": "materializedScorePartials",
|
| 2342 |
+
"buffer": { "type": "storage" },
|
| 2343 |
+
"elementType": "f32"
|
| 2344 |
+
},
|
| 2345 |
+
{
|
| 2346 |
+
"name": "params",
|
| 2347 |
+
"semantic": "kernel.params",
|
| 2348 |
+
"buffer": { "type": "uniform" },
|
| 2349 |
+
"struct": {
|
| 2350 |
+
"name": "Params",
|
| 2351 |
+
"fields": [
|
| 2352 |
+
{ "name": "qSeq", "type": "u32", "value": "dim(shapes.queryT, 1)" },
|
| 2353 |
+
{ "name": "kvSeq", "type": "u32", "value": "dim(shapes.presentKeyT, 2)" },
|
| 2354 |
+
{ "name": "scale", "type": "f32", "value": "attrs.scale if attrs.scale else 0" },
|
| 2355 |
+
{ "name": "biasBatch", "type": "u32", "value": "dim(shapes.attentionBiasT, 0)" },
|
| 2356 |
+
{ "name": "biasHeads", "type": "u32", "value": "dim(shapes.attentionBiasT, 1)" }
|
| 2357 |
+
]
|
| 2358 |
+
}
|
| 2359 |
+
}
|
| 2360 |
]
|
| 2361 |
},
|
| 2362 |
"variants": [
|
| 2363 |
+
{
|
| 2364 |
+
"id": "qkv_present_materialized_sgmat_f32",
|
| 2365 |
+
"description": "Materialized float32 subgroup-matrix prefill for the bidirectional no-past qkv route, where `seqlens_k` is metadata-only like the flash routes: the score pass emits per-row softmax statistics, the apply pass folds the softmax, and the present copy is unchanged. It serves square-ish f32 prefill where the score and value GEMMs dominate.",
|
| 2366 |
+
"priority": 23,
|
| 2367 |
+
"requires": {
|
| 2368 |
+
"features": ["subgroups", "chromium-experimental-subgroup-matrix"],
|
| 2369 |
+
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 2370 |
+
},
|
| 2371 |
+
"when": ["gqaMatCoreOk"],
|
| 2372 |
+
"constants": {
|
| 2373 |
+
"qNumHeads": "attrs.num_heads",
|
| 2374 |
+
"kvNumHeads": "attrs.kv_num_heads",
|
| 2375 |
+
"headDim": "dim(shapes.query, 2) / attrs.num_heads",
|
| 2376 |
+
"qHidden": "dim(shapes.query, 2)",
|
| 2377 |
+
"kvHidden": "dim(shapes.key, 2)",
|
| 2378 |
+
"hasBias": false,
|
| 2379 |
+
"useSubgroups": true,
|
| 2380 |
+
"attentionScaleExpression": "\"select(inverseSqrt(f32(HEAD_DIM)), params.scale, params.scale != 0.0)\"",
|
| 2381 |
+
"materializedSgmatQueryTile": "gqaMatQueryTile",
|
| 2382 |
+
"materializedSgmatKeyTile": "gqaMatKeyTile",
|
| 2383 |
+
"materializedSgmatInnerTile": "gqaMatInnerTile",
|
| 2384 |
+
"materializedSgmatDirectScoreStore": false,
|
| 2385 |
+
"materializedSgmatDirectApplyStore": false,
|
| 2386 |
+
"materializedSgmatRuntimeDirectStore": false,
|
| 2387 |
+
"materializedRowStatsWg": "gqaMatRowStatsWg",
|
| 2388 |
+
"statSlots": "gqaMatStatSlots",
|
| 2389 |
+
"statQuerySeq": "dim(shapes.query, 1)",
|
| 2390 |
+
"presentScalar": "qkvCacheScalar",
|
| 2391 |
+
"presentElement": "qkvCacheVec4",
|
| 2392 |
+
"presentVec4": true,
|
| 2393 |
+
"copyWorkgroupSize": "copyWorkgroupSize",
|
| 2394 |
+
"inputElement": "qkvInputVec4",
|
| 2395 |
+
"headDimV4": "(dim(shapes.query, 2) / attrs.num_heads) / 4",
|
| 2396 |
+
"kvHiddenV4": "dim(shapes.key, 2) / 4"
|
| 2397 |
+
},
|
| 2398 |
+
"intermediates": [
|
| 2399 |
+
{
|
| 2400 |
+
"id": "materializedScores",
|
| 2401 |
+
"dtype": "float32",
|
| 2402 |
+
"shape": "[dim(shapes.query, 0) * attrs.num_heads * dim(shapes.query, 1) * dim(shapes.key, 1)]"
|
| 2403 |
+
},
|
| 2404 |
+
{ "id": "materializedRowStats", "dtype": "float32", "shape": "[gqaMatRowStatsElements]" },
|
| 2405 |
+
{ "id": "materializedScorePartials", "dtype": "float32", "shape": "[gqaMatScorePartialElements]" }
|
| 2406 |
+
],
|
| 2407 |
+
"passes": [
|
| 2408 |
+
{
|
| 2409 |
+
"id": "scores",
|
| 2410 |
+
"name": "GroupQueryAttention.MaterializedScoresSgmat",
|
| 2411 |
+
"source": {
|
| 2412 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2413 |
+
"inputs": { "phase": "\"score\"", "emitRowStats": true, "layout": "\"bsh\"" }
|
| 2414 |
+
},
|
| 2415 |
+
"bindings": "gqaMatScoreStats",
|
| 2416 |
+
"dispatch": {
|
| 2417 |
+
"x": "ceilDiv(dim(shapes.key, 1), gqaMatKeyTile)",
|
| 2418 |
+
"y": "ceilDiv(dim(shapes.query, 1), gqaMatQueryTile)",
|
| 2419 |
+
"z": "dim(shapes.query, 0) * attrs.num_heads"
|
| 2420 |
+
}
|
| 2421 |
+
},
|
| 2422 |
+
{
|
| 2423 |
+
"id": "rowstats",
|
| 2424 |
+
"name": "GroupQueryAttention.MaterializedRowStatsCombine",
|
| 2425 |
+
"source": { "shader": "attn-materialized-rowstats-combine-f32.wgsl.jinja" },
|
| 2426 |
+
"bindings": "gqaMatRowStatsCombine",
|
| 2427 |
+
"dispatch": {
|
| 2428 |
+
"gridStride": "dim(shapes.query, 0) * attrs.num_heads * dim(shapes.query, 1)",
|
| 2429 |
+
"workgroupSize": "gqaMatRowStatsWg"
|
| 2430 |
+
}
|
| 2431 |
+
},
|
| 2432 |
+
{
|
| 2433 |
+
"id": "apply",
|
| 2434 |
+
"name": "GroupQueryAttention.MaterializedApplySgmat",
|
| 2435 |
+
"source": {
|
| 2436 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2437 |
+
"inputs": { "phase": "\"apply\"", "fusedSoftmax": true, "layout": "\"bsh\"" }
|
| 2438 |
+
},
|
| 2439 |
+
"bindings": "gqaMatApplyFused",
|
| 2440 |
+
"dispatch": {
|
| 2441 |
+
"x": "ceilDiv(headDim, gqaMatKeyTile)",
|
| 2442 |
+
"y": "ceilDiv(dim(shapes.query, 1), gqaMatQueryTile)",
|
| 2443 |
+
"z": "dim(shapes.query, 0) * attrs.num_heads"
|
| 2444 |
+
}
|
| 2445 |
+
},
|
| 2446 |
+
{
|
| 2447 |
+
"id": "present",
|
| 2448 |
+
"name": "GroupQueryAttention.MaterializedPresent",
|
| 2449 |
+
"shader": "gqa-present.wgsl.jinja",
|
| 2450 |
+
"bindings": "qkvPresent",
|
| 2451 |
+
"dispatch": { "threads": "numel(shapes.presentKeyT) / 4", "workgroupSize": "constants.copyWorkgroupSize" }
|
| 2452 |
+
}
|
| 2453 |
+
]
|
| 2454 |
+
},
|
| 2455 |
+
{
|
| 2456 |
+
"id": "past_kv_materialized_sgmat_f32",
|
| 2457 |
+
"requires": {
|
| 2458 |
+
"features": ["subgroups", "chromium-experimental-subgroup-matrix"],
|
| 2459 |
+
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 2460 |
+
},
|
| 2461 |
+
"description": "Materializes the causal score matrix with float32 subgroup-matrix tiles over the shared float cache and applies the softmax-normalized weights with the same tiles. The score pass skips key tiles past each query tile's causal bound and the apply pass stops its reduction there, matching flash's triangular work at matrix-unit throughput.",
|
| 2462 |
+
"priority": 35,
|
| 2463 |
+
"when": ["gqaMatPastCoreOk"],
|
| 2464 |
+
"constants": {
|
| 2465 |
+
"qNumHeads": "attrs.num_heads",
|
| 2466 |
+
"kvNumHeads": "attrs.kv_num_heads",
|
| 2467 |
+
"headDim": "gqaHeadDim",
|
| 2468 |
+
"qHidden": "dim(shapes.queryT, 2)",
|
| 2469 |
+
"hasBias": false,
|
| 2470 |
+
"useSubgroups": true,
|
| 2471 |
+
"attentionScaleExpression": "\"select(inverseSqrt(f32(HEAD_DIM)), params.scale, params.scale != 0.0)\"",
|
| 2472 |
+
"materializedSgmatQueryTile": "gqaMatQueryTile",
|
| 2473 |
+
"materializedSgmatKeyTile": "gqaMatKeyTile",
|
| 2474 |
+
"materializedSgmatInnerTile": "gqaMatInnerTile",
|
| 2475 |
+
"materializedSgmatDirectScoreStore": false,
|
| 2476 |
+
"materializedSgmatDirectApplyStore": false,
|
| 2477 |
+
"materializedSgmatRuntimeDirectStore": false,
|
| 2478 |
+
"materializedRowStatsWg": "gqaMatRowStatsWg",
|
| 2479 |
+
"statSlots": "gqaMatPastStatSlots",
|
| 2480 |
+
"statQuerySeq": "dim(shapes.queryT, 1)",
|
| 2481 |
+
"mode": "\"copy\"",
|
| 2482 |
+
"packed": "gqaHeadDim",
|
| 2483 |
+
"kvHeads": "attrs.kv_num_heads",
|
| 2484 |
+
"inputScalar": "gqaScalar",
|
| 2485 |
+
"usesF16": false,
|
| 2486 |
+
"copyWorkgroupSize": "copyWorkgroupSize"
|
| 2487 |
+
},
|
| 2488 |
+
"intermediates": [
|
| 2489 |
+
{
|
| 2490 |
+
"id": "materializedScores",
|
| 2491 |
+
"dtype": "float32",
|
| 2492 |
+
"shape": "[dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1) * dim(shapes.presentKeyT, 2)]"
|
| 2493 |
+
},
|
| 2494 |
+
{ "id": "materializedRowStats", "dtype": "float32", "shape": "[gqaMatPastRowStatsElements]" },
|
| 2495 |
+
{ "id": "materializedScorePartials", "dtype": "float32", "shape": "[gqaMatPastScorePartialElements]" }
|
| 2496 |
+
],
|
| 2497 |
+
"passes": [
|
| 2498 |
+
{
|
| 2499 |
+
"id": "present",
|
| 2500 |
+
"name": "GroupQueryAttention.Present",
|
| 2501 |
+
"shader": "gqa-present.wgsl.jinja",
|
| 2502 |
+
"bindings": "presentCopy",
|
| 2503 |
+
"dispatch": {
|
| 2504 |
+
"threads": "dim(shapes.queryT, 0) * attrs.kv_num_heads * dim(shapes.pastKeyT, 2)",
|
| 2505 |
+
"workgroupSize": "copyWorkgroupSize"
|
| 2506 |
+
},
|
| 2507 |
+
"viewAlias": [{ "input": "src_k", "output": "present_key" }, { "input": "src_v", "output": "present_value" }]
|
| 2508 |
+
},
|
| 2509 |
+
{
|
| 2510 |
+
"id": "scores",
|
| 2511 |
+
"name": "GroupQueryAttention.PastMaterializedScores",
|
| 2512 |
+
"source": {
|
| 2513 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2514 |
+
"inputs": {
|
| 2515 |
+
"phase": "\"score\"",
|
| 2516 |
+
"emitRowStats": true,
|
| 2517 |
+
"layout": "\"bsh\"",
|
| 2518 |
+
"kvLayout": "\"bhsd\"",
|
| 2519 |
+
"causalRightAlign": true
|
| 2520 |
+
}
|
| 2521 |
+
},
|
| 2522 |
+
"bindings": "gqaMatPastScoreStats",
|
| 2523 |
+
"dispatch": {
|
| 2524 |
+
"x": "ceilDiv(dim(shapes.presentKeyT, 2), gqaMatKeyTile)",
|
| 2525 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 2526 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 2527 |
+
}
|
| 2528 |
+
},
|
| 2529 |
+
{
|
| 2530 |
+
"id": "rowstats",
|
| 2531 |
+
"name": "GroupQueryAttention.PastMaterializedRowStats",
|
| 2532 |
+
"source": { "shader": "attn-materialized-rowstats-combine-f32.wgsl.jinja", "inputs": {} },
|
| 2533 |
+
"bindings": "gqaMatPastRowStatsCombine",
|
| 2534 |
+
"dispatch": {
|
| 2535 |
+
"gridStride": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)",
|
| 2536 |
+
"workgroupSize": "gqaMatRowStatsWg"
|
| 2537 |
+
}
|
| 2538 |
+
},
|
| 2539 |
+
{
|
| 2540 |
+
"id": "apply",
|
| 2541 |
+
"name": "GroupQueryAttention.PastMaterializedApply",
|
| 2542 |
+
"source": {
|
| 2543 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2544 |
+
"inputs": {
|
| 2545 |
+
"phase": "\"apply\"",
|
| 2546 |
+
"fusedSoftmax": true,
|
| 2547 |
+
"layout": "\"bsh\"",
|
| 2548 |
+
"kvLayout": "\"bhsd\"",
|
| 2549 |
+
"causalRightAlign": true
|
| 2550 |
+
}
|
| 2551 |
+
},
|
| 2552 |
+
"bindings": "gqaMatPastApplyFused",
|
| 2553 |
+
"dispatch": {
|
| 2554 |
+
"x": "ceilDiv(gqaHeadDim, gqaMatKeyTile)",
|
| 2555 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 2556 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 2557 |
+
}
|
| 2558 |
+
}
|
| 2559 |
+
]
|
| 2560 |
+
},
|
| 2561 |
+
{
|
| 2562 |
+
"id": "past_kv_bias_materialized_sgmat_f32",
|
| 2563 |
+
"requires": {
|
| 2564 |
+
"features": ["subgroups", "chromium-experimental-subgroup-matrix"],
|
| 2565 |
+
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 2566 |
+
},
|
| 2567 |
+
"description": "Adds the additive attention bias (batch/head-broadcast at runtime) to the materialized causal scores as they are stored, so the emitted row statistics fold it in for free; everything else matches `past_kv_materialized_sgmat_f32`.",
|
| 2568 |
+
"priority": 36,
|
| 2569 |
+
"when": ["gqaMatPastBiasOk"],
|
| 2570 |
+
"constants": {
|
| 2571 |
+
"qNumHeads": "attrs.num_heads",
|
| 2572 |
+
"kvNumHeads": "attrs.kv_num_heads",
|
| 2573 |
+
"headDim": "gqaHeadDim",
|
| 2574 |
+
"qHidden": "dim(shapes.queryT, 2)",
|
| 2575 |
+
"hasBias": false,
|
| 2576 |
+
"useSubgroups": true,
|
| 2577 |
+
"attentionScaleExpression": "\"select(inverseSqrt(f32(HEAD_DIM)), params.scale, params.scale != 0.0)\"",
|
| 2578 |
+
"materializedSgmatQueryTile": "gqaMatQueryTile",
|
| 2579 |
+
"materializedSgmatKeyTile": "gqaMatKeyTile",
|
| 2580 |
+
"materializedSgmatInnerTile": "gqaMatInnerTile",
|
| 2581 |
+
"materializedSgmatDirectScoreStore": false,
|
| 2582 |
+
"materializedSgmatDirectApplyStore": false,
|
| 2583 |
+
"materializedSgmatRuntimeDirectStore": false,
|
| 2584 |
+
"materializedRowStatsWg": "gqaMatRowStatsWg",
|
| 2585 |
+
"statSlots": "gqaMatPastStatSlots",
|
| 2586 |
+
"statQuerySeq": "dim(shapes.queryT, 1)",
|
| 2587 |
+
"mode": "\"copy\"",
|
| 2588 |
+
"packed": "gqaHeadDim",
|
| 2589 |
+
"kvHeads": "attrs.kv_num_heads",
|
| 2590 |
+
"inputScalar": "gqaScalar",
|
| 2591 |
+
"usesF16": false,
|
| 2592 |
+
"copyWorkgroupSize": "copyWorkgroupSize"
|
| 2593 |
+
},
|
| 2594 |
+
"intermediates": [
|
| 2595 |
+
{
|
| 2596 |
+
"id": "materializedScores",
|
| 2597 |
+
"dtype": "float32",
|
| 2598 |
+
"shape": "[dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1) * dim(shapes.presentKeyT, 2)]"
|
| 2599 |
+
},
|
| 2600 |
+
{ "id": "materializedRowStats", "dtype": "float32", "shape": "[gqaMatPastRowStatsElements]" },
|
| 2601 |
+
{ "id": "materializedScorePartials", "dtype": "float32", "shape": "[gqaMatPastScorePartialElements]" }
|
| 2602 |
+
],
|
| 2603 |
+
"passes": [
|
| 2604 |
+
{
|
| 2605 |
+
"id": "present",
|
| 2606 |
+
"name": "GroupQueryAttention.Present",
|
| 2607 |
+
"shader": "gqa-present.wgsl.jinja",
|
| 2608 |
+
"bindings": "presentCopy",
|
| 2609 |
+
"dispatch": {
|
| 2610 |
+
"threads": "dim(shapes.queryT, 0) * attrs.kv_num_heads * dim(shapes.pastKeyT, 2)",
|
| 2611 |
+
"workgroupSize": "copyWorkgroupSize"
|
| 2612 |
+
},
|
| 2613 |
+
"viewAlias": [{ "input": "src_k", "output": "present_key" }, { "input": "src_v", "output": "present_value" }]
|
| 2614 |
+
},
|
| 2615 |
+
{
|
| 2616 |
+
"id": "scores",
|
| 2617 |
+
"name": "GroupQueryAttention.PastMaterializedScores",
|
| 2618 |
+
"source": {
|
| 2619 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2620 |
+
"inputs": {
|
| 2621 |
+
"phase": "\"score\"",
|
| 2622 |
+
"emitRowStats": true,
|
| 2623 |
+
"layout": "\"bsh\"",
|
| 2624 |
+
"kvLayout": "\"bhsd\"",
|
| 2625 |
+
"causalRightAlign": true,
|
| 2626 |
+
"scoreBias": true
|
| 2627 |
+
}
|
| 2628 |
+
},
|
| 2629 |
+
"bindings": "gqaMatPastBiasScoreStats",
|
| 2630 |
+
"dispatch": {
|
| 2631 |
+
"x": "ceilDiv(dim(shapes.presentKeyT, 2), gqaMatKeyTile)",
|
| 2632 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 2633 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 2634 |
+
}
|
| 2635 |
+
},
|
| 2636 |
+
{
|
| 2637 |
+
"id": "rowstats",
|
| 2638 |
+
"name": "GroupQueryAttention.PastMaterializedRowStats",
|
| 2639 |
+
"source": { "shader": "attn-materialized-rowstats-combine-f32.wgsl.jinja", "inputs": {} },
|
| 2640 |
+
"bindings": "gqaMatPastRowStatsCombine",
|
| 2641 |
+
"dispatch": {
|
| 2642 |
+
"gridStride": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)",
|
| 2643 |
+
"workgroupSize": "gqaMatRowStatsWg"
|
| 2644 |
+
}
|
| 2645 |
+
},
|
| 2646 |
+
{
|
| 2647 |
+
"id": "apply",
|
| 2648 |
+
"name": "GroupQueryAttention.PastMaterializedApply",
|
| 2649 |
+
"source": {
|
| 2650 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2651 |
+
"inputs": {
|
| 2652 |
+
"phase": "\"apply\"",
|
| 2653 |
+
"fusedSoftmax": true,
|
| 2654 |
+
"layout": "\"bsh\"",
|
| 2655 |
+
"kvLayout": "\"bhsd\"",
|
| 2656 |
+
"causalRightAlign": true
|
| 2657 |
+
}
|
| 2658 |
+
},
|
| 2659 |
+
"bindings": "gqaMatPastApplyFused",
|
| 2660 |
+
"dispatch": {
|
| 2661 |
+
"x": "ceilDiv(gqaHeadDim, gqaMatKeyTile)",
|
| 2662 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 2663 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 2664 |
+
}
|
| 2665 |
+
}
|
| 2666 |
+
]
|
| 2667 |
+
},
|
| 2668 |
+
{
|
| 2669 |
+
"id": "past_kv_materialized_sgmat_f16",
|
| 2670 |
+
"requires": {
|
| 2671 |
+
"features": ["subgroups", "chromium-experimental-subgroup-matrix"],
|
| 2672 |
+
"subgroupMatrixConfigs": [{ "componentType": "f16", "M": 8, "N": 8, "K": 8 }]
|
| 2673 |
+
},
|
| 2674 |
+
"description": "Materializes the causal score matrix with `f16` operand tiles feeding `f32`-accumulating subgroup matrices over the shared cache and applies the softmax-normalized weights the same way; scores and row statistics stay `f32`. The score pass skips key tiles past each query tile's causal bound and the apply pass stops its reduction there.",
|
| 2675 |
+
"priority": 35,
|
| 2676 |
+
"when": ["gqaMatPastCoreF16Ok"],
|
| 2677 |
+
"constants": {
|
| 2678 |
+
"qNumHeads": "attrs.num_heads",
|
| 2679 |
+
"kvNumHeads": "attrs.kv_num_heads",
|
| 2680 |
+
"headDim": "gqaHeadDim",
|
| 2681 |
+
"qHidden": "dim(shapes.queryT, 2)",
|
| 2682 |
+
"hasBias": false,
|
| 2683 |
+
"useSubgroups": true,
|
| 2684 |
+
"attentionScaleExpression": "\"select(inverseSqrt(f32(HEAD_DIM)), params.scale, params.scale != 0.0)\"",
|
| 2685 |
+
"materializedSgmatQueryTile": "gqaMatQueryTile",
|
| 2686 |
+
"materializedSgmatKeyTile": "gqaMatKeyTile",
|
| 2687 |
+
"materializedSgmatInnerTile": "gqaMatInnerTile",
|
| 2688 |
+
"materializedSgmatDirectScoreStore": false,
|
| 2689 |
+
"materializedSgmatDirectApplyStore": false,
|
| 2690 |
+
"materializedSgmatRuntimeDirectStore": false,
|
| 2691 |
+
"materializedRowStatsWg": "gqaMatRowStatsWg",
|
| 2692 |
+
"statSlots": "gqaMatPastStatSlots",
|
| 2693 |
+
"statQuerySeq": "dim(shapes.queryT, 1)",
|
| 2694 |
+
"mode": "\"copy\"",
|
| 2695 |
+
"packed": "gqaHeadDim",
|
| 2696 |
+
"kvHeads": "attrs.kv_num_heads",
|
| 2697 |
+
"inputScalar": "gqaScalar",
|
| 2698 |
+
"usesF16": true,
|
| 2699 |
+
"copyWorkgroupSize": "copyWorkgroupSize",
|
| 2700 |
+
"operandF16": true
|
| 2701 |
+
},
|
| 2702 |
+
"intermediates": [
|
| 2703 |
+
{
|
| 2704 |
+
"id": "materializedScores",
|
| 2705 |
+
"dtype": "float32",
|
| 2706 |
+
"shape": "[dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1) * dim(shapes.presentKeyT, 2)]"
|
| 2707 |
+
},
|
| 2708 |
+
{ "id": "materializedRowStats", "dtype": "float32", "shape": "[gqaMatPastRowStatsElements]" },
|
| 2709 |
+
{ "id": "materializedScorePartials", "dtype": "float32", "shape": "[gqaMatPastScorePartialElements]" }
|
| 2710 |
+
],
|
| 2711 |
+
"passes": [
|
| 2712 |
+
{
|
| 2713 |
+
"id": "present",
|
| 2714 |
+
"name": "GroupQueryAttention.Present",
|
| 2715 |
+
"shader": "gqa-present.wgsl.jinja",
|
| 2716 |
+
"bindings": "presentCopy",
|
| 2717 |
+
"dispatch": {
|
| 2718 |
+
"threads": "dim(shapes.queryT, 0) * attrs.kv_num_heads * dim(shapes.pastKeyT, 2)",
|
| 2719 |
+
"workgroupSize": "copyWorkgroupSize"
|
| 2720 |
+
},
|
| 2721 |
+
"viewAlias": [{ "input": "src_k", "output": "present_key" }, { "input": "src_v", "output": "present_value" }]
|
| 2722 |
+
},
|
| 2723 |
+
{
|
| 2724 |
+
"id": "scores",
|
| 2725 |
+
"name": "GroupQueryAttention.PastMaterializedScores",
|
| 2726 |
+
"source": {
|
| 2727 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2728 |
+
"inputs": {
|
| 2729 |
+
"phase": "\"score\"",
|
| 2730 |
+
"emitRowStats": true,
|
| 2731 |
+
"layout": "\"bsh\"",
|
| 2732 |
+
"kvLayout": "\"bhsd\"",
|
| 2733 |
+
"causalRightAlign": true
|
| 2734 |
+
}
|
| 2735 |
+
},
|
| 2736 |
+
"bindings": "gqaMatPastScoreStatsF16",
|
| 2737 |
+
"dispatch": {
|
| 2738 |
+
"x": "ceilDiv(dim(shapes.presentKeyT, 2), gqaMatKeyTile)",
|
| 2739 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 2740 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 2741 |
+
}
|
| 2742 |
+
},
|
| 2743 |
+
{
|
| 2744 |
+
"id": "rowstats",
|
| 2745 |
+
"name": "GroupQueryAttention.PastMaterializedRowStats",
|
| 2746 |
+
"source": { "shader": "attn-materialized-rowstats-combine-f32.wgsl.jinja", "inputs": {} },
|
| 2747 |
+
"bindings": "gqaMatPastRowStatsCombine",
|
| 2748 |
+
"dispatch": {
|
| 2749 |
+
"gridStride": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)",
|
| 2750 |
+
"workgroupSize": "gqaMatRowStatsWg"
|
| 2751 |
+
}
|
| 2752 |
+
},
|
| 2753 |
+
{
|
| 2754 |
+
"id": "apply",
|
| 2755 |
+
"name": "GroupQueryAttention.PastMaterializedApply",
|
| 2756 |
+
"source": {
|
| 2757 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2758 |
+
"inputs": {
|
| 2759 |
+
"phase": "\"apply\"",
|
| 2760 |
+
"fusedSoftmax": true,
|
| 2761 |
+
"layout": "\"bsh\"",
|
| 2762 |
+
"kvLayout": "\"bhsd\"",
|
| 2763 |
+
"causalRightAlign": true
|
| 2764 |
+
}
|
| 2765 |
+
},
|
| 2766 |
+
"bindings": "gqaMatPastApplyFusedF16",
|
| 2767 |
+
"dispatch": {
|
| 2768 |
+
"x": "ceilDiv(gqaHeadDim, gqaMatKeyTile)",
|
| 2769 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 2770 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 2771 |
+
}
|
| 2772 |
+
}
|
| 2773 |
+
]
|
| 2774 |
+
},
|
| 2775 |
+
{
|
| 2776 |
+
"id": "past_kv_rotary_materialized_sgmat_f32",
|
| 2777 |
+
"requires": {
|
| 2778 |
+
"features": ["subgroups", "chromium-experimental-subgroup-matrix"],
|
| 2779 |
+
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 2780 |
+
},
|
| 2781 |
+
"description": "Rotary twin of the causal materialized route: the shared cache already holds rotary-transformed keys, so one preparation pass rotates the query block at its absolute positions and the tile-skipping score/apply passes run unchanged on the prepared buffer.",
|
| 2782 |
+
"priority": 37,
|
| 2783 |
+
"when": ["gqaMatPastRotaryOk"],
|
| 2784 |
+
"constants": {
|
| 2785 |
+
"qNumHeads": "attrs.num_heads",
|
| 2786 |
+
"kvNumHeads": "attrs.kv_num_heads",
|
| 2787 |
+
"headDim": "gqaHeadDim",
|
| 2788 |
+
"qHidden": "dim(shapes.queryT, 2)",
|
| 2789 |
+
"hasBias": false,
|
| 2790 |
+
"useSubgroups": true,
|
| 2791 |
+
"attentionScaleExpression": "\"select(inverseSqrt(f32(HEAD_DIM)), params.scale, params.scale != 0.0)\"",
|
| 2792 |
+
"materializedSgmatQueryTile": "gqaMatQueryTile",
|
| 2793 |
+
"materializedSgmatKeyTile": "gqaMatKeyTile",
|
| 2794 |
+
"materializedSgmatInnerTile": "gqaMatInnerTile",
|
| 2795 |
+
"materializedSgmatDirectScoreStore": false,
|
| 2796 |
+
"materializedSgmatDirectApplyStore": false,
|
| 2797 |
+
"materializedSgmatRuntimeDirectStore": false,
|
| 2798 |
+
"materializedRowStatsWg": "gqaMatRowStatsWg",
|
| 2799 |
+
"statSlots": "gqaMatPastStatSlots",
|
| 2800 |
+
"statQuerySeq": "dim(shapes.queryT, 1)",
|
| 2801 |
+
"mode": "\"copy\"",
|
| 2802 |
+
"packed": "gqaHeadDim",
|
| 2803 |
+
"kvHeads": "attrs.kv_num_heads",
|
| 2804 |
+
"inputScalar": "gqaScalar",
|
| 2805 |
+
"usesF16": false,
|
| 2806 |
+
"copyWorkgroupSize": "copyWorkgroupSize",
|
| 2807 |
+
"half": "gqaHeadDim / 2",
|
| 2808 |
+
"qHeads": "attrs.num_heads",
|
| 2809 |
+
"cosScalar": "\"f16\" if tensorDtypes.cosCacheT == \"float16\" else \"f32\"",
|
| 2810 |
+
"hasQNorm": false
|
| 2811 |
+
},
|
| 2812 |
+
"intermediates": [
|
| 2813 |
+
{
|
| 2814 |
+
"id": "qPrep",
|
| 2815 |
+
"dtype": "float32",
|
| 2816 |
+
"shape": "[dim(shapes.queryT, 0), dim(shapes.queryT, 1), dim(shapes.queryT, 2)]"
|
| 2817 |
+
},
|
| 2818 |
+
{
|
| 2819 |
+
"id": "materializedScores",
|
| 2820 |
+
"dtype": "float32",
|
| 2821 |
+
"shape": "[dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1) * dim(shapes.presentKeyT, 2)]"
|
| 2822 |
+
},
|
| 2823 |
+
{ "id": "materializedRowStats", "dtype": "float32", "shape": "[gqaMatPastRowStatsElements]" },
|
| 2824 |
+
{ "id": "materializedScorePartials", "dtype": "float32", "shape": "[gqaMatPastScorePartialElements]" }
|
| 2825 |
+
],
|
| 2826 |
+
"passes": [
|
| 2827 |
+
{
|
| 2828 |
+
"id": "present",
|
| 2829 |
+
"name": "GroupQueryAttention.Present",
|
| 2830 |
+
"shader": "gqa-present.wgsl.jinja",
|
| 2831 |
+
"bindings": "presentCopy",
|
| 2832 |
+
"dispatch": {
|
| 2833 |
+
"threads": "dim(shapes.queryT, 0) * attrs.kv_num_heads * dim(shapes.pastKeyT, 2)",
|
| 2834 |
+
"workgroupSize": "copyWorkgroupSize"
|
| 2835 |
+
},
|
| 2836 |
+
"viewAlias": [{ "input": "src_k", "output": "present_key" }, { "input": "src_v", "output": "present_value" }]
|
| 2837 |
+
},
|
| 2838 |
+
{
|
| 2839 |
+
"id": "qprep",
|
| 2840 |
+
"name": "GroupQueryAttention.RotaryQPrep",
|
| 2841 |
+
"shader": "gqa-qprep.wgsl.jinja",
|
| 2842 |
+
"bindings": "rotaryQprep",
|
| 2843 |
+
"dispatch": {
|
| 2844 |
+
"threads": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)",
|
| 2845 |
+
"workgroupSize": "copyWorkgroupSize"
|
| 2846 |
+
}
|
| 2847 |
+
},
|
| 2848 |
+
{
|
| 2849 |
+
"id": "scores",
|
| 2850 |
+
"name": "GroupQueryAttention.PastRotaryMaterializedScores",
|
| 2851 |
+
"source": {
|
| 2852 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2853 |
+
"inputs": {
|
| 2854 |
+
"phase": "\"score\"",
|
| 2855 |
+
"emitRowStats": true,
|
| 2856 |
+
"layout": "\"bsh\"",
|
| 2857 |
+
"kvLayout": "\"bhsd\"",
|
| 2858 |
+
"causalRightAlign": true
|
| 2859 |
+
}
|
| 2860 |
+
},
|
| 2861 |
+
"bindings": "gqaMatPastRotaryScoreStats",
|
| 2862 |
+
"dispatch": {
|
| 2863 |
+
"x": "ceilDiv(dim(shapes.presentKeyT, 2), gqaMatKeyTile)",
|
| 2864 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 2865 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 2866 |
+
}
|
| 2867 |
+
},
|
| 2868 |
+
{
|
| 2869 |
+
"id": "rowstats",
|
| 2870 |
+
"name": "GroupQueryAttention.PastRotaryMaterializedRowStats",
|
| 2871 |
+
"source": { "shader": "attn-materialized-rowstats-combine-f32.wgsl.jinja", "inputs": {} },
|
| 2872 |
+
"bindings": "gqaMatPastRowStatsCombine",
|
| 2873 |
+
"dispatch": {
|
| 2874 |
+
"gridStride": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)",
|
| 2875 |
+
"workgroupSize": "gqaMatRowStatsWg"
|
| 2876 |
+
}
|
| 2877 |
+
},
|
| 2878 |
+
{
|
| 2879 |
+
"id": "apply",
|
| 2880 |
+
"name": "GroupQueryAttention.PastRotaryMaterializedApply",
|
| 2881 |
+
"source": {
|
| 2882 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2883 |
+
"inputs": {
|
| 2884 |
+
"phase": "\"apply\"",
|
| 2885 |
+
"fusedSoftmax": true,
|
| 2886 |
+
"layout": "\"bsh\"",
|
| 2887 |
+
"kvLayout": "\"bhsd\"",
|
| 2888 |
+
"causalRightAlign": true
|
| 2889 |
+
}
|
| 2890 |
+
},
|
| 2891 |
+
"bindings": "gqaMatPastApplyFused",
|
| 2892 |
+
"dispatch": {
|
| 2893 |
+
"x": "ceilDiv(gqaHeadDim, gqaMatKeyTile)",
|
| 2894 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 2895 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 2896 |
+
}
|
| 2897 |
+
}
|
| 2898 |
+
]
|
| 2899 |
+
},
|
| 2900 |
+
{
|
| 2901 |
+
"id": "past_kv_rotary_materialized_sgmat_f16",
|
| 2902 |
+
"requires": {
|
| 2903 |
+
"features": ["subgroups", "chromium-experimental-subgroup-matrix"],
|
| 2904 |
+
"subgroupMatrixConfigs": [{ "componentType": "f16", "M": 8, "N": 8, "K": 8 }]
|
| 2905 |
+
},
|
| 2906 |
+
"description": "Materializes the causal score matrix with `f16` operand tiles feeding `f32`-accumulating subgroup matrices over the shared cache and applies the softmax-normalized weights the same way; scores and row statistics stay `f32`. The score pass skips key tiles past each query tile's causal bound and the apply pass stops its reduction there.",
|
| 2907 |
+
"priority": 37,
|
| 2908 |
+
"when": ["gqaMatPastRotaryF16Ok"],
|
| 2909 |
+
"constants": {
|
| 2910 |
+
"qNumHeads": "attrs.num_heads",
|
| 2911 |
+
"kvNumHeads": "attrs.kv_num_heads",
|
| 2912 |
+
"headDim": "gqaHeadDim",
|
| 2913 |
+
"qHidden": "dim(shapes.queryT, 2)",
|
| 2914 |
+
"hasBias": false,
|
| 2915 |
+
"useSubgroups": true,
|
| 2916 |
+
"attentionScaleExpression": "\"select(inverseSqrt(f32(HEAD_DIM)), params.scale, params.scale != 0.0)\"",
|
| 2917 |
+
"materializedSgmatQueryTile": "gqaMatQueryTile",
|
| 2918 |
+
"materializedSgmatKeyTile": "gqaMatKeyTile",
|
| 2919 |
+
"materializedSgmatInnerTile": "gqaMatInnerTile",
|
| 2920 |
+
"materializedSgmatDirectScoreStore": false,
|
| 2921 |
+
"materializedSgmatDirectApplyStore": false,
|
| 2922 |
+
"materializedSgmatRuntimeDirectStore": false,
|
| 2923 |
+
"materializedRowStatsWg": "gqaMatRowStatsWg",
|
| 2924 |
+
"statSlots": "gqaMatPastStatSlots",
|
| 2925 |
+
"statQuerySeq": "dim(shapes.queryT, 1)",
|
| 2926 |
+
"mode": "\"copy\"",
|
| 2927 |
+
"packed": "gqaHeadDim",
|
| 2928 |
+
"kvHeads": "attrs.kv_num_heads",
|
| 2929 |
+
"inputScalar": "gqaScalar",
|
| 2930 |
+
"usesF16": true,
|
| 2931 |
+
"copyWorkgroupSize": "copyWorkgroupSize",
|
| 2932 |
+
"half": "gqaHeadDim / 2",
|
| 2933 |
+
"qHeads": "attrs.num_heads",
|
| 2934 |
+
"cosScalar": "\"f16\" if tensorDtypes.cosCacheT == \"float16\" else \"f32\"",
|
| 2935 |
+
"hasQNorm": false,
|
| 2936 |
+
"operandF16": true
|
| 2937 |
+
},
|
| 2938 |
+
"intermediates": [
|
| 2939 |
+
{
|
| 2940 |
+
"id": "qPrep",
|
| 2941 |
+
"dtype": "float16",
|
| 2942 |
+
"shape": "[dim(shapes.queryT, 0), dim(shapes.queryT, 1), dim(shapes.queryT, 2)]"
|
| 2943 |
+
},
|
| 2944 |
+
{
|
| 2945 |
+
"id": "materializedScores",
|
| 2946 |
+
"dtype": "float32",
|
| 2947 |
+
"shape": "[dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1) * dim(shapes.presentKeyT, 2)]"
|
| 2948 |
+
},
|
| 2949 |
+
{ "id": "materializedRowStats", "dtype": "float32", "shape": "[gqaMatPastRowStatsElements]" },
|
| 2950 |
+
{ "id": "materializedScorePartials", "dtype": "float32", "shape": "[gqaMatPastScorePartialElements]" }
|
| 2951 |
+
],
|
| 2952 |
+
"passes": [
|
| 2953 |
+
{
|
| 2954 |
+
"id": "present",
|
| 2955 |
+
"name": "GroupQueryAttention.Present",
|
| 2956 |
+
"shader": "gqa-present.wgsl.jinja",
|
| 2957 |
+
"bindings": "presentCopy",
|
| 2958 |
+
"dispatch": {
|
| 2959 |
+
"threads": "dim(shapes.queryT, 0) * attrs.kv_num_heads * dim(shapes.pastKeyT, 2)",
|
| 2960 |
+
"workgroupSize": "copyWorkgroupSize"
|
| 2961 |
+
},
|
| 2962 |
+
"viewAlias": [{ "input": "src_k", "output": "present_key" }, { "input": "src_v", "output": "present_value" }]
|
| 2963 |
+
},
|
| 2964 |
+
{
|
| 2965 |
+
"id": "qprep",
|
| 2966 |
+
"name": "GroupQueryAttention.RotaryQPrep",
|
| 2967 |
+
"shader": "gqa-qprep.wgsl.jinja",
|
| 2968 |
+
"bindings": "rotaryQprepF16",
|
| 2969 |
+
"dispatch": {
|
| 2970 |
+
"threads": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)",
|
| 2971 |
+
"workgroupSize": "copyWorkgroupSize"
|
| 2972 |
+
},
|
| 2973 |
+
"constants": { "qPrepF16": true }
|
| 2974 |
+
},
|
| 2975 |
+
{
|
| 2976 |
+
"id": "scores",
|
| 2977 |
+
"name": "GroupQueryAttention.PastRotaryMaterializedScores",
|
| 2978 |
+
"source": {
|
| 2979 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 2980 |
+
"inputs": {
|
| 2981 |
+
"phase": "\"score\"",
|
| 2982 |
+
"emitRowStats": true,
|
| 2983 |
+
"layout": "\"bsh\"",
|
| 2984 |
+
"kvLayout": "\"bhsd\"",
|
| 2985 |
+
"causalRightAlign": true
|
| 2986 |
+
}
|
| 2987 |
+
},
|
| 2988 |
+
"bindings": "gqaMatPastRotaryScoreStatsF16",
|
| 2989 |
+
"dispatch": {
|
| 2990 |
+
"x": "ceilDiv(dim(shapes.presentKeyT, 2), gqaMatKeyTile)",
|
| 2991 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 2992 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 2993 |
+
}
|
| 2994 |
+
},
|
| 2995 |
+
{
|
| 2996 |
+
"id": "rowstats",
|
| 2997 |
+
"name": "GroupQueryAttention.PastRotaryMaterializedRowStats",
|
| 2998 |
+
"source": { "shader": "attn-materialized-rowstats-combine-f32.wgsl.jinja", "inputs": {} },
|
| 2999 |
+
"bindings": "gqaMatPastRowStatsCombine",
|
| 3000 |
+
"dispatch": {
|
| 3001 |
+
"gridStride": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)",
|
| 3002 |
+
"workgroupSize": "gqaMatRowStatsWg"
|
| 3003 |
+
}
|
| 3004 |
+
},
|
| 3005 |
+
{
|
| 3006 |
+
"id": "apply",
|
| 3007 |
+
"name": "GroupQueryAttention.PastRotaryMaterializedApply",
|
| 3008 |
+
"source": {
|
| 3009 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 3010 |
+
"inputs": {
|
| 3011 |
+
"phase": "\"apply\"",
|
| 3012 |
+
"fusedSoftmax": true,
|
| 3013 |
+
"layout": "\"bsh\"",
|
| 3014 |
+
"kvLayout": "\"bhsd\"",
|
| 3015 |
+
"causalRightAlign": true
|
| 3016 |
+
}
|
| 3017 |
+
},
|
| 3018 |
+
"bindings": "gqaMatPastApplyFusedF16",
|
| 3019 |
+
"dispatch": {
|
| 3020 |
+
"x": "ceilDiv(gqaHeadDim, gqaMatKeyTile)",
|
| 3021 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 3022 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 3023 |
+
}
|
| 3024 |
+
}
|
| 3025 |
+
]
|
| 3026 |
+
},
|
| 3027 |
+
{
|
| 3028 |
+
"id": "new_kv_past_materialized_sgmat_f32",
|
| 3029 |
+
"requires": {
|
| 3030 |
+
"features": ["subgroups", "chromium-experimental-subgroup-matrix"],
|
| 3031 |
+
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 3032 |
+
},
|
| 3033 |
+
"description": "Append-route twin of the causal materialized route for chunked prefill: one merge pass concatenates the past cache with the new key/value rows, and the tile-skipping score/apply passes run over the merged cache with the same right-aligned causal bound.",
|
| 3034 |
+
"priority": 35,
|
| 3035 |
+
"when": ["gqaMatNewPastOk"],
|
| 3036 |
+
"constants": {
|
| 3037 |
+
"qNumHeads": "attrs.num_heads",
|
| 3038 |
+
"kvNumHeads": "attrs.kv_num_heads",
|
| 3039 |
+
"headDim": "gqaHeadDim",
|
| 3040 |
+
"qHidden": "dim(shapes.queryT, 2)",
|
| 3041 |
+
"hasBias": false,
|
| 3042 |
+
"useSubgroups": true,
|
| 3043 |
+
"attentionScaleExpression": "\"select(inverseSqrt(f32(HEAD_DIM)), params.scale, params.scale != 0.0)\"",
|
| 3044 |
+
"materializedSgmatQueryTile": "gqaMatQueryTile",
|
| 3045 |
+
"materializedSgmatKeyTile": "gqaMatKeyTile",
|
| 3046 |
+
"materializedSgmatInnerTile": "gqaMatInnerTile",
|
| 3047 |
+
"materializedSgmatDirectScoreStore": false,
|
| 3048 |
+
"materializedSgmatDirectApplyStore": false,
|
| 3049 |
+
"materializedSgmatRuntimeDirectStore": false,
|
| 3050 |
+
"materializedRowStatsWg": "gqaMatRowStatsWg",
|
| 3051 |
+
"statSlots": "gqaMatPastStatSlots",
|
| 3052 |
+
"statQuerySeq": "dim(shapes.queryT, 1)",
|
| 3053 |
+
"mode": "\"merge\"",
|
| 3054 |
+
"packed": "gqaHeadDim",
|
| 3055 |
+
"kvHeads": "attrs.kv_num_heads",
|
| 3056 |
+
"inputScalar": "gqaScalar",
|
| 3057 |
+
"usesF16": false,
|
| 3058 |
+
"copyWorkgroupSize": "copyWorkgroupSize"
|
| 3059 |
+
},
|
| 3060 |
+
"intermediates": [
|
| 3061 |
+
{
|
| 3062 |
+
"id": "materializedScores",
|
| 3063 |
+
"dtype": "float32",
|
| 3064 |
+
"shape": "[dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1) * dim(shapes.presentKeyT, 2)]"
|
| 3065 |
+
},
|
| 3066 |
+
{ "id": "materializedRowStats", "dtype": "float32", "shape": "[gqaMatPastRowStatsElements]" },
|
| 3067 |
+
{ "id": "materializedScorePartials", "dtype": "float32", "shape": "[gqaMatPastScorePartialElements]" }
|
| 3068 |
+
],
|
| 3069 |
+
"passes": [
|
| 3070 |
+
{
|
| 3071 |
+
"id": "present",
|
| 3072 |
+
"name": "GroupQueryAttention.Merge",
|
| 3073 |
+
"shader": "gqa-present.wgsl.jinja",
|
| 3074 |
+
"bindings": "presentMerge",
|
| 3075 |
+
"dispatch": {
|
| 3076 |
+
"threads": "dim(shapes.queryT, 0) * attrs.kv_num_heads * dim(shapes.presentKeyT, 2)",
|
| 3077 |
+
"workgroupSize": "copyWorkgroupSize"
|
| 3078 |
+
}
|
| 3079 |
+
},
|
| 3080 |
+
{
|
| 3081 |
+
"id": "scores",
|
| 3082 |
+
"name": "GroupQueryAttention.NewPastMaterializedScores",
|
| 3083 |
+
"source": {
|
| 3084 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 3085 |
+
"inputs": {
|
| 3086 |
+
"phase": "\"score\"",
|
| 3087 |
+
"emitRowStats": true,
|
| 3088 |
+
"layout": "\"bsh\"",
|
| 3089 |
+
"kvLayout": "\"bhsd\"",
|
| 3090 |
+
"causalRightAlign": true
|
| 3091 |
+
}
|
| 3092 |
+
},
|
| 3093 |
+
"bindings": "gqaMatPastScoreStats",
|
| 3094 |
+
"dispatch": {
|
| 3095 |
+
"x": "ceilDiv(dim(shapes.presentKeyT, 2), gqaMatKeyTile)",
|
| 3096 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 3097 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 3098 |
+
}
|
| 3099 |
+
},
|
| 3100 |
+
{
|
| 3101 |
+
"id": "rowstats",
|
| 3102 |
+
"name": "GroupQueryAttention.NewPastMaterializedRowStats",
|
| 3103 |
+
"source": { "shader": "attn-materialized-rowstats-combine-f32.wgsl.jinja", "inputs": {} },
|
| 3104 |
+
"bindings": "gqaMatPastRowStatsCombine",
|
| 3105 |
+
"dispatch": {
|
| 3106 |
+
"gridStride": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)",
|
| 3107 |
+
"workgroupSize": "gqaMatRowStatsWg"
|
| 3108 |
+
}
|
| 3109 |
+
},
|
| 3110 |
+
{
|
| 3111 |
+
"id": "apply",
|
| 3112 |
+
"name": "GroupQueryAttention.NewPastMaterializedApply",
|
| 3113 |
+
"source": {
|
| 3114 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 3115 |
+
"inputs": {
|
| 3116 |
+
"phase": "\"apply\"",
|
| 3117 |
+
"fusedSoftmax": true,
|
| 3118 |
+
"layout": "\"bsh\"",
|
| 3119 |
+
"kvLayout": "\"bhsd\"",
|
| 3120 |
+
"causalRightAlign": true
|
| 3121 |
+
}
|
| 3122 |
+
},
|
| 3123 |
+
"bindings": "gqaMatPastApplyFused",
|
| 3124 |
+
"dispatch": {
|
| 3125 |
+
"x": "ceilDiv(gqaHeadDim, gqaMatKeyTile)",
|
| 3126 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 3127 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 3128 |
+
}
|
| 3129 |
+
}
|
| 3130 |
+
]
|
| 3131 |
+
},
|
| 3132 |
+
{
|
| 3133 |
+
"id": "window_shift_materialized_sgmat_f32",
|
| 3134 |
+
"requires": {
|
| 3135 |
+
"features": ["subgroups", "chromium-experimental-subgroup-matrix"],
|
| 3136 |
+
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 3137 |
+
},
|
| 3138 |
+
"description": "Windowed-cache twin of the causal materialized route for chunked prefill: the shift pass compacts surviving cache rows and appends the chunk, the score pass masks each row's sliding-window floor alongside the causal bound so the row statistics fold both out, and the apply pass starts each reduction at the first key tile the window can reach.",
|
| 3139 |
+
"priority": 36,
|
| 3140 |
+
"when": ["gqaMatWindowOk"],
|
| 3141 |
+
"constants": {
|
| 3142 |
+
"qNumHeads": "attrs.num_heads",
|
| 3143 |
+
"kvNumHeads": "attrs.kv_num_heads",
|
| 3144 |
+
"headDim": "gqaHeadDim",
|
| 3145 |
+
"qHidden": "dim(shapes.queryT, 2)",
|
| 3146 |
+
"hasBias": false,
|
| 3147 |
+
"useSubgroups": true,
|
| 3148 |
+
"attentionScaleExpression": "\"select(inverseSqrt(f32(HEAD_DIM)), params.scale, params.scale != 0.0)\"",
|
| 3149 |
+
"materializedSgmatQueryTile": "gqaMatQueryTile",
|
| 3150 |
+
"materializedSgmatKeyTile": "gqaMatKeyTile",
|
| 3151 |
+
"materializedSgmatInnerTile": "gqaMatInnerTile",
|
| 3152 |
+
"materializedSgmatDirectScoreStore": false,
|
| 3153 |
+
"materializedSgmatDirectApplyStore": false,
|
| 3154 |
+
"materializedSgmatRuntimeDirectStore": false,
|
| 3155 |
+
"materializedRowStatsWg": "gqaMatRowStatsWg",
|
| 3156 |
+
"statSlots": "gqaMatPastStatSlots",
|
| 3157 |
+
"statQuerySeq": "dim(shapes.queryT, 1)",
|
| 3158 |
+
"mode": "\"window_shift\"",
|
| 3159 |
+
"packed": "gqaHeadDim",
|
| 3160 |
+
"kvHeads": "attrs.kv_num_heads",
|
| 3161 |
+
"inputScalar": "gqaScalar",
|
| 3162 |
+
"zeroScalar": "gqaScalar",
|
| 3163 |
+
"usesF16": false,
|
| 3164 |
+
"copyWorkgroupSize": "copyWorkgroupSize"
|
| 3165 |
+
},
|
| 3166 |
+
"intermediates": [
|
| 3167 |
+
{
|
| 3168 |
+
"id": "materializedScores",
|
| 3169 |
+
"dtype": "float32",
|
| 3170 |
+
"shape": "[dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1) * dim(shapes.presentKeyT, 2)]"
|
| 3171 |
+
},
|
| 3172 |
+
{ "id": "materializedRowStats", "dtype": "float32", "shape": "[gqaMatPastRowStatsElements]" },
|
| 3173 |
+
{ "id": "materializedScorePartials", "dtype": "float32", "shape": "[gqaMatPastScorePartialElements]" }
|
| 3174 |
+
],
|
| 3175 |
+
"passes": [
|
| 3176 |
+
{
|
| 3177 |
+
"id": "present",
|
| 3178 |
+
"name": "GroupQueryAttention.WindowShift",
|
| 3179 |
+
"shader": "gqa-present.wgsl.jinja",
|
| 3180 |
+
"bindings": "presentMergeShare",
|
| 3181 |
+
"dispatch": {
|
| 3182 |
+
"threads": "dim(shapes.queryT, 0) * attrs.kv_num_heads * dim(shapes.presentKeyT, 2)",
|
| 3183 |
+
"workgroupSize": "copyWorkgroupSize"
|
| 3184 |
+
}
|
| 3185 |
+
},
|
| 3186 |
+
{
|
| 3187 |
+
"id": "scores",
|
| 3188 |
+
"name": "GroupQueryAttention.WindowMaterializedScores",
|
| 3189 |
+
"source": {
|
| 3190 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 3191 |
+
"inputs": {
|
| 3192 |
+
"phase": "\"score\"",
|
| 3193 |
+
"emitRowStats": true,
|
| 3194 |
+
"layout": "\"bsh\"",
|
| 3195 |
+
"kvLayout": "\"bhsd\"",
|
| 3196 |
+
"causalRightAlign": true,
|
| 3197 |
+
"scoreWindow": true,
|
| 3198 |
+
"useSeqlens": true
|
| 3199 |
+
}
|
| 3200 |
+
},
|
| 3201 |
+
"bindings": "gqaMatWindowScoreStats",
|
| 3202 |
+
"dispatch": {
|
| 3203 |
+
"x": "ceilDiv(dim(shapes.presentKeyT, 2), gqaMatKeyTile)",
|
| 3204 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 3205 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 3206 |
+
}
|
| 3207 |
+
},
|
| 3208 |
+
{
|
| 3209 |
+
"id": "rowstats",
|
| 3210 |
+
"name": "GroupQueryAttention.WindowMaterializedRowStats",
|
| 3211 |
+
"source": { "shader": "attn-materialized-rowstats-combine-f32.wgsl.jinja", "inputs": {} },
|
| 3212 |
+
"bindings": "gqaMatPastRowStatsCombine",
|
| 3213 |
+
"dispatch": {
|
| 3214 |
+
"gridStride": "dim(shapes.queryT, 0) * attrs.num_heads * dim(shapes.queryT, 1)",
|
| 3215 |
+
"workgroupSize": "gqaMatRowStatsWg"
|
| 3216 |
+
}
|
| 3217 |
+
},
|
| 3218 |
+
{
|
| 3219 |
+
"id": "apply",
|
| 3220 |
+
"name": "GroupQueryAttention.WindowMaterializedApply",
|
| 3221 |
+
"source": {
|
| 3222 |
+
"shader": "attn-materialized-sgmat-f32.wgsl.jinja",
|
| 3223 |
+
"inputs": {
|
| 3224 |
+
"phase": "\"apply\"",
|
| 3225 |
+
"fusedSoftmax": true,
|
| 3226 |
+
"layout": "\"bsh\"",
|
| 3227 |
+
"kvLayout": "\"bhsd\"",
|
| 3228 |
+
"causalRightAlign": true,
|
| 3229 |
+
"scoreWindow": true,
|
| 3230 |
+
"useSeqlens": true
|
| 3231 |
+
}
|
| 3232 |
+
},
|
| 3233 |
+
"bindings": "gqaMatWindowApplyFused",
|
| 3234 |
+
"dispatch": {
|
| 3235 |
+
"x": "ceilDiv(gqaHeadDim, gqaMatKeyTile)",
|
| 3236 |
+
"y": "ceilDiv(dim(shapes.queryT, 1), gqaMatQueryTile)",
|
| 3237 |
+
"z": "dim(shapes.queryT, 0) * attrs.num_heads"
|
| 3238 |
+
}
|
| 3239 |
+
}
|
| 3240 |
+
]
|
| 3241 |
+
},
|
| 3242 |
{
|
| 3243 |
"id": "new_kv_share_append_split",
|
| 3244 |
"description": "Retains the existing cache and appends new key/value rows in separate passes before portable attention. It avoids rebuilding unchanged cache positions when the past and present allocations share capacity.",
|
build/webgpu/metadata.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"name": "com.microsoft.GroupQueryAttention",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"backend": { "type": "webgpu" },
|
|
@@ -13,15 +13,17 @@
|
|
| 13 |
"attn-flash-online.wgsl.jinja": "MStTMF1/l5L9Rzx1+rPz5T+70/46n/vO/+hZQ0lbFws=",
|
| 14 |
"attn-flash-prefill-cluster.wgsl.jinja": "yk1WymJIbxCy0slbiho5DS223uZH9PQ15629yvQ9RFc=",
|
| 15 |
"attn-flash-q32-broadcast.wgsl.jinja": "evSdaiYgvrikYZ8hpb5m4gxf+rIryKkHOTiKgyF7ioI=",
|
|
|
|
|
|
|
| 16 |
"attn-online-scalar.wgsl.jinja": "X4yGNCYu9+uJX6Q3EKkxV6v28CPlIYWme0Nmf8F16L8=",
|
| 17 |
-
"bench.json": "
|
| 18 |
"gqa-attention.wgsl.jinja": "0EbwmdstNZMuskS170zYEo8whbQOFtupXLnNP2PaFL0=",
|
| 19 |
"gqa-present.wgsl.jinja": "J9g6oAeY2BtbmWBMlmbIXbxzo4sKHdxYqcE4EAd7BYM=",
|
| 20 |
-
"gqa-qprep.wgsl.jinja": "
|
| 21 |
-
"manifest.json": "
|
| 22 |
-
"test.json": "
|
| 23 |
}
|
| 24 |
},
|
| 25 |
-
"provenance": { "kernel": { "sha": "
|
| 26 |
"webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/com.microsoft.GroupQueryAttention" }
|
| 27 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"name": "com.microsoft.GroupQueryAttention",
|
| 3 |
+
"id": "_com_microsoft_groupqueryattention_webgpu_34ecc1b",
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"backend": { "type": "webgpu" },
|
|
|
|
| 13 |
"attn-flash-online.wgsl.jinja": "MStTMF1/l5L9Rzx1+rPz5T+70/46n/vO/+hZQ0lbFws=",
|
| 14 |
"attn-flash-prefill-cluster.wgsl.jinja": "yk1WymJIbxCy0slbiho5DS223uZH9PQ15629yvQ9RFc=",
|
| 15 |
"attn-flash-q32-broadcast.wgsl.jinja": "evSdaiYgvrikYZ8hpb5m4gxf+rIryKkHOTiKgyF7ioI=",
|
| 16 |
+
"attn-materialized-rowstats-combine-f32.wgsl.jinja": "TtTBeeeP/ufhzeNHoeLWGLxKTfFT9fiEAstnXB79j48=",
|
| 17 |
+
"attn-materialized-sgmat-f32.wgsl.jinja": "iQeacl5PUCl75lx78qlSBaQ/syBDNxgjZg4UPGki9U0=",
|
| 18 |
"attn-online-scalar.wgsl.jinja": "X4yGNCYu9+uJX6Q3EKkxV6v28CPlIYWme0Nmf8F16L8=",
|
| 19 |
+
"bench.json": "b4ZLhmCqTm6AgiNfIiRHYVeNp4q1mx12GMcDAextGqI=",
|
| 20 |
"gqa-attention.wgsl.jinja": "0EbwmdstNZMuskS170zYEo8whbQOFtupXLnNP2PaFL0=",
|
| 21 |
"gqa-present.wgsl.jinja": "J9g6oAeY2BtbmWBMlmbIXbxzo4sKHdxYqcE4EAd7BYM=",
|
| 22 |
+
"gqa-qprep.wgsl.jinja": "RCBDy7LA/yy4ayRAsnyq+7/IaXjsDGmPWidj51c+t8k=",
|
| 23 |
+
"manifest.json": "oxSz/yE5vrd9vU5lHkrRN2kG8sdBzWQmGP9/jjRoqNU=",
|
| 24 |
+
"test.json": "zfjYb8H4THOE5qN8K90UPdGq0lL/B2LWarbvokAz8Cg="
|
| 25 |
}
|
| 26 |
},
|
| 27 |
+
"provenance": { "kernel": { "sha": "c928d21e6cc1310861cba3bafb75f5f679ecf5f3", "dirty": false } },
|
| 28 |
"webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/com.microsoft.GroupQueryAttention" }
|
| 29 |
}
|
build/webgpu/test.json
CHANGED
|
@@ -4271,6 +4271,205 @@
|
|
| 4271 |
"notes": "Chunked flash prefill into a windowed cache: the present pass compacts entries, the attention bound comes from seqlens_k (kvActive), and the batch stride remains the cache capacity. Batch 0 is unfilled at T=40 while batch 1 evicts at T=80, requiring kvActive to be tracked per batch."
|
| 4272 |
}
|
| 4273 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4274 |
{
|
| 4275 |
"name": "share_append_flash_chunk_slack_b1q32cap64_h2kv1d64",
|
| 4276 |
"attrs": { "num_heads": 2, "kv_num_heads": 1, "local_window_size": 16 },
|
|
@@ -4655,6 +4854,526 @@
|
|
| 4655 |
"presentKeyT": { "dtype": "uint8", "shape": [1, 1, 4, 4], "tolerance": 0 },
|
| 4656 |
"presentValueT": { "dtype": "uint8", "shape": [1, 1, 4, 4], "tolerance": 0 }
|
| 4657 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4658 |
}
|
| 4659 |
]
|
| 4660 |
}
|
|
|
|
| 4271 |
"notes": "Chunked flash prefill into a windowed cache: the present pass compacts entries, the attention bound comes from seqlens_k (kvActive), and the batch stride remains the cache capacity. Batch 0 is unfilled at T=40 while batch 1 evicts at T=80, requiring kvActive to be tracked per batch."
|
| 4272 |
}
|
| 4273 |
},
|
| 4274 |
+
{
|
| 4275 |
+
"name": "window_cache_sgmat_chunk_evicts_b1q128cap256_h2kv1d128_w256",
|
| 4276 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "sliding_window_cache": 1, "local_window_size": 256 },
|
| 4277 |
+
"inputs": {
|
| 4278 |
+
"queryT": {
|
| 4279 |
+
"dtype": "float32",
|
| 4280 |
+
"shape": [1, 128, 256],
|
| 4281 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.27, "scale": 0.5 }
|
| 4282 |
+
},
|
| 4283 |
+
"keyT": {
|
| 4284 |
+
"dtype": "float32",
|
| 4285 |
+
"shape": [1, 128, 128],
|
| 4286 |
+
"data": { "kind": "linspace", "start": -1.0, "end": 1.0 }
|
| 4287 |
+
},
|
| 4288 |
+
"valueT": {
|
| 4289 |
+
"dtype": "float32",
|
| 4290 |
+
"shape": [1, 128, 128],
|
| 4291 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 2.0 }
|
| 4292 |
+
},
|
| 4293 |
+
"pastKeyT": {
|
| 4294 |
+
"dtype": "float32",
|
| 4295 |
+
"shape": [1, 1, 256, 128],
|
| 4296 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.31, "scale": 0.5 }
|
| 4297 |
+
},
|
| 4298 |
+
"pastValueT": {
|
| 4299 |
+
"dtype": "float32",
|
| 4300 |
+
"shape": [1, 1, 256, 128],
|
| 4301 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 4.0 }
|
| 4302 |
+
},
|
| 4303 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [383] } },
|
| 4304 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [384] } }
|
| 4305 |
+
},
|
| 4306 |
+
"outputs": {
|
| 4307 |
+
"outputT": { "dtype": "float32", "shape": [1, 128, 256], "tolerance": 0.005 },
|
| 4308 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 256, 128], "tolerance": 0.0001 },
|
| 4309 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 256, 128], "tolerance": 0.0001 }
|
| 4310 |
+
},
|
| 4311 |
+
"provenance": {
|
| 4312 |
+
"source": "onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc",
|
| 4313 |
+
"test": "GQA sliding_window_cache chunk prefill on the materialized subgroup-matrix route",
|
| 4314 |
+
"notes": "T=384 > C=256 evicts 128 rows; w=256=C keeps the floor inactive, so this pins the shift + right-aligned causal path of the materialized window route at d=128 (two apply column tiles)."
|
| 4315 |
+
}
|
| 4316 |
+
},
|
| 4317 |
+
{
|
| 4318 |
+
"name": "window_cache_sgmat_chunk_floor_b1q128cap384_h2kv1d64_w256",
|
| 4319 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "sliding_window_cache": 1, "local_window_size": 256 },
|
| 4320 |
+
"inputs": {
|
| 4321 |
+
"queryT": {
|
| 4322 |
+
"dtype": "float32",
|
| 4323 |
+
"shape": [1, 128, 128],
|
| 4324 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.27, "scale": 0.5 }
|
| 4325 |
+
},
|
| 4326 |
+
"keyT": { "dtype": "float32", "shape": [1, 128, 64], "data": { "kind": "linspace", "start": -1.0, "end": 1.0 } },
|
| 4327 |
+
"valueT": {
|
| 4328 |
+
"dtype": "float32",
|
| 4329 |
+
"shape": [1, 128, 64],
|
| 4330 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 2.0 }
|
| 4331 |
+
},
|
| 4332 |
+
"pastKeyT": {
|
| 4333 |
+
"dtype": "float32",
|
| 4334 |
+
"shape": [1, 1, 384, 64],
|
| 4335 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.31, "scale": 0.5 }
|
| 4336 |
+
},
|
| 4337 |
+
"pastValueT": {
|
| 4338 |
+
"dtype": "float32",
|
| 4339 |
+
"shape": [1, 1, 384, 64],
|
| 4340 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 4.0 }
|
| 4341 |
+
},
|
| 4342 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [511] } },
|
| 4343 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [512] } }
|
| 4344 |
+
},
|
| 4345 |
+
"outputs": {
|
| 4346 |
+
"outputT": { "dtype": "float32", "shape": [1, 128, 128], "tolerance": 0.005 },
|
| 4347 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 384, 64], "tolerance": 0.0001 },
|
| 4348 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 384, 64], "tolerance": 0.0001 }
|
| 4349 |
+
},
|
| 4350 |
+
"provenance": {
|
| 4351 |
+
"source": "onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc",
|
| 4352 |
+
"test": "GQA sliding_window_cache chunk prefill on the materialized subgroup-matrix route",
|
| 4353 |
+
"notes": "w+q == C exactly, so every row's window floor is row+1: the second query tile's first key tile is dead (uniform window skip) and the apply pass starts its reduction one tile in. The two-sided band mask is fully exercised."
|
| 4354 |
+
}
|
| 4355 |
+
},
|
| 4356 |
+
{
|
| 4357 |
+
"name": "window_cache_sgmat_chunk_unfilled_b1q128cap256_h2kv1d64_w256",
|
| 4358 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "sliding_window_cache": 1, "local_window_size": 256 },
|
| 4359 |
+
"inputs": {
|
| 4360 |
+
"queryT": {
|
| 4361 |
+
"dtype": "float32",
|
| 4362 |
+
"shape": [1, 128, 128],
|
| 4363 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.27, "scale": 0.5 }
|
| 4364 |
+
},
|
| 4365 |
+
"keyT": { "dtype": "float32", "shape": [1, 128, 64], "data": { "kind": "linspace", "start": -1.0, "end": 1.0 } },
|
| 4366 |
+
"valueT": {
|
| 4367 |
+
"dtype": "float32",
|
| 4368 |
+
"shape": [1, 128, 64],
|
| 4369 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 2.0 }
|
| 4370 |
+
},
|
| 4371 |
+
"pastKeyT": {
|
| 4372 |
+
"dtype": "float32",
|
| 4373 |
+
"shape": [1, 1, 256, 64],
|
| 4374 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.31, "scale": 0.5 }
|
| 4375 |
+
},
|
| 4376 |
+
"pastValueT": {
|
| 4377 |
+
"dtype": "float32",
|
| 4378 |
+
"shape": [1, 1, 256, 64],
|
| 4379 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 4.0 }
|
| 4380 |
+
},
|
| 4381 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [191] } },
|
| 4382 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [192] } }
|
| 4383 |
+
},
|
| 4384 |
+
"outputs": {
|
| 4385 |
+
"outputT": { "dtype": "float32", "shape": [1, 128, 128], "tolerance": 0.005 },
|
| 4386 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 256, 64], "tolerance": 0.0001 },
|
| 4387 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 256, 64], "tolerance": 0.0001 }
|
| 4388 |
+
},
|
| 4389 |
+
"provenance": {
|
| 4390 |
+
"source": "onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc",
|
| 4391 |
+
"test": "GQA sliding_window_cache chunk prefill on the materialized subgroup-matrix route",
|
| 4392 |
+
"notes": "Partially filled cache: kvActive=192 < C=256, so the live length comes from seqlens_k and the key tiles beyond it publish the stats identity instead of reading cleared rows."
|
| 4393 |
+
}
|
| 4394 |
+
},
|
| 4395 |
+
{
|
| 4396 |
+
"name": "window_cache_sgmat_chunk_mixed_batch_b2q128cap256_h2kv1d64_w192",
|
| 4397 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "sliding_window_cache": 1, "local_window_size": 192 },
|
| 4398 |
+
"inputs": {
|
| 4399 |
+
"queryT": {
|
| 4400 |
+
"dtype": "float32",
|
| 4401 |
+
"shape": [2, 128, 128],
|
| 4402 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.27, "scale": 0.5 }
|
| 4403 |
+
},
|
| 4404 |
+
"keyT": { "dtype": "float32", "shape": [2, 128, 64], "data": { "kind": "linspace", "start": -1.0, "end": 1.0 } },
|
| 4405 |
+
"valueT": {
|
| 4406 |
+
"dtype": "float32",
|
| 4407 |
+
"shape": [2, 128, 64],
|
| 4408 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 2.0 }
|
| 4409 |
+
},
|
| 4410 |
+
"pastKeyT": {
|
| 4411 |
+
"dtype": "float32",
|
| 4412 |
+
"shape": [2, 1, 256, 64],
|
| 4413 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.31, "scale": 0.5 }
|
| 4414 |
+
},
|
| 4415 |
+
"pastValueT": {
|
| 4416 |
+
"dtype": "float32",
|
| 4417 |
+
"shape": [2, 1, 256, 64],
|
| 4418 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 4.0 }
|
| 4419 |
+
},
|
| 4420 |
+
"seqlensKT": { "dtype": "int32", "shape": [2], "data": { "kind": "values", "values": [319, 191] } },
|
| 4421 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [320] } }
|
| 4422 |
+
},
|
| 4423 |
+
"outputs": {
|
| 4424 |
+
"outputT": { "dtype": "float32", "shape": [2, 128, 128], "tolerance": 0.005 },
|
| 4425 |
+
"presentKeyT": { "dtype": "float32", "shape": [2, 1, 256, 64], "tolerance": 0.0001 },
|
| 4426 |
+
"presentValueT": { "dtype": "float32", "shape": [2, 1, 256, 64], "tolerance": 0.0001 }
|
| 4427 |
+
},
|
| 4428 |
+
"provenance": {
|
| 4429 |
+
"source": "onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc",
|
| 4430 |
+
"test": "GQA sliding_window_cache chunk prefill on the materialized subgroup-matrix route",
|
| 4431 |
+
"notes": "Per-batch live lengths: batch 0 evicts (kvActive=256) with an active window floor, batch 1 is unfilled (kvActive=192) with the floor inactive — both from the same dispatch."
|
| 4432 |
+
}
|
| 4433 |
+
},
|
| 4434 |
+
{
|
| 4435 |
+
"name": "window_cache_sgmat_chunk_qtail_b1q160cap320_h2kv1d64_w160",
|
| 4436 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "sliding_window_cache": 1, "local_window_size": 160 },
|
| 4437 |
+
"inputs": {
|
| 4438 |
+
"queryT": {
|
| 4439 |
+
"dtype": "float32",
|
| 4440 |
+
"shape": [1, 160, 128],
|
| 4441 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.13, "cosStep": 0.27, "scale": 0.5 }
|
| 4442 |
+
},
|
| 4443 |
+
"keyT": { "dtype": "float32", "shape": [1, 160, 64], "data": { "kind": "linspace", "start": -1.0, "end": 1.0 } },
|
| 4444 |
+
"valueT": {
|
| 4445 |
+
"dtype": "float32",
|
| 4446 |
+
"shape": [1, 160, 64],
|
| 4447 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 2.0 }
|
| 4448 |
+
},
|
| 4449 |
+
"pastKeyT": {
|
| 4450 |
+
"dtype": "float32",
|
| 4451 |
+
"shape": [1, 1, 320, 64],
|
| 4452 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.19, "cosStep": 0.31, "scale": 0.5 }
|
| 4453 |
+
},
|
| 4454 |
+
"pastValueT": {
|
| 4455 |
+
"dtype": "float32",
|
| 4456 |
+
"shape": [1, 1, 320, 64],
|
| 4457 |
+
"data": { "kind": "linspace", "start": 0.0, "end": 4.0 }
|
| 4458 |
+
},
|
| 4459 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [399] } },
|
| 4460 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [400] } }
|
| 4461 |
+
},
|
| 4462 |
+
"outputs": {
|
| 4463 |
+
"outputT": { "dtype": "float32", "shape": [1, 160, 128], "tolerance": 0.005 },
|
| 4464 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 320, 64], "tolerance": 0.0001 },
|
| 4465 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 320, 64], "tolerance": 0.0001 }
|
| 4466 |
+
},
|
| 4467 |
+
"provenance": {
|
| 4468 |
+
"source": "onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc",
|
| 4469 |
+
"test": "GQA sliding_window_cache chunk prefill on the materialized subgroup-matrix route",
|
| 4470 |
+
"notes": "q=160 is not a query-tile multiple and w+q == C makes every floor active, so the guarded tail rows and the tile-aligned reduction start are exercised together."
|
| 4471 |
+
}
|
| 4472 |
+
},
|
| 4473 |
{
|
| 4474 |
"name": "share_append_flash_chunk_slack_b1q32cap64_h2kv1d64",
|
| 4475 |
"attrs": { "num_heads": 2, "kv_num_heads": 1, "local_window_size": 16 },
|
|
|
|
| 4854 |
"presentKeyT": { "dtype": "uint8", "shape": [1, 1, 4, 4], "tolerance": 0 },
|
| 4855 |
"presentValueT": { "dtype": "uint8", "shape": [1, 1, 4, 4], "tolerance": 0 }
|
| 4856 |
}
|
| 4857 |
+
},
|
| 4858 |
+
{
|
| 4859 |
+
"name": "qkv_materialized_sgmat_f32_q512_kv512_h2kv1_d64",
|
| 4860 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "causal": 0 },
|
| 4861 |
+
"inputs": {
|
| 4862 |
+
"queryT": {
|
| 4863 |
+
"dtype": "float32",
|
| 4864 |
+
"shape": [1, 512, 128],
|
| 4865 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 4866 |
+
},
|
| 4867 |
+
"keyT": {
|
| 4868 |
+
"dtype": "float32",
|
| 4869 |
+
"shape": [1, 512, 64],
|
| 4870 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 4871 |
+
},
|
| 4872 |
+
"valueT": {
|
| 4873 |
+
"dtype": "float32",
|
| 4874 |
+
"shape": [1, 512, 64],
|
| 4875 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 4876 |
+
},
|
| 4877 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [511] } },
|
| 4878 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [512] } }
|
| 4879 |
+
},
|
| 4880 |
+
"outputs": {
|
| 4881 |
+
"outputT": { "dtype": "float32", "shape": [1, 512, 128], "tolerance": 0.00002 },
|
| 4882 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 },
|
| 4883 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 }
|
| 4884 |
+
}
|
| 4885 |
+
},
|
| 4886 |
+
{
|
| 4887 |
+
"name": "qkv_materialized_sgmat_f32_padded_seqlens_q512_kv512_h2kv1_d64",
|
| 4888 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "causal": 0 },
|
| 4889 |
+
"inputs": {
|
| 4890 |
+
"queryT": {
|
| 4891 |
+
"dtype": "float32",
|
| 4892 |
+
"shape": [1, 512, 128],
|
| 4893 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 4894 |
+
},
|
| 4895 |
+
"keyT": {
|
| 4896 |
+
"dtype": "float32",
|
| 4897 |
+
"shape": [1, 512, 64],
|
| 4898 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 4899 |
+
},
|
| 4900 |
+
"valueT": {
|
| 4901 |
+
"dtype": "float32",
|
| 4902 |
+
"shape": [1, 512, 64],
|
| 4903 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 4904 |
+
},
|
| 4905 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [299] } },
|
| 4906 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [512] } }
|
| 4907 |
+
},
|
| 4908 |
+
"outputs": {
|
| 4909 |
+
"outputT": { "dtype": "float32", "shape": [1, 512, 128], "tolerance": 0.00002 },
|
| 4910 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 },
|
| 4911 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 }
|
| 4912 |
+
}
|
| 4913 |
+
},
|
| 4914 |
+
{
|
| 4915 |
+
"name": "qkv_materialized_sgmat_f32_rightalign_q512_kv576_h2kv1_d128",
|
| 4916 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "causal": 0 },
|
| 4917 |
+
"inputs": {
|
| 4918 |
+
"queryT": {
|
| 4919 |
+
"dtype": "float32",
|
| 4920 |
+
"shape": [1, 512, 256],
|
| 4921 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 4922 |
+
},
|
| 4923 |
+
"keyT": {
|
| 4924 |
+
"dtype": "float32",
|
| 4925 |
+
"shape": [1, 576, 128],
|
| 4926 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 4927 |
+
},
|
| 4928 |
+
"valueT": {
|
| 4929 |
+
"dtype": "float32",
|
| 4930 |
+
"shape": [1, 576, 128],
|
| 4931 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 4932 |
+
},
|
| 4933 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [575] } },
|
| 4934 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [576] } }
|
| 4935 |
+
},
|
| 4936 |
+
"outputs": {
|
| 4937 |
+
"outputT": { "dtype": "float32", "shape": [1, 512, 256], "tolerance": 0.00002 },
|
| 4938 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 576, 128], "tolerance": 0.000001 },
|
| 4939 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 576, 128], "tolerance": 0.000001 }
|
| 4940 |
+
}
|
| 4941 |
+
},
|
| 4942 |
+
{
|
| 4943 |
+
"name": "past_kv_materialized_sgmat_f32_q512_p512_h2kv1_d64",
|
| 4944 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1 },
|
| 4945 |
+
"inputs": {
|
| 4946 |
+
"queryT": {
|
| 4947 |
+
"dtype": "float32",
|
| 4948 |
+
"shape": [1, 512, 128],
|
| 4949 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 4950 |
+
},
|
| 4951 |
+
"keyT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 4952 |
+
"valueT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 4953 |
+
"pastKeyT": {
|
| 4954 |
+
"dtype": "float32",
|
| 4955 |
+
"shape": [1, 1, 512, 64],
|
| 4956 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 4957 |
+
},
|
| 4958 |
+
"pastValueT": {
|
| 4959 |
+
"dtype": "float32",
|
| 4960 |
+
"shape": [1, 1, 512, 64],
|
| 4961 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 4962 |
+
},
|
| 4963 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [511] } },
|
| 4964 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [512] } }
|
| 4965 |
+
},
|
| 4966 |
+
"outputs": {
|
| 4967 |
+
"outputT": { "dtype": "float32", "shape": [1, 512, 128], "tolerance": 0.00002 },
|
| 4968 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 },
|
| 4969 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 }
|
| 4970 |
+
}
|
| 4971 |
+
},
|
| 4972 |
+
{
|
| 4973 |
+
"name": "past_kv_materialized_sgmat_f32_qtail_q520_p576_h2kv1_d64",
|
| 4974 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1 },
|
| 4975 |
+
"inputs": {
|
| 4976 |
+
"queryT": {
|
| 4977 |
+
"dtype": "float32",
|
| 4978 |
+
"shape": [1, 520, 128],
|
| 4979 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 4980 |
+
},
|
| 4981 |
+
"keyT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 4982 |
+
"valueT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 4983 |
+
"pastKeyT": {
|
| 4984 |
+
"dtype": "float32",
|
| 4985 |
+
"shape": [1, 1, 576, 64],
|
| 4986 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 4987 |
+
},
|
| 4988 |
+
"pastValueT": {
|
| 4989 |
+
"dtype": "float32",
|
| 4990 |
+
"shape": [1, 1, 576, 64],
|
| 4991 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 4992 |
+
},
|
| 4993 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [575] } },
|
| 4994 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [576] } }
|
| 4995 |
+
},
|
| 4996 |
+
"outputs": {
|
| 4997 |
+
"outputT": { "dtype": "float32", "shape": [1, 520, 128], "tolerance": 0.00002 },
|
| 4998 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 576, 64], "tolerance": 0.000001 },
|
| 4999 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 576, 64], "tolerance": 0.000001 }
|
| 5000 |
+
}
|
| 5001 |
+
},
|
| 5002 |
+
{
|
| 5003 |
+
"name": "past_kv_materialized_sgmat_f32_group_q512_p512_h4kv2_d128",
|
| 5004 |
+
"attrs": { "num_heads": 4, "kv_num_heads": 2 },
|
| 5005 |
+
"inputs": {
|
| 5006 |
+
"queryT": {
|
| 5007 |
+
"dtype": "float32",
|
| 5008 |
+
"shape": [1, 512, 512],
|
| 5009 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5010 |
+
},
|
| 5011 |
+
"keyT": { "dtype": "float32", "shape": [1, 0, 256], "data": { "kind": "values", "values": [] } },
|
| 5012 |
+
"valueT": { "dtype": "float32", "shape": [1, 0, 256], "data": { "kind": "values", "values": [] } },
|
| 5013 |
+
"pastKeyT": {
|
| 5014 |
+
"dtype": "float32",
|
| 5015 |
+
"shape": [1, 2, 512, 128],
|
| 5016 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5017 |
+
},
|
| 5018 |
+
"pastValueT": {
|
| 5019 |
+
"dtype": "float32",
|
| 5020 |
+
"shape": [1, 2, 512, 128],
|
| 5021 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5022 |
+
},
|
| 5023 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [511] } },
|
| 5024 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [512] } }
|
| 5025 |
+
},
|
| 5026 |
+
"outputs": {
|
| 5027 |
+
"outputT": { "dtype": "float32", "shape": [1, 512, 512], "tolerance": 0.00002 },
|
| 5028 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 2, 512, 128], "tolerance": 0.000001 },
|
| 5029 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 2, 512, 128], "tolerance": 0.000001 }
|
| 5030 |
+
}
|
| 5031 |
+
},
|
| 5032 |
+
{
|
| 5033 |
+
"name": "past_kv_materialized_sgmat_f32_floor_q256_p256_h2kv1_d64",
|
| 5034 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1 },
|
| 5035 |
+
"inputs": {
|
| 5036 |
+
"queryT": {
|
| 5037 |
+
"dtype": "float32",
|
| 5038 |
+
"shape": [1, 256, 128],
|
| 5039 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5040 |
+
},
|
| 5041 |
+
"keyT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5042 |
+
"valueT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5043 |
+
"pastKeyT": {
|
| 5044 |
+
"dtype": "float32",
|
| 5045 |
+
"shape": [1, 1, 256, 64],
|
| 5046 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5047 |
+
},
|
| 5048 |
+
"pastValueT": {
|
| 5049 |
+
"dtype": "float32",
|
| 5050 |
+
"shape": [1, 1, 256, 64],
|
| 5051 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5052 |
+
},
|
| 5053 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [255] } },
|
| 5054 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [256] } }
|
| 5055 |
+
},
|
| 5056 |
+
"outputs": {
|
| 5057 |
+
"outputT": { "dtype": "float32", "shape": [1, 256, 128], "tolerance": 0.00002 },
|
| 5058 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 256, 64], "tolerance": 0.000001 },
|
| 5059 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 256, 64], "tolerance": 0.000001 }
|
| 5060 |
+
}
|
| 5061 |
+
},
|
| 5062 |
+
{
|
| 5063 |
+
"name": "past_kv_rotary_materialized_sgmat_f32_q512_p512_h2kv1_d64",
|
| 5064 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "do_rotary": 1 },
|
| 5065 |
+
"inputs": {
|
| 5066 |
+
"queryT": {
|
| 5067 |
+
"dtype": "float32",
|
| 5068 |
+
"shape": [1, 512, 128],
|
| 5069 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5070 |
+
},
|
| 5071 |
+
"keyT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5072 |
+
"valueT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5073 |
+
"pastKeyT": {
|
| 5074 |
+
"dtype": "float32",
|
| 5075 |
+
"shape": [1, 1, 512, 64],
|
| 5076 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5077 |
+
},
|
| 5078 |
+
"pastValueT": {
|
| 5079 |
+
"dtype": "float32",
|
| 5080 |
+
"shape": [1, 1, 512, 64],
|
| 5081 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5082 |
+
},
|
| 5083 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [511] } },
|
| 5084 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [512] } },
|
| 5085 |
+
"cosCacheT": {
|
| 5086 |
+
"dtype": "float32",
|
| 5087 |
+
"shape": [512, 32],
|
| 5088 |
+
"data": { "kind": "rotaryCos", "thetaStart": 0.07, "thetaStep": 0.013 }
|
| 5089 |
+
},
|
| 5090 |
+
"sinCacheT": {
|
| 5091 |
+
"dtype": "float32",
|
| 5092 |
+
"shape": [512, 32],
|
| 5093 |
+
"data": { "kind": "rotarySin", "thetaStart": 0.07, "thetaStep": 0.013 }
|
| 5094 |
+
}
|
| 5095 |
+
},
|
| 5096 |
+
"outputs": {
|
| 5097 |
+
"outputT": { "dtype": "float32", "shape": [1, 512, 128], "tolerance": 0.00002 },
|
| 5098 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 },
|
| 5099 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 }
|
| 5100 |
+
}
|
| 5101 |
+
},
|
| 5102 |
+
{
|
| 5103 |
+
"name": "past_kv_rotary_materialized_sgmat_f32_offset_q512_p576_h2kv1_d64",
|
| 5104 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "do_rotary": 1 },
|
| 5105 |
+
"inputs": {
|
| 5106 |
+
"queryT": {
|
| 5107 |
+
"dtype": "float32",
|
| 5108 |
+
"shape": [1, 512, 128],
|
| 5109 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5110 |
+
},
|
| 5111 |
+
"keyT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5112 |
+
"valueT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5113 |
+
"pastKeyT": {
|
| 5114 |
+
"dtype": "float32",
|
| 5115 |
+
"shape": [1, 1, 576, 64],
|
| 5116 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5117 |
+
},
|
| 5118 |
+
"pastValueT": {
|
| 5119 |
+
"dtype": "float32",
|
| 5120 |
+
"shape": [1, 1, 576, 64],
|
| 5121 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5122 |
+
},
|
| 5123 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [575] } },
|
| 5124 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [576] } },
|
| 5125 |
+
"cosCacheT": {
|
| 5126 |
+
"dtype": "float32",
|
| 5127 |
+
"shape": [576, 32],
|
| 5128 |
+
"data": { "kind": "rotaryCos", "thetaStart": 0.07, "thetaStep": 0.013 }
|
| 5129 |
+
},
|
| 5130 |
+
"sinCacheT": {
|
| 5131 |
+
"dtype": "float32",
|
| 5132 |
+
"shape": [576, 32],
|
| 5133 |
+
"data": { "kind": "rotarySin", "thetaStart": 0.07, "thetaStep": 0.013 }
|
| 5134 |
+
}
|
| 5135 |
+
},
|
| 5136 |
+
"outputs": {
|
| 5137 |
+
"outputT": { "dtype": "float32", "shape": [1, 512, 128], "tolerance": 0.00002 },
|
| 5138 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 576, 64], "tolerance": 0.000001 },
|
| 5139 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 576, 64], "tolerance": 0.000001 }
|
| 5140 |
+
}
|
| 5141 |
+
},
|
| 5142 |
+
{
|
| 5143 |
+
"name": "new_kv_past_materialized_sgmat_f32_chunk_q512_p512_h2kv1_d64",
|
| 5144 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1 },
|
| 5145 |
+
"inputs": {
|
| 5146 |
+
"queryT": {
|
| 5147 |
+
"dtype": "float32",
|
| 5148 |
+
"shape": [1, 512, 128],
|
| 5149 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5150 |
+
},
|
| 5151 |
+
"keyT": {
|
| 5152 |
+
"dtype": "float32",
|
| 5153 |
+
"shape": [1, 512, 64],
|
| 5154 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.019, "cosStep": 0.037 }
|
| 5155 |
+
},
|
| 5156 |
+
"valueT": {
|
| 5157 |
+
"dtype": "float32",
|
| 5158 |
+
"shape": [1, 512, 64],
|
| 5159 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.029, "cosStep": 0.013 }
|
| 5160 |
+
},
|
| 5161 |
+
"pastKeyT": {
|
| 5162 |
+
"dtype": "float32",
|
| 5163 |
+
"shape": [1, 1, 512, 64],
|
| 5164 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5165 |
+
},
|
| 5166 |
+
"pastValueT": {
|
| 5167 |
+
"dtype": "float32",
|
| 5168 |
+
"shape": [1, 1, 512, 64],
|
| 5169 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5170 |
+
},
|
| 5171 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [1023] } },
|
| 5172 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [1024] } }
|
| 5173 |
+
},
|
| 5174 |
+
"outputs": {
|
| 5175 |
+
"outputT": { "dtype": "float32", "shape": [1, 512, 128], "tolerance": 0.00002 },
|
| 5176 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 1024, 64], "tolerance": 0.000001 },
|
| 5177 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 1024, 64], "tolerance": 0.000001 }
|
| 5178 |
+
}
|
| 5179 |
+
},
|
| 5180 |
+
{
|
| 5181 |
+
"name": "qkv_materialized_sgmat_f32_floor_q256_kv256_h2kv1_d64",
|
| 5182 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "causal": 0 },
|
| 5183 |
+
"inputs": {
|
| 5184 |
+
"queryT": {
|
| 5185 |
+
"dtype": "float32",
|
| 5186 |
+
"shape": [1, 256, 128],
|
| 5187 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5188 |
+
},
|
| 5189 |
+
"keyT": {
|
| 5190 |
+
"dtype": "float32",
|
| 5191 |
+
"shape": [1, 256, 64],
|
| 5192 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5193 |
+
},
|
| 5194 |
+
"valueT": {
|
| 5195 |
+
"dtype": "float32",
|
| 5196 |
+
"shape": [1, 256, 64],
|
| 5197 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5198 |
+
},
|
| 5199 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [255] } },
|
| 5200 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [256] } }
|
| 5201 |
+
},
|
| 5202 |
+
"outputs": {
|
| 5203 |
+
"outputT": { "dtype": "float32", "shape": [1, 256, 128], "tolerance": 0.00002 },
|
| 5204 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 256, 64], "tolerance": 0.000001 },
|
| 5205 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 256, 64], "tolerance": 0.000001 }
|
| 5206 |
+
}
|
| 5207 |
+
},
|
| 5208 |
+
{
|
| 5209 |
+
"name": "past_kv_materialized_sgmat_f16_q512_p512_h2kv1_d64",
|
| 5210 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1 },
|
| 5211 |
+
"inputs": {
|
| 5212 |
+
"queryT": {
|
| 5213 |
+
"dtype": "float16",
|
| 5214 |
+
"shape": [1, 512, 128],
|
| 5215 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5216 |
+
},
|
| 5217 |
+
"keyT": { "dtype": "float16", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5218 |
+
"valueT": { "dtype": "float16", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5219 |
+
"pastKeyT": {
|
| 5220 |
+
"dtype": "float16",
|
| 5221 |
+
"shape": [1, 1, 512, 64],
|
| 5222 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5223 |
+
},
|
| 5224 |
+
"pastValueT": {
|
| 5225 |
+
"dtype": "float16",
|
| 5226 |
+
"shape": [1, 1, 512, 64],
|
| 5227 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5228 |
+
},
|
| 5229 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [511] } },
|
| 5230 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [512] } }
|
| 5231 |
+
},
|
| 5232 |
+
"outputs": {
|
| 5233 |
+
"outputT": { "dtype": "float16", "shape": [1, 512, 128], "tolerance": 0.03 },
|
| 5234 |
+
"presentKeyT": { "dtype": "float16", "shape": [1, 1, 512, 64], "tolerance": 0.001 },
|
| 5235 |
+
"presentValueT": { "dtype": "float16", "shape": [1, 1, 512, 64], "tolerance": 0.001 }
|
| 5236 |
+
}
|
| 5237 |
+
},
|
| 5238 |
+
{
|
| 5239 |
+
"name": "past_kv_materialized_sgmat_f16_floor_q256_p256_h2kv1_d64",
|
| 5240 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1 },
|
| 5241 |
+
"inputs": {
|
| 5242 |
+
"queryT": {
|
| 5243 |
+
"dtype": "float16",
|
| 5244 |
+
"shape": [1, 256, 128],
|
| 5245 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5246 |
+
},
|
| 5247 |
+
"keyT": { "dtype": "float16", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5248 |
+
"valueT": { "dtype": "float16", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5249 |
+
"pastKeyT": {
|
| 5250 |
+
"dtype": "float16",
|
| 5251 |
+
"shape": [1, 1, 256, 64],
|
| 5252 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5253 |
+
},
|
| 5254 |
+
"pastValueT": {
|
| 5255 |
+
"dtype": "float16",
|
| 5256 |
+
"shape": [1, 1, 256, 64],
|
| 5257 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5258 |
+
},
|
| 5259 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [255] } },
|
| 5260 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [256] } }
|
| 5261 |
+
},
|
| 5262 |
+
"outputs": {
|
| 5263 |
+
"outputT": { "dtype": "float16", "shape": [1, 256, 128], "tolerance": 0.03 },
|
| 5264 |
+
"presentKeyT": { "dtype": "float16", "shape": [1, 1, 256, 64], "tolerance": 0.001 },
|
| 5265 |
+
"presentValueT": { "dtype": "float16", "shape": [1, 1, 256, 64], "tolerance": 0.001 }
|
| 5266 |
+
}
|
| 5267 |
+
},
|
| 5268 |
+
{
|
| 5269 |
+
"name": "past_kv_rotary_materialized_sgmat_f16_q512_p512_h2kv1_d64",
|
| 5270 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1, "do_rotary": 1 },
|
| 5271 |
+
"inputs": {
|
| 5272 |
+
"queryT": {
|
| 5273 |
+
"dtype": "float16",
|
| 5274 |
+
"shape": [1, 512, 128],
|
| 5275 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5276 |
+
},
|
| 5277 |
+
"keyT": { "dtype": "float16", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5278 |
+
"valueT": { "dtype": "float16", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5279 |
+
"pastKeyT": {
|
| 5280 |
+
"dtype": "float16",
|
| 5281 |
+
"shape": [1, 1, 512, 64],
|
| 5282 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5283 |
+
},
|
| 5284 |
+
"pastValueT": {
|
| 5285 |
+
"dtype": "float16",
|
| 5286 |
+
"shape": [1, 1, 512, 64],
|
| 5287 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5288 |
+
},
|
| 5289 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [511] } },
|
| 5290 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [512] } },
|
| 5291 |
+
"cosCacheT": {
|
| 5292 |
+
"dtype": "float16",
|
| 5293 |
+
"shape": [512, 32],
|
| 5294 |
+
"data": { "kind": "rotaryCos", "thetaStart": 0.07, "thetaStep": 0.013 }
|
| 5295 |
+
},
|
| 5296 |
+
"sinCacheT": {
|
| 5297 |
+
"dtype": "float16",
|
| 5298 |
+
"shape": [512, 32],
|
| 5299 |
+
"data": { "kind": "rotarySin", "thetaStart": 0.07, "thetaStep": 0.013 }
|
| 5300 |
+
}
|
| 5301 |
+
},
|
| 5302 |
+
"outputs": {
|
| 5303 |
+
"outputT": { "dtype": "float16", "shape": [1, 512, 128], "tolerance": 0.03 },
|
| 5304 |
+
"presentKeyT": { "dtype": "float16", "shape": [1, 1, 512, 64], "tolerance": 0.001 },
|
| 5305 |
+
"presentValueT": { "dtype": "float16", "shape": [1, 1, 512, 64], "tolerance": 0.001 }
|
| 5306 |
+
}
|
| 5307 |
+
},
|
| 5308 |
+
{
|
| 5309 |
+
"name": "past_kv_bias_materialized_sgmat_f32_q512_p512_h2kv1_d64",
|
| 5310 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1 },
|
| 5311 |
+
"inputs": {
|
| 5312 |
+
"queryT": {
|
| 5313 |
+
"dtype": "float32",
|
| 5314 |
+
"shape": [1, 512, 128],
|
| 5315 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5316 |
+
},
|
| 5317 |
+
"keyT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5318 |
+
"valueT": { "dtype": "float32", "shape": [1, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5319 |
+
"pastKeyT": {
|
| 5320 |
+
"dtype": "float32",
|
| 5321 |
+
"shape": [1, 1, 512, 64],
|
| 5322 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5323 |
+
},
|
| 5324 |
+
"pastValueT": {
|
| 5325 |
+
"dtype": "float32",
|
| 5326 |
+
"shape": [1, 1, 512, 64],
|
| 5327 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5328 |
+
},
|
| 5329 |
+
"seqlensKT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [511] } },
|
| 5330 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [512] } },
|
| 5331 |
+
"attentionBiasT": {
|
| 5332 |
+
"dtype": "float32",
|
| 5333 |
+
"shape": [1, 2, 512, 512],
|
| 5334 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.29, "cosStep": 0.13, "scale": 0.5 }
|
| 5335 |
+
}
|
| 5336 |
+
},
|
| 5337 |
+
"outputs": {
|
| 5338 |
+
"outputT": { "dtype": "float32", "shape": [1, 512, 128], "tolerance": 0.00002 },
|
| 5339 |
+
"presentKeyT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 },
|
| 5340 |
+
"presentValueT": { "dtype": "float32", "shape": [1, 1, 512, 64], "tolerance": 0.000001 }
|
| 5341 |
+
}
|
| 5342 |
+
},
|
| 5343 |
+
{
|
| 5344 |
+
"name": "past_kv_bias_materialized_sgmat_f32_broadcast_b2_q256_p256_h2kv1_d64",
|
| 5345 |
+
"attrs": { "num_heads": 2, "kv_num_heads": 1 },
|
| 5346 |
+
"inputs": {
|
| 5347 |
+
"queryT": {
|
| 5348 |
+
"dtype": "float32",
|
| 5349 |
+
"shape": [2, 256, 128],
|
| 5350 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.31 }
|
| 5351 |
+
},
|
| 5352 |
+
"keyT": { "dtype": "float32", "shape": [2, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5353 |
+
"valueT": { "dtype": "float32", "shape": [2, 0, 64], "data": { "kind": "values", "values": [] } },
|
| 5354 |
+
"pastKeyT": {
|
| 5355 |
+
"dtype": "float32",
|
| 5356 |
+
"shape": [2, 1, 256, 64],
|
| 5357 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.11, "cosStep": 0.23 }
|
| 5358 |
+
},
|
| 5359 |
+
"pastValueT": {
|
| 5360 |
+
"dtype": "float32",
|
| 5361 |
+
"shape": [2, 1, 256, 64],
|
| 5362 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.41 }
|
| 5363 |
+
},
|
| 5364 |
+
"seqlensKT": { "dtype": "int32", "shape": [2], "data": { "kind": "values", "values": [255, 255] } },
|
| 5365 |
+
"totalSequenceLengthT": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [256] } },
|
| 5366 |
+
"attentionBiasT": {
|
| 5367 |
+
"dtype": "float32",
|
| 5368 |
+
"shape": [2, 1, 256, 256],
|
| 5369 |
+
"data": { "kind": "fillFloat32", "sinStep": 0.31, "cosStep": 0.17, "scale": 0.5 }
|
| 5370 |
+
}
|
| 5371 |
+
},
|
| 5372 |
+
"outputs": {
|
| 5373 |
+
"outputT": { "dtype": "float32", "shape": [2, 256, 128], "tolerance": 0.00002 },
|
| 5374 |
+
"presentKeyT": { "dtype": "float32", "shape": [2, 1, 256, 64], "tolerance": 0.000001 },
|
| 5375 |
+
"presentValueT": { "dtype": "float32", "shape": [2, 1, 256, 64], "tolerance": 0.000001 }
|
| 5376 |
+
}
|
| 5377 |
}
|
| 5378 |
]
|
| 5379 |
}
|