diff --git a/src/kernbench/benches/_gqa_attention_decode_cube_repl_pe_sp.py b/src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_repl_pe_sp.py similarity index 98% rename from src/kernbench/benches/_gqa_attention_decode_cube_repl_pe_sp.py rename to src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_repl_pe_sp.py index 5e1a427..7eb8957 100644 --- a/src/kernbench/benches/_gqa_attention_decode_cube_repl_pe_sp.py +++ b/src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_repl_pe_sp.py @@ -31,7 +31,7 @@ from kernbench.benches._gqa_attention_decode_long import _merge_running TILE_S_KV = 1024 # ADR-0063 §A.2 S_kv-axis tile sweep (per-tile width). -def gqa_attention_decode_cube_repl_pe_sp_kernel( +def gqa_attention_decode_long_ctx_cube_repl_pe_sp_kernel( q_ptr: int, k_ptr: int, v_ptr: int, diff --git a/src/kernbench/benches/_gqa_attention_decode_cube_repl_pe_tp.py b/src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_repl_pe_tp.py similarity index 98% rename from src/kernbench/benches/_gqa_attention_decode_cube_repl_pe_tp.py rename to src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_repl_pe_tp.py index 91da063..9964793 100644 --- a/src/kernbench/benches/_gqa_attention_decode_cube_repl_pe_tp.py +++ b/src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_repl_pe_tp.py @@ -31,7 +31,7 @@ from __future__ import annotations TILE_S_KV = 1024 # match decode_long — per-tile S_kv width (ADR-0063 §A.2). -def gqa_attention_decode_cube_repl_pe_tp_kernel( +def gqa_attention_decode_long_ctx_cube_repl_pe_tp_kernel( q_ptr: int, k_ptr: int, v_ptr: int, diff --git a/src/kernbench/benches/_gqa_attention_decode_cube_sp_pe_sp.py b/src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_sp_pe_sp.py similarity index 96% rename from src/kernbench/benches/_gqa_attention_decode_cube_sp_pe_sp.py rename to src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_sp_pe_sp.py index 2f06c0c..e9201a7 100644 --- a/src/kernbench/benches/_gqa_attention_decode_cube_sp_pe_sp.py +++ b/src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_sp_pe_sp.py @@ -23,7 +23,7 @@ from kernbench.benches._gqa_attention_decode_long import ( ) -def gqa_attention_decode_cube_sp_pe_sp_kernel( +def gqa_attention_decode_long_ctx_cube_sp_pe_sp_kernel( q_ptr: int, k_ptr: int, v_ptr: int, diff --git a/src/kernbench/benches/_gqa_attention_decode_cube_sp_pe_tp.py b/src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_sp_pe_tp.py similarity index 99% rename from src/kernbench/benches/_gqa_attention_decode_cube_sp_pe_tp.py rename to src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_sp_pe_tp.py index 0899742..5e96ddb 100644 --- a/src/kernbench/benches/_gqa_attention_decode_cube_sp_pe_tp.py +++ b/src/kernbench/benches/_gqa_attention_decode_long_ctx_cube_sp_pe_tp.py @@ -33,7 +33,7 @@ from kernbench.benches._gqa_attention_decode_long import _merge_running TILE_S_KV = 1024 # ADR-0063 §A.2 S_kv-axis tile sweep (per-tile width). -def gqa_attention_decode_cube_sp_pe_tp_kernel( +def gqa_attention_decode_long_ctx_cube_sp_pe_tp_kernel( q_ptr: int, k_ptr: int, v_ptr: int, diff --git a/src/kernbench/benches/milestone_gqa_decode_4cases.py b/src/kernbench/benches/milestone_gqa_decode_long_ctx_4cases.py similarity index 75% rename from src/kernbench/benches/milestone_gqa_decode_4cases.py rename to src/kernbench/benches/milestone_gqa_decode_long_ctx_4cases.py index 29bb541..0498752 100644 --- a/src/kernbench/benches/milestone_gqa_decode_4cases.py +++ b/src/kernbench/benches/milestone_gqa_decode_long_ctx_4cases.py @@ -1,7 +1,8 @@ -"""milestone-gqa-decode-4cases: comparative study of 4 decode sharding cases. +"""milestone-gqa-decode-long-ctx-4cases: long-context decode 4-cases study. Per GQA_full_deck.pptx slides 11-17: 4 KV-cache sharding strategies on -the LLaMA-3.1-70B single-KV-head group (8 cubes × 8 PEs): +the LLaMA-3.1-70B single-KV-head group (8 cubes × 8 PEs) at long +context (S_kv = 128K, T_q = 1): Case 1 Cube-SP / PE-TP → KV split by S_kv across cubes; PEs TP on batch Case 2 Cube-Repl / PE-TP → full KV per cube; PEs TP on batch @@ -13,18 +14,11 @@ invocation and writes per-panel op_log_summary to sweep.json so the comparative analysis (latency, GEMM/MAC util, comm volume) can be generated from a single sweep. -Status (initial commit, 5C.D): - - Case 4 panel implemented (uses _gqa_attention_decode_long with - sub_w=4 — ADR-0060 §4.2 lrab-adapted center-root reduce; that is - structurally Case 4 per slide 11 with the reduce-to-root variant - of the AR pattern). - - Cases 1-3 panels: TBD in subsequent sub-increments (5C.A/B/C). - Deviation from slide 13: slide prescribes AllReduce (every rank has the answer); the kernel does reduce-to-root (only the lrab center cube has it) per ADR-0060 §4. Treated as the kernbench Case-4 baseline. -Gated by ``GQA_DECODE_4CASES_RUN=1``. +Gated by ``GQA_DECODE_LONG_CTX_4CASES_RUN=1``. """ from __future__ import annotations @@ -32,17 +26,17 @@ import json import os from pathlib import Path -from kernbench.benches._gqa_attention_decode_cube_repl_pe_sp import ( - gqa_attention_decode_cube_repl_pe_sp_kernel, +from kernbench.benches._gqa_attention_decode_long_ctx_cube_repl_pe_sp import ( + gqa_attention_decode_long_ctx_cube_repl_pe_sp_kernel, ) -from kernbench.benches._gqa_attention_decode_cube_repl_pe_tp import ( - gqa_attention_decode_cube_repl_pe_tp_kernel, +from kernbench.benches._gqa_attention_decode_long_ctx_cube_repl_pe_tp import ( + gqa_attention_decode_long_ctx_cube_repl_pe_tp_kernel, ) -from kernbench.benches._gqa_attention_decode_cube_sp_pe_sp import ( - gqa_attention_decode_cube_sp_pe_sp_kernel, +from kernbench.benches._gqa_attention_decode_long_ctx_cube_sp_pe_sp import ( + gqa_attention_decode_long_ctx_cube_sp_pe_sp_kernel, ) -from kernbench.benches._gqa_attention_decode_cube_sp_pe_tp import ( - gqa_attention_decode_cube_sp_pe_tp_kernel, +from kernbench.benches._gqa_attention_decode_long_ctx_cube_sp_pe_tp import ( + gqa_attention_decode_long_ctx_cube_sp_pe_tp_kernel, ) from kernbench.benches.milestone_gqa_headline import ( _ccl_cfg, @@ -55,7 +49,7 @@ from kernbench.policy.placement.dp import DPPolicy _OUTPUT_DIR = ( Path(__file__).resolve().parent / "1H_milestone_output" - / "gqa_decode_4cases" + / "gqa_decode_long_ctx_4cases" ) _SWEEP_JSON = _OUTPUT_DIR / "sweep.json" @@ -64,10 +58,10 @@ _SWEEP_JSON = _OUTPUT_DIR / "sweep.json" _PANELS = ( - "single_kv_group_decode_gqa_cube_sp_pe_sp", # Case 4 ★ optimal - "single_kv_group_decode_gqa_cube_repl_pe_tp", # Case 2 (no comm; 8× memory) - "single_kv_group_decode_gqa_cube_repl_pe_sp", # Case 3 (intra-CUBE AR only; 8× memory) - "single_kv_group_decode_gqa_cube_sp_pe_tp", # Case 1 (inter-CUBE lrab only; PE-TP B=1 waste) + "single_kv_group_decode_long_ctx_gqa_cube_sp_pe_sp", # Case 4 ★ optimal + "single_kv_group_decode_long_ctx_gqa_cube_repl_pe_tp", # Case 2 (no comm; 8× memory) + "single_kv_group_decode_long_ctx_gqa_cube_repl_pe_sp", # Case 3 (intra-CUBE AR only; 8× memory) + "single_kv_group_decode_long_ctx_gqa_cube_sp_pe_tp", # Case 1 (inter-CUBE lrab only; PE-TP B=1 waste) ) # Each entry: (kind, panel-specific params). @@ -76,7 +70,7 @@ _PANELS = ( # 8 cubes (head-parallel group), 8 PEs/cube # S_kv = 128K (long-context decode), T_q = 1 (one new token per pass) _PANEL_DISPATCH: dict[str, tuple[str, dict]] = { - "single_kv_group_decode_gqa_cube_sp_pe_sp": ("decode_cube_sp_pe_sp", { + "single_kv_group_decode_long_ctx_gqa_cube_sp_pe_sp": ("decode_long_ctx_cube_sp_pe_sp", { # Case 4: KV split 64-way (Cube-SP × PE-SP), 2-level reduce. # The sub_w=4/sub_h=2 lrab center-root geometry (root cube 6) is # baked into the Case-4 wrapper kernel. @@ -84,7 +78,7 @@ _PANEL_DISPATCH: dict[str, tuple[str, dict]] = { "T_q": 1, "S_kv": 131_072, "d_head": 128, "h_q": 8, "h_kv": 1, }), - "single_kv_group_decode_gqa_cube_repl_pe_tp": ("decode_cube_repl_pe_tp", { + "single_kv_group_decode_long_ctx_gqa_cube_repl_pe_tp": ("decode_long_ctx_cube_repl_pe_tp", { # Case 2: K, V replicated everywhere (8× memory waste); PEs TP # on batch. For B=1 only one rank works (slide-11 PE-TP waste). # No inter-rank communication. @@ -92,7 +86,7 @@ _PANEL_DISPATCH: dict[str, tuple[str, dict]] = { "T_q": 1, "S_kv": 131_072, "d_head": 128, "h_q": 8, "h_kv": 1, }), - "single_kv_group_decode_gqa_cube_repl_pe_sp": ("decode_cube_repl_pe_sp", { + "single_kv_group_decode_long_ctx_gqa_cube_repl_pe_sp": ("decode_long_ctx_cube_repl_pe_sp", { # Case 3: K, V replicated per cube (8× memory); PEs SP on S_kv # within each cube. Intra-CUBE 8-way reduce; no inter-CUBE comm # (every cube ends with full answer; designated writer = cube 0). @@ -100,7 +94,7 @@ _PANEL_DISPATCH: dict[str, tuple[str, dict]] = { "T_q": 1, "S_kv": 131_072, "d_head": 128, "h_q": 8, "h_kv": 1, }), - "single_kv_group_decode_gqa_cube_sp_pe_tp": ("decode_cube_sp_pe_tp", { + "single_kv_group_decode_long_ctx_gqa_cube_sp_pe_tp": ("decode_long_ctx_cube_sp_pe_tp", { # Case 1: K, V split across cubes (S_local = S_kv/C per cube); # PEs TP on batch — at B=1 only PE 0 of each cube works (PE-TP # waste). Inter-CUBE lrab AR (root = cube 6); no intra-CUBE comm. @@ -114,7 +108,7 @@ _PANEL_DISPATCH: dict[str, tuple[str, dict]] = { # ── Per-panel runner ───────────────────────────────────────────────── -def _run_decode_panel_cube_repl_pe_tp( +def _run_decode_panel_long_ctx_cube_repl_pe_tp( ctx, *, panel: str, C: int, P: int, T_q: int, S_kv: int, d_head: int, h_q: int, h_kv: int, @@ -138,14 +132,14 @@ def _run_decode_panel_cube_repl_pe_tp( o = ctx.empty((T_q, h_q * d_head), dtype="f16", dp=dp_repl, name=f"{panel}_o") ctx.launch( - panel, gqa_attention_decode_cube_repl_pe_tp_kernel, + panel, gqa_attention_decode_long_ctx_cube_repl_pe_tp_kernel, q, k, v, o, T_q, S_kv, h_q, h_kv, d_head, C, P, _auto_dim_remap=False, ) -def _run_decode_panel_cube_repl_pe_sp( +def _run_decode_panel_long_ctx_cube_repl_pe_sp( ctx, *, panel: str, C: int, P: int, T_q: int, S_kv: int, d_head: int, h_q: int, h_kv: int, @@ -171,14 +165,14 @@ def _run_decode_panel_cube_repl_pe_sp( o = ctx.empty((T_q, h_q * d_head), dtype="f16", dp=dp_full, name=f"{panel}_o") ctx.launch( - panel, gqa_attention_decode_cube_repl_pe_sp_kernel, + panel, gqa_attention_decode_long_ctx_cube_repl_pe_sp_kernel, q, k, v, o, T_q, S_kv, h_q, h_kv, d_head, C, P, _auto_dim_remap=False, ) -def _run_decode_panel_cube_sp_pe_tp( +def _run_decode_panel_long_ctx_cube_sp_pe_tp( ctx, *, panel: str, C: int, P: int, T_q: int, S_kv: int, d_head: int, h_q: int, h_kv: int, @@ -205,14 +199,14 @@ def _run_decode_panel_cube_sp_pe_tp( o = ctx.empty((T_q, h_q * d_head), dtype="f16", dp=dp_full, name=f"{panel}_o") ctx.launch( - panel, gqa_attention_decode_cube_sp_pe_tp_kernel, + panel, gqa_attention_decode_long_ctx_cube_sp_pe_tp_kernel, q, k, v, o, T_q, S_kv, h_q, h_kv, d_head, C, P, _auto_dim_remap=False, ) -def _run_decode_panel_cube_sp_pe_sp( +def _run_decode_panel_long_ctx_cube_sp_pe_sp( ctx, *, panel: str, C: int, P: int, T_q: int, S_kv: int, d_head: int, h_q: int, h_kv: int, @@ -237,7 +231,7 @@ def _run_decode_panel_cube_sp_pe_sp( o = ctx.empty((T_q, h_q * d_head), dtype="f16", dp=dp_full, name=f"{panel}_o") ctx.launch( - panel, gqa_attention_decode_cube_sp_pe_sp_kernel, + panel, gqa_attention_decode_long_ctx_cube_sp_pe_sp_kernel, q, k, v, o, T_q, S_kv, h_q, h_kv, d_head, C, P, _auto_dim_remap=False, @@ -248,17 +242,17 @@ def _make_bench_fn(panel: str): kind, params = _PANEL_DISPATCH[panel] def _bench_fn(ctx): - if kind == "decode_cube_sp_pe_sp": - _run_decode_panel_cube_sp_pe_sp(ctx, panel=panel, **params) - elif kind == "decode_cube_repl_pe_tp": - _run_decode_panel_cube_repl_pe_tp(ctx, panel=panel, **params) - elif kind == "decode_cube_repl_pe_sp": - _run_decode_panel_cube_repl_pe_sp(ctx, panel=panel, **params) - elif kind == "decode_cube_sp_pe_tp": - _run_decode_panel_cube_sp_pe_tp(ctx, panel=panel, **params) + if kind == "decode_long_ctx_cube_sp_pe_sp": + _run_decode_panel_long_ctx_cube_sp_pe_sp(ctx, panel=panel, **params) + elif kind == "decode_long_ctx_cube_repl_pe_tp": + _run_decode_panel_long_ctx_cube_repl_pe_tp(ctx, panel=panel, **params) + elif kind == "decode_long_ctx_cube_repl_pe_sp": + _run_decode_panel_long_ctx_cube_repl_pe_sp(ctx, panel=panel, **params) + elif kind == "decode_long_ctx_cube_sp_pe_tp": + _run_decode_panel_long_ctx_cube_sp_pe_tp(ctx, panel=panel, **params) else: raise RuntimeError( - f"milestone-gqa-decode-4cases panel {panel!r} has " + f"milestone-gqa-decode-long-ctx-4cases panel {panel!r} has " f"unsupported kind={kind!r}." ) return _bench_fn @@ -280,7 +274,7 @@ def _run_panel(panel: str, topology: str) -> dict: ) if not result.completion.ok: raise RuntimeError( - f"milestone-gqa-decode-4cases panel {panel!r} failed: " + f"milestone-gqa-decode-long-ctx-4cases panel {panel!r} failed: " f"{result.completion}" ) kind, params = _PANEL_DISPATCH[panel] @@ -296,25 +290,26 @@ def _run_panel(panel: str, topology: str) -> dict: @bench( - name="milestone-gqa-decode-4cases", + name="milestone-gqa-decode-long-ctx-4cases", description=( - "Comparative decode study of 4 KV-cache sharding cases on the " + "Long-context decode 4-cases comparative study on the " "LLaMA-3.1-70B single-KV-head group (8 cubes × 8 PEs)." ), ) def run(torch) -> None: """Drive the registered decode case panels; write sweep.json. - Gated by GQA_DECODE_4CASES_RUN=1. + Gated by GQA_DECODE_LONG_CTX_4CASES_RUN=1. """ _OUTPUT_DIR.mkdir(parents=True, exist_ok=True) - if not os.environ.get("GQA_DECODE_4CASES_RUN"): + if not os.environ.get("GQA_DECODE_LONG_CTX_4CASES_RUN"): raise RuntimeError( - "milestone-gqa-decode-4cases needs GQA_DECODE_4CASES_RUN=1." + "milestone-gqa-decode-long-ctx-4cases needs " + "GQA_DECODE_LONG_CTX_4CASES_RUN=1." ) topology = os.environ.get( - "GQA_DECODE_4CASES_TOPOLOGY", "topology.yaml", + "GQA_DECODE_LONG_CTX_4CASES_TOPOLOGY", "topology.yaml", ) rows = [_run_panel(panel, topology) for panel in _PANELS] sweep = { @@ -324,5 +319,5 @@ def run(torch) -> None: } _SWEEP_JSON.write_text(json.dumps(sweep, indent=2)) print( - f" milestone-gqa-decode-4cases: {len(rows)} rows -> {_SWEEP_JSON}" + f" milestone-gqa-decode-long-ctx-4cases: {len(rows)} rows -> {_SWEEP_JSON}" ) diff --git a/tests/attention/test_milestone_gqa_decode_4cases.py b/tests/attention/test_milestone_gqa_decode_long_ctx_4cases.py similarity index 83% rename from tests/attention/test_milestone_gqa_decode_4cases.py rename to tests/attention/test_milestone_gqa_decode_long_ctx_4cases.py index efbf0e3..a2d0684 100644 --- a/tests/attention/test_milestone_gqa_decode_4cases.py +++ b/tests/attention/test_milestone_gqa_decode_long_ctx_4cases.py @@ -1,4 +1,4 @@ -"""Tests for the decode 4-cases comparative-study bench. +"""Tests for the long-context decode 4-cases comparative-study bench. Per ``GQA_full_deck.pptx`` slides 11-17, the 4 cases differ in how KV cache is sharded across the 8 cubes and 8 PEs of a single KV-head @@ -9,28 +9,15 @@ group on LLaMA-3.1-70B GQA: Case 3 Cube-Repl / PE-SP → full KV per cube; PEs SP on S_kv (intra-cube AR) Case 4 Cube-SP / PE-SP → KV split 64-way; 2-phase AR on (m,ℓ,O) ★ optimal -This file grows as each case lands. Phase 1 of 5C.D adds Case 4 first, -which is structurally the existing ``_gqa_attention_decode_long.py`` at -``sub_w=4`` (Increment 2's lrab-adapted center-root reduce). The Phase 2 -production change introduces a new bench file -``src/kernbench/benches/milestone_gqa_decode_4cases.py`` housing the 4 -case panels under a single ``milestone-gqa-decode-4cases`` entry, and -extends ``_run_decode_panel`` in ``milestone_gqa_headline`` to accept -``sub_w``/``d_head``/``h_q``/``h_kv`` overrides. - Deviation from slide 13: slide prescribes AllReduce on (m,ℓ,O); the kernel does reduce-to-root (only the lrab center cube has the answer) per ADR-0060 §4. Treated as the kernbench Case-4 baseline. - -Phase 1: tests only. T1, T2, T3, T4 fail today (new bench file does -not yet exist; ``_run_decode_panel`` does not yet accept ``sub_w``). """ from __future__ import annotations import re from pathlib import Path -from kernbench.benches.milestone_gqa_headline import _run_decode_panel from kernbench.runtime_api.bench_runner import run_bench from kernbench.runtime_api.types import resolve_device from kernbench.sim_engine.engine import GraphEngine @@ -38,10 +25,10 @@ from kernbench.topology.builder import resolve_topology TOPOLOGY_DEFAULT = Path(__file__).resolve().parents[2] / "topology.yaml" -_CASE4_PANEL = "single_kv_group_decode_gqa_cube_sp_pe_sp" -_CASE3_PANEL = "single_kv_group_decode_gqa_cube_repl_pe_sp" -_CASE2_PANEL = "single_kv_group_decode_gqa_cube_repl_pe_tp" -_CASE1_PANEL = "single_kv_group_decode_gqa_cube_sp_pe_tp" +_CASE4_PANEL = "single_kv_group_decode_long_ctx_gqa_cube_sp_pe_sp" +_CASE3_PANEL = "single_kv_group_decode_long_ctx_gqa_cube_repl_pe_sp" +_CASE2_PANEL = "single_kv_group_decode_long_ctx_gqa_cube_repl_pe_tp" +_CASE1_PANEL = "single_kv_group_decode_long_ctx_gqa_cube_sp_pe_tp" _CUBE_RE = re.compile(r"\bcube(\d+)\b") @@ -64,20 +51,26 @@ def _dma_write_cubes(op_log) -> list[int]: return cubes +# ── Case 4 (Cube-SP × PE-SP) — ★ optimal ──────────────────────────── + + def _run_case4_smoke(*, S_kv: int): - """Drive the Case 4 decode panel via ``_run_decode_panel``. + """Drive the Case 4 decode panel via the case-specific runner. Uses ``S_kv=8192`` (smoke) to keep test time bounded; the headline ``S_kv=128K`` runs come from ``kernbench run --bench - milestone-gqa-decode-4cases``, not pytest. + milestone-gqa-decode-long-ctx-4cases``, not pytest. """ + from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import ( + _run_decode_panel_long_ctx_cube_sp_pe_sp, + ) topo = resolve_topology(str(TOPOLOGY_DEFAULT)) def _bench_fn(ctx): - _run_decode_panel( + _run_decode_panel_long_ctx_cube_sp_pe_sp( ctx, panel=_CASE4_PANEL, - C=8, P=8, sub_w=4, - S_kv=S_kv, + C=8, P=8, + T_q=1, S_kv=S_kv, d_head=128, h_q=8, h_kv=1, ) @@ -88,11 +81,11 @@ def _run_case4_smoke(*, S_kv: int): ) -# ── T1: Case 4 panel is registered in the new bench ────────────────── +# ── Case 4 — T1: panel is registered in the bench ─────────────────── def test_case4_panel_registered(): - """The Case 4 panel must be in the new bench's ``_PANELS`` + + """The Case 4 panel must be in the bench's ``_PANELS`` + ``_PANEL_DISPATCH`` with the expected LLaMA-3.1-70B target dims. Headline config: @@ -103,10 +96,9 @@ def test_case4_panel_registered(): d_head = 128, h_q = 8, h_kv = 1 The lrab sub_w=4 / sub_h=2 geometry is baked into the Case 4 - wrapper kernel (``_gqa_attention_decode_cube_sp_pe_sp.py``); it - is not a panel parameter. + wrapper kernel; it is not a panel parameter. """ - from kernbench.benches.milestone_gqa_decode_4cases import ( + from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import ( _PANEL_DISPATCH, _PANELS, ) @@ -115,8 +107,8 @@ def test_case4_panel_registered(): ) assert _CASE4_PANEL in _PANEL_DISPATCH kind, params = _PANEL_DISPATCH[_CASE4_PANEL] - assert kind == "decode_cube_sp_pe_sp", ( - f"kind={kind!r}, expected 'decode_cube_sp_pe_sp'" + assert kind == "decode_long_ctx_cube_sp_pe_sp", ( + f"kind={kind!r}, expected 'decode_long_ctx_cube_sp_pe_sp'" ) assert params.get("C") == 8 assert params.get("P") == 8 @@ -127,26 +119,19 @@ def test_case4_panel_registered(): assert params.get("h_kv") == 1 -# ── T2: Case 4 runner drives the kernel to completion ─────────────── +# ── Case 4 — T2: runner drives the kernel to completion ───────────── def test_case4_runner_smoke(): - """``_run_decode_panel`` must accept the new ``sub_w``, - ``d_head``, ``h_q``, ``h_kv`` kwargs and launch the kernel at - ``(C, P, sub_w) = (8, 8, 4)`` (the Case 4 / lrab path). - - Smoke uses ``S_kv=8192`` so the simulation completes quickly. The - headline 128K dims run via ``kernbench run --bench - milestone-gqa-decode-4cases``. - """ + """Case 4 runner drives the new kernel to completion at smoke S_kv.""" result = _run_case4_smoke(S_kv=8192) assert result.completion.ok, ( - f"Case 4 decode smoke at C=8 P=8 sub_w=4 must complete; " + f"Case 4 decode smoke at C=8 P=8 must complete; " f"got {result.completion}" ) -# ── T3: reduce-to-root lands at the lrab center cube (cube 6) ─────── +# ── Case 4 — T3: reduce-to-root at the lrab center cube (cube 6) ──── def test_case4_root_at_center_cube_6(): @@ -165,7 +150,37 @@ def test_case4_root_at_center_cube_6(): ) -# ── T4: 2-phase AR ipcq pattern matches the predicted Case-4 traffic ─ +# ── Case 4 — T4: 2-phase AR ipcq pattern matches Case-4 traffic ───── + + +def test_case4_two_level_ar_ipcq_pattern(): + """Total ipcq_copy for the Case 4 reduce at (C, P, sub_w) = + (8, 8, 4): + + Intra-CUBE (per CUBE = 8 PEs in a 2×4 grid): + row chain along intra_W: cols 1,2,3 each row × 2 rows × + 3 tensors = 18 + col bridge along intra_N: pe4 only × 3 tensors = 3 + per-CUBE intra total = 21 + × 8 CUBEs = 168 + + Inter-CUBE lrab (sub_w=4, sub_h=2): + Phase 1 row reduce — 3 sends/row × 3 tensors × 2 rows = 18 + Phase 2 col reduce — cube 2 → S × 3 tensors = 3 + inter-CUBE total = 21 + + Grand total: 168 + 21 = 189 + """ + result = _run_case4_smoke(S_kv=8192) + assert result.completion.ok + n_copy = _count(result.engine.op_log, "ipcq_copy") + assert n_copy == 189, ( + f"Case 4 expected 189 ipcq_copy " + f"(168 intra-CUBE + 21 inter-CUBE lrab); got {n_copy}" + ) + + +# ── Case 2 (Cube-Repl × PE-TP) ────────────────────────────────────── def _run_case2_smoke(*, S_kv: int): @@ -175,13 +190,13 @@ def _run_case2_smoke(*, S_kv: int): slide-11 memory waste); for B=1 only one rank does the work; no inter-rank comm. """ - from kernbench.benches.milestone_gqa_decode_4cases import ( - _run_decode_panel_cube_repl_pe_tp, + from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import ( + _run_decode_panel_long_ctx_cube_repl_pe_tp, ) topo = resolve_topology(str(TOPOLOGY_DEFAULT)) def _bench_fn(ctx): - _run_decode_panel_cube_repl_pe_tp( + _run_decode_panel_long_ctx_cube_repl_pe_tp( ctx, panel=_CASE2_PANEL, C=8, P=8, T_q=1, S_kv=S_kv, @@ -207,7 +222,7 @@ def test_case2_panel_registered(): For B=1 only one rank works (PEs 1-7 idle — slide-11 calls out this PE-TP waste). """ - from kernbench.benches.milestone_gqa_decode_4cases import ( + from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import ( _PANEL_DISPATCH, _PANELS, ) @@ -216,7 +231,7 @@ def test_case2_panel_registered(): ) assert _CASE2_PANEL in _PANEL_DISPATCH kind, params = _PANEL_DISPATCH[_CASE2_PANEL] - assert kind == "decode_cube_repl_pe_tp" + assert kind == "decode_long_ctx_cube_repl_pe_tp" assert params.get("C") == 8 assert params.get("P") == 8 assert params.get("T_q") == 1 @@ -281,13 +296,13 @@ def _run_case3_smoke(*, S_kv: int): 8-way across PEs within each cube. Intra-CUBE 8-way reduce on (m, ℓ, O); no inter-CUBE comm (every cube ends with full answer). """ - from kernbench.benches.milestone_gqa_decode_4cases import ( - _run_decode_panel_cube_repl_pe_sp, + from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import ( + _run_decode_panel_long_ctx_cube_repl_pe_sp, ) topo = resolve_topology(str(TOPOLOGY_DEFAULT)) def _bench_fn(ctx): - _run_decode_panel_cube_repl_pe_sp( + _run_decode_panel_long_ctx_cube_repl_pe_sp( ctx, panel=_CASE3_PANEL, C=8, P=8, T_q=1, S_kv=S_kv, @@ -311,7 +326,7 @@ def test_case3_panel_registered(): Case 3: Cube-Repl × PE-SP. K, V replicated per cube; PEs SP on S_kv. Intra-CUBE 8-way AR; no inter-CUBE comm. """ - from kernbench.benches.milestone_gqa_decode_4cases import ( + from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import ( _PANEL_DISPATCH, _PANELS, ) @@ -320,7 +335,7 @@ def test_case3_panel_registered(): ) assert _CASE3_PANEL in _PANEL_DISPATCH kind, params = _PANEL_DISPATCH[_CASE3_PANEL] - assert kind == "decode_cube_repl_pe_sp" + assert kind == "decode_long_ctx_cube_repl_pe_sp" assert params.get("C") == 8 assert params.get("P") == 8 assert params.get("T_q") == 1 @@ -401,13 +416,13 @@ def _run_case1_smoke(*, S_kv: int): each cube has work; PEs 1-7 idle. Inter-CUBE 8-way reduce via the lrab-adapted center-root pattern (root cube 6); no intra-CUBE comm. """ - from kernbench.benches.milestone_gqa_decode_4cases import ( - _run_decode_panel_cube_sp_pe_tp, + from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import ( + _run_decode_panel_long_ctx_cube_sp_pe_tp, ) topo = resolve_topology(str(TOPOLOGY_DEFAULT)) def _bench_fn(ctx): - _run_decode_panel_cube_sp_pe_tp( + _run_decode_panel_long_ctx_cube_sp_pe_tp( ctx, panel=_CASE1_PANEL, C=8, P=8, T_q=1, S_kv=S_kv, @@ -432,7 +447,7 @@ def test_case1_panel_registered(): batch. At B=1 only PE 0 of each cube works (PE-TP waste). Inter-CUBE lrab AR; no intra-CUBE comm. """ - from kernbench.benches.milestone_gqa_decode_4cases import ( + from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import ( _PANEL_DISPATCH, _PANELS, ) @@ -441,7 +456,7 @@ def test_case1_panel_registered(): ) assert _CASE1_PANEL in _PANEL_DISPATCH kind, params = _PANEL_DISPATCH[_CASE1_PANEL] - assert kind == "decode_cube_sp_pe_tp" + assert kind == "decode_long_ctx_cube_sp_pe_tp" assert params.get("C") == 8 assert params.get("P") == 8 assert params.get("T_q") == 1 @@ -507,33 +522,3 @@ def test_case1_root_at_center_cube_6(): f"Case 1 root must be the lrab center cube 6; " f"got cubes={sorted(distinct)}" ) - - -# ── Case 4 — T4 (existing, kept) ──────────────────────────────────── - - -def test_case4_two_level_ar_ipcq_pattern(): - """Total ipcq_copy for the Case 4 reduce at (C, P, sub_w) = - (8, 8, 4): - - Intra-CUBE (per CUBE = 8 PEs in a 2×4 grid): - row chain along intra_W: cols 1,2,3 each row × 2 rows × - 3 tensors = 18 - col bridge along intra_N: pe4 only × 3 tensors = 3 - per-CUBE intra total = 21 - × 8 CUBEs = 168 - - Inter-CUBE lrab (sub_w=4, sub_h=2): - Phase 1 row reduce — 3 sends/row × 3 tensors × 2 rows = 18 - Phase 2 col reduce — cube 2 → S × 3 tensors = 3 - inter-CUBE total = 21 - - Grand total: 168 + 21 = 189 - """ - result = _run_case4_smoke(S_kv=8192) - assert result.completion.ok - n_copy = _count(result.engine.op_log, "ipcq_copy") - assert n_copy == 189, ( - f"Case 4 expected 189 ipcq_copy " - f"(168 intra-CUBE + 21 inter-CUBE lrab); got {n_copy}" - )