Commit 1ad4160
Enable static-cache + Flash-attention path (runtime-gated, ready for ORT #28958) (#364)
## What
mobius `main` already emits the correct maskless `is_causal=1` +
`nonpad_kv_seqlen` + `TensorScatter` static-cache decoder graph. This PR
adds the runtime **enablement, verification, and CI** for that path on
the CUDA Flash-attention kernel — it is **not** graph surgery. Nothing
in the emitted graph is reverted or rewritten.
The path becomes runnable once an ONNX Runtime build containing
[microsoft/onnxruntime#28958](microsoft/onnxruntime#28958)
is installed (Flash eligibility widening for the bottom-right-causal
errata [onnx/onnx#8068](onnx/onnx#8068)).
## Issues
- Closes #329 — this PR fully delivers the static-cache numerical-parity
CI coverage that #329 asks for (`tests/static_cache_parity_test.py`:
static vs dynamic vs HuggingFace, chunked-prefill zero-guard, V
convex-hull valid-row invariant, exact-triangle `nonpad == q_seq`).
- Part of #345 — this PR delivers the code/probe/CI half of #345 ("emit
maskless `is_causal=1` + `nonpad_kv_seqlen` static-cache graph once
upstream lands"). The ORT pin bump + node-count rebaseline + ONNX 1.22
pin + skill docs remain deferred until an official PyPI ORT release with
microsoft/onnxruntime#28958, so #345 stays open (intentionally `Part
of`, not `Closes`).
## Changes
- **(a) Conditional opset 24→23 lowering** in `_builder.py` via
`_graph_requires_opset24` (a **recursive** subgraph scan) +
`_apply_opset_lowering`, so graphs carrying `TensorScatter` or the
`Attention` `nonpad_kv_seqlen` input correctly **stay at opset 24**.
Flag-gated, default off. (`_builder_test.py` exercises the real branch.)
- **(b) Canonical capability probe**
`src/mobius/_testing/ort_capabilities.py` —
`supports_static_cache_flash()` is a **functional, fail-closed-but-loud
runtime probe** (not a version-string check). It builds a minimal
`TensorScatter` + maskless `Attention` graph and runs it on CUDA. A
**known-answer value check** closes a latent CPU-fallback fail-open:
because ORT implicitly appends the CPU EP, a CUDA build that declines
the node would silently run on CPU with wrong (top-left) values; the
probe's deterministic reference (`2.0`) rejects that → `NEEDS_FIX` →
`False`. A structured `_ProbeOutcome` enum distinguishes the expected
pre-#28958 reject from unexpected probe errors (logged with `exc_info`).
- **(c) Static-cache parity test (#329)**
`tests/static_cache_parity_test.py` — static vs dynamic vs HuggingFace,
chunked-prefill zero-guard, V convex-hull valid-row invariant,
exact-triangle `nonpad == q_seq`.
- **(d) e2e CUDA Flash-dispatch test**
`tests/static_cache_flash_e2e_test.py` — asserts the ONNX-domain
`Attention` actually routes to **Flash** (via VERBOSE dispatch capture),
gated on SM ≥ 8.0 (`_flash_capable_gpu`) and `onnxruntime_QUICK_BUILD`.
- **(e) Probe consolidation** — deleted
`tests/_static_cache_support.py`; one canonical probe module, no shim.
## Gating
All new GPU tests **skip automatically** unless the installed ORT can
actually run the path (probe-gated). CI stays green today and **flips
green automatically** once an official ORT release containing
microsoft/onnxruntime#28958 is installed — **zero code change needed**
to enable.
## Verified
- **5/5** static-cache tests pass on an A100 (SM 8.0) with a post-#28958
ORT (full targeted suite: 14 passed including builder tests).
- **Fail-closed on pre-#28958 confirmed two ways**: (1) source — the
CUDA kernel guard `causal_cross_no_past = is_causal && (q_seq !=
total_seq) && (past == 0)` in `Attention<T>::ComputeInternal`
(`llm/attention.cc`) raises `NOT_IMPLEMENTED` for the `S_q=1` decode
shape (no fast-path bypass); (2) empirically — a real
`onnxruntime-gpu==1.27.0` isolated venv raises `NotImplemented` →
`supports_static_cache_flash() == False`.
## Explicitly out of scope (intentionally held, separate follow-ups)
- ORT dependency pin bump + node-count rebaseline + ONNX 1.22 pin +
skill docs — parked until an official PyPI ORT release with #28958
exists.
- `examples/static_cache_generation.py` nonpad-before-scatter check
(`verify-example-nonpad`).
- Pre-existing `RUF067` ruff version-skew in `pyproject.toml`.
- onnxruntime-genai#2204-blocked bias-decoder external-KV work (#349).
## References
- [onnx/onnx#8068](onnx/onnx#8068) — causal
top-left → bottom-right errata
-
[microsoft/onnxruntime#28958](microsoft/onnxruntime#28958)
— Flash eligibility widening
---
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Signed-off-by: titaiwang <titaiwang@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent bab4068 commit 1ad4160
8 files changed
Lines changed: 2099 additions & 30 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
213 | 213 | | |
214 | 214 | | |
215 | 215 | | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
221 | | - | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
226 | | - | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
233 | | - | |
234 | | - | |
235 | | - | |
| 216 | + | |
236 | 217 | | |
237 | 218 | | |
238 | 219 | | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
239 | 305 | | |
240 | 306 | | |
241 | 307 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
0 commit comments