gqa(adr-0065): N4 — opt2 numeric parity vs opt3 in data mode

composite() now awaits its prologue recipe operands (e.g. the score tile from a prior #1 composite) so the cross-composite RAW (#1 writes scores -> #2 reads them) is ordered: #2 waits for #1 before reading. With N1-N3, opt2 (the two-composite recipe kernel) now computes a correct attention output end-to-end in data mode and matches opt3 within fp tolerance.

Scope note: the e2e opt2<->opt3 parity holds in the near-uniform-attention regime (small inputs). kernbench's K reshape-as-transpose (opt3 kernel docstring: 'correct for zero/symmetric inputs') makes opt2's per-sub-tile K interpretation differ from opt3's single-tile one for high-contrast inputs — a pre-existing kernbench limitation shared by both kernels, not the recipe. The EXACT recipe math (online-softmax merge m/l + O = O*corr + P@V) is verified non-trivially and exactly by N2/N3 (test_recipe_data_mode.py). Suite 817 pass / 3 pre-existing fail.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-10 23:13:16 -07:00
parent 5bbe293bea
commit e9d62b908c
2 changed files with 61 additions and 0 deletions
+7
View File
@@ -802,6 +802,13 @@ class TLContext:
rw_handles: tuple[TensorHandle, ...] = ()
if prologue:
prologue_ops, primary_out, rw_handles = self._expand_prologue(prologue)
# Await any prologue operand that is a pending composite output
# (e.g. the score tile produced by a prior #1 composite) so it is
# computed before this composite reads it (RAW across composites).
for _item in prologue:
self._await_pending(
*[v for v in _item.values() if isinstance(v, TensorHandle)]
)
# Auto-bind (D6.6): the recipe's primary output fills the head GEMM's
# `a` unless the kernel supplied `a` explicitly (then it's ambiguous).