perf(cost-model): D8 single-op-cmd fast-path (FIXED=8 single-op / 40 composite)

ADR-0064 D8 broadened from "DMA fast-path" to "single-op-cmd fast-path":
every single-op command (DmaRead/DmaWrite/Gemm/Math/Copy) now pays the
lighter FIXED=8; only CompositeCmd keeps the 40-cycle control-path FIXED
(it alone needs scheduler plan generation + per-tile RW-hazard tracking +
completion wiring). Renamed knob fixed_per_dma_cmd_cycles ->
fixed_per_single_op_cmd_cycles. dispatch_cycles now branches on
"is CompositeCmd" rather than enumerating DMA types.

Term choice: "single-op" (not "atomic", which read as sync/async) — the
axis is composition (one engine op vs fused multi-op plan), orthogonal to
timing. single-op <-> composite.

Tests: test_pe_cost_model.py updated to the single-op surface (defaults,
fast-path over all 5 single-op cmd types, composite general path, yaml
override). All green.

Recalibrated tests/attention/test_gqa_decode_opt2.py
::test_opt3_dispatch_exceeds_opt2 — NOT a regression: D8 makes single-op
cmds 5x cheaper, so opt2's two-composite fusion win over opt3's many
single-ops narrowed from pre-D8 ~3.7x to ~1.87x (opt3=224 > opt2=120).
The CPU-offload invariant (opt2 cheaper) still holds; only the model-
dependent ">2x" constant was over-fit to the old uniform-40 model. Gate
now: direction + >1.5x margin (matches sibling R-sweep test's stated
"absolute ratio informative-only" philosophy).
NOTE for review: ADR-0065's "2x CPU-offload win" headline may want a
refresh to reflect the post-D8 ~1.87x — left to user (architectural doc).

Full regression: 826 passed, 1 skipped (tests/ excl. tests/gemm).

--- Remaining work (resume here if interrupted) ---
5. Re-run scripts/paper/paper_plot_gemm_async_vs_composite.py with new
   cost model; verify async-tiled dispatch overhead drops (~4576ns ->
   ~1536ns expected) and the composite-vs-async-tiled gap narrows from
   the prior ~6.3x at K=3072.
6. Copy regenerated gemm_composite_vs_async_tflops.png to
   docs/report/1H-codesign-paper/figures/.
7. Paper §3.4 (03-gemm.tex sec:gemm-vs-async): finish naive->async-full /
   chunked->async-tiled rename AND reframe FIXED_DMA wording to single-op
   vs composite (currently still says "lighter FIXED for DMA descriptors,
   FIXED_DMA=8"). Table 2 (02-platform) + §2 dispatch prose already done.
8. Paper §3.4 K=3072 corner para + mechanism #3: update dispatch breakdown
   to new model (96 DMA*8 + 95 single-op*8 ≈ 1.5us vs old 4.6us); update
   headline ratio if it changed.
9. Rebuild docs/report/1H-codesign-paper/build/main.pdf (tectonic) +
   verify via pdftotext.
10. Then this is the bench-harness + paper commits (Groups 2 & 3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 15:04:53 -07:00
parent 0c6ca0aaed
commit 2d8271c981
6 changed files with 258 additions and 23 deletions
+14 -2
View File
@@ -89,11 +89,23 @@ def _dispatch_cycles(emitter, cost_model) -> float:
# ── dispatch ratio (ADR-0064 Test #9 / ADR-0065 Test #7) ─────────────
def test_opt3_dispatch_exceeds_opt2_by_2x():
def test_opt3_dispatch_exceeds_opt2():
"""ADR-0064 Test #9 / ADR-0065 Test #7 — fusing opt3's per-tile
primitives into opt2's two composites lowers dispatch cost (the
CPU-offload win).
ADR-0064 D8 (single-op fast-path) narrowed this win: single-op
commands now pay FIXED=8 while a composite pays FIXED=40, so opt2's
two composites no longer dominate opt3's many (now cheap) single-ops
by the pre-D8 2x. At the default model opt2 is still ~46% cheaper
(opt3 ≈ 1.87x opt2); the invariant that survives recalibration is the
direction plus a >1.5x margin. The sibling R-sweep test gates the
formula-level (direction + monotonicity) claim.
"""
opt3 = _dispatch_cycles(_opt3_tile, DEFAULT_PE_COST_MODEL)
opt2 = _dispatch_cycles(_opt2_tile, DEFAULT_PE_COST_MODEL)
assert opt2 > 0 and opt3 > 0
assert opt3 > 2 * opt2, f"opt3={opt3} must exceed 2x opt2={opt2}"
assert opt3 > 1.5 * opt2, f"opt3={opt3} must exceed 1.5x opt2={opt2}"
def test_dispatch_ratio_R_sensitivity():