gqa(decode-4cases): rename bench/kernels/panels with long_ctx token
The 4-cases comparative study is specifically about long-context
decode (LLaMA-3.1-70B, S_kv=128K, T_q=1); the long_ctx token in the
names makes the scope explicit and aligns with the existing
_gqa_attention_decode_long convention.
Renames (mechanical; no semantic change):
- bench file: milestone_gqa_decode_4cases.py
→ milestone_gqa_decode_long_ctx_4cases.py
- bench name: milestone-gqa-decode-4cases
→ milestone-gqa-decode-long-ctx-4cases
- output dir: 1H_milestone_output/gqa_decode_4cases/
→ 1H_milestone_output/gqa_decode_long_ctx_4cases/
- env vars: GQA_DECODE_4CASES_RUN / _TOPOLOGY
→ GQA_DECODE_LONG_CTX_4CASES_RUN / _TOPOLOGY
- 4 kernel files _gqa_attention_decode_<case>.py
→ _gqa_attention_decode_long_ctx_<case>.py
- 4 kernel functions gqa_attention_decode_<case>_kernel
→ gqa_attention_decode_long_ctx_<case>_kernel
- 4 dispatch kinds decode_<case> → decode_long_ctx_<case>
- 4 panel names single_kv_group_decode_gqa_<case>
→ single_kv_group_decode_long_ctx_gqa_<case>
- 4 helper functions _run_decode_panel_<case>
→ _run_decode_panel_long_ctx_<case>
- test file renamed in lockstep
Also: Case 4 smoke test now uses its case-specific helper
_run_decode_panel_long_ctx_cube_sp_pe_sp (consistent with Cases 1-3)
instead of the legacy _run_decode_panel from milestone_gqa_headline.
16 tests pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -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).
|
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,
|
q_ptr: int,
|
||||||
k_ptr: int,
|
k_ptr: int,
|
||||||
v_ptr: int,
|
v_ptr: int,
|
||||||
+1
-1
@@ -31,7 +31,7 @@ from __future__ import annotations
|
|||||||
TILE_S_KV = 1024 # match decode_long — per-tile S_kv width (ADR-0063 §A.2).
|
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,
|
q_ptr: int,
|
||||||
k_ptr: int,
|
k_ptr: int,
|
||||||
v_ptr: int,
|
v_ptr: int,
|
||||||
+1
-1
@@ -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,
|
q_ptr: int,
|
||||||
k_ptr: int,
|
k_ptr: int,
|
||||||
v_ptr: int,
|
v_ptr: int,
|
||||||
+1
-1
@@ -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).
|
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,
|
q_ptr: int,
|
||||||
k_ptr: int,
|
k_ptr: int,
|
||||||
v_ptr: int,
|
v_ptr: int,
|
||||||
+47
-52
@@ -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
|
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 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
|
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
|
comparative analysis (latency, GEMM/MAC util, comm volume) can be
|
||||||
generated from a single sweep.
|
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
|
Deviation from slide 13: slide prescribes AllReduce (every rank has
|
||||||
the answer); the kernel does reduce-to-root (only the lrab center
|
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.
|
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
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -32,17 +26,17 @@ import json
|
|||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from kernbench.benches._gqa_attention_decode_cube_repl_pe_sp import (
|
from kernbench.benches._gqa_attention_decode_long_ctx_cube_repl_pe_sp import (
|
||||||
gqa_attention_decode_cube_repl_pe_sp_kernel,
|
gqa_attention_decode_long_ctx_cube_repl_pe_sp_kernel,
|
||||||
)
|
)
|
||||||
from kernbench.benches._gqa_attention_decode_cube_repl_pe_tp import (
|
from kernbench.benches._gqa_attention_decode_long_ctx_cube_repl_pe_tp import (
|
||||||
gqa_attention_decode_cube_repl_pe_tp_kernel,
|
gqa_attention_decode_long_ctx_cube_repl_pe_tp_kernel,
|
||||||
)
|
)
|
||||||
from kernbench.benches._gqa_attention_decode_cube_sp_pe_sp import (
|
from kernbench.benches._gqa_attention_decode_long_ctx_cube_sp_pe_sp import (
|
||||||
gqa_attention_decode_cube_sp_pe_sp_kernel,
|
gqa_attention_decode_long_ctx_cube_sp_pe_sp_kernel,
|
||||||
)
|
)
|
||||||
from kernbench.benches._gqa_attention_decode_cube_sp_pe_tp import (
|
from kernbench.benches._gqa_attention_decode_long_ctx_cube_sp_pe_tp import (
|
||||||
gqa_attention_decode_cube_sp_pe_tp_kernel,
|
gqa_attention_decode_long_ctx_cube_sp_pe_tp_kernel,
|
||||||
)
|
)
|
||||||
from kernbench.benches.milestone_gqa_headline import (
|
from kernbench.benches.milestone_gqa_headline import (
|
||||||
_ccl_cfg,
|
_ccl_cfg,
|
||||||
@@ -55,7 +49,7 @@ from kernbench.policy.placement.dp import DPPolicy
|
|||||||
_OUTPUT_DIR = (
|
_OUTPUT_DIR = (
|
||||||
Path(__file__).resolve().parent
|
Path(__file__).resolve().parent
|
||||||
/ "1H_milestone_output"
|
/ "1H_milestone_output"
|
||||||
/ "gqa_decode_4cases"
|
/ "gqa_decode_long_ctx_4cases"
|
||||||
)
|
)
|
||||||
_SWEEP_JSON = _OUTPUT_DIR / "sweep.json"
|
_SWEEP_JSON = _OUTPUT_DIR / "sweep.json"
|
||||||
|
|
||||||
@@ -64,10 +58,10 @@ _SWEEP_JSON = _OUTPUT_DIR / "sweep.json"
|
|||||||
|
|
||||||
|
|
||||||
_PANELS = (
|
_PANELS = (
|
||||||
"single_kv_group_decode_gqa_cube_sp_pe_sp", # Case 4 ★ optimal
|
"single_kv_group_decode_long_ctx_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_long_ctx_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_long_ctx_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_tp", # Case 1 (inter-CUBE lrab only; PE-TP B=1 waste)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Each entry: (kind, panel-specific params).
|
# Each entry: (kind, panel-specific params).
|
||||||
@@ -76,7 +70,7 @@ _PANELS = (
|
|||||||
# 8 cubes (head-parallel group), 8 PEs/cube
|
# 8 cubes (head-parallel group), 8 PEs/cube
|
||||||
# S_kv = 128K (long-context decode), T_q = 1 (one new token per pass)
|
# S_kv = 128K (long-context decode), T_q = 1 (one new token per pass)
|
||||||
_PANEL_DISPATCH: dict[str, tuple[str, dict]] = {
|
_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.
|
# 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
|
# The sub_w=4/sub_h=2 lrab center-root geometry (root cube 6) is
|
||||||
# baked into the Case-4 wrapper kernel.
|
# 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,
|
"T_q": 1, "S_kv": 131_072,
|
||||||
"d_head": 128, "h_q": 8, "h_kv": 1,
|
"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
|
# 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).
|
# on batch. For B=1 only one rank works (slide-11 PE-TP waste).
|
||||||
# No inter-rank communication.
|
# No inter-rank communication.
|
||||||
@@ -92,7 +86,7 @@ _PANEL_DISPATCH: dict[str, tuple[str, dict]] = {
|
|||||||
"T_q": 1, "S_kv": 131_072,
|
"T_q": 1, "S_kv": 131_072,
|
||||||
"d_head": 128, "h_q": 8, "h_kv": 1,
|
"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
|
# 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
|
# within each cube. Intra-CUBE 8-way reduce; no inter-CUBE comm
|
||||||
# (every cube ends with full answer; designated writer = cube 0).
|
# (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,
|
"T_q": 1, "S_kv": 131_072,
|
||||||
"d_head": 128, "h_q": 8, "h_kv": 1,
|
"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);
|
# 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
|
# 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.
|
# 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 ─────────────────────────────────────────────────
|
# ── 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,
|
ctx, *, panel: str, C: int, P: int,
|
||||||
T_q: int, S_kv: int,
|
T_q: int, S_kv: int,
|
||||||
d_head: int, h_q: int, h_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),
|
o = ctx.empty((T_q, h_q * d_head),
|
||||||
dtype="f16", dp=dp_repl, name=f"{panel}_o")
|
dtype="f16", dp=dp_repl, name=f"{panel}_o")
|
||||||
ctx.launch(
|
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,
|
q, k, v, o,
|
||||||
T_q, S_kv, h_q, h_kv, d_head, C, P,
|
T_q, S_kv, h_q, h_kv, d_head, C, P,
|
||||||
_auto_dim_remap=False,
|
_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,
|
ctx, *, panel: str, C: int, P: int,
|
||||||
T_q: int, S_kv: int,
|
T_q: int, S_kv: int,
|
||||||
d_head: int, h_q: int, h_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),
|
o = ctx.empty((T_q, h_q * d_head),
|
||||||
dtype="f16", dp=dp_full, name=f"{panel}_o")
|
dtype="f16", dp=dp_full, name=f"{panel}_o")
|
||||||
ctx.launch(
|
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,
|
q, k, v, o,
|
||||||
T_q, S_kv, h_q, h_kv, d_head, C, P,
|
T_q, S_kv, h_q, h_kv, d_head, C, P,
|
||||||
_auto_dim_remap=False,
|
_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,
|
ctx, *, panel: str, C: int, P: int,
|
||||||
T_q: int, S_kv: int,
|
T_q: int, S_kv: int,
|
||||||
d_head: int, h_q: int, h_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),
|
o = ctx.empty((T_q, h_q * d_head),
|
||||||
dtype="f16", dp=dp_full, name=f"{panel}_o")
|
dtype="f16", dp=dp_full, name=f"{panel}_o")
|
||||||
ctx.launch(
|
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,
|
q, k, v, o,
|
||||||
T_q, S_kv, h_q, h_kv, d_head, C, P,
|
T_q, S_kv, h_q, h_kv, d_head, C, P,
|
||||||
_auto_dim_remap=False,
|
_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,
|
ctx, *, panel: str, C: int, P: int,
|
||||||
T_q: int, S_kv: int,
|
T_q: int, S_kv: int,
|
||||||
d_head: int, h_q: int, h_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),
|
o = ctx.empty((T_q, h_q * d_head),
|
||||||
dtype="f16", dp=dp_full, name=f"{panel}_o")
|
dtype="f16", dp=dp_full, name=f"{panel}_o")
|
||||||
ctx.launch(
|
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,
|
q, k, v, o,
|
||||||
T_q, S_kv, h_q, h_kv, d_head, C, P,
|
T_q, S_kv, h_q, h_kv, d_head, C, P,
|
||||||
_auto_dim_remap=False,
|
_auto_dim_remap=False,
|
||||||
@@ -248,17 +242,17 @@ def _make_bench_fn(panel: str):
|
|||||||
kind, params = _PANEL_DISPATCH[panel]
|
kind, params = _PANEL_DISPATCH[panel]
|
||||||
|
|
||||||
def _bench_fn(ctx):
|
def _bench_fn(ctx):
|
||||||
if kind == "decode_cube_sp_pe_sp":
|
if kind == "decode_long_ctx_cube_sp_pe_sp":
|
||||||
_run_decode_panel_cube_sp_pe_sp(ctx, panel=panel, **params)
|
_run_decode_panel_long_ctx_cube_sp_pe_sp(ctx, panel=panel, **params)
|
||||||
elif kind == "decode_cube_repl_pe_tp":
|
elif kind == "decode_long_ctx_cube_repl_pe_tp":
|
||||||
_run_decode_panel_cube_repl_pe_tp(ctx, panel=panel, **params)
|
_run_decode_panel_long_ctx_cube_repl_pe_tp(ctx, panel=panel, **params)
|
||||||
elif kind == "decode_cube_repl_pe_sp":
|
elif kind == "decode_long_ctx_cube_repl_pe_sp":
|
||||||
_run_decode_panel_cube_repl_pe_sp(ctx, panel=panel, **params)
|
_run_decode_panel_long_ctx_cube_repl_pe_sp(ctx, panel=panel, **params)
|
||||||
elif kind == "decode_cube_sp_pe_tp":
|
elif kind == "decode_long_ctx_cube_sp_pe_tp":
|
||||||
_run_decode_panel_cube_sp_pe_tp(ctx, panel=panel, **params)
|
_run_decode_panel_long_ctx_cube_sp_pe_tp(ctx, panel=panel, **params)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
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}."
|
f"unsupported kind={kind!r}."
|
||||||
)
|
)
|
||||||
return _bench_fn
|
return _bench_fn
|
||||||
@@ -280,7 +274,7 @@ def _run_panel(panel: str, topology: str) -> dict:
|
|||||||
)
|
)
|
||||||
if not result.completion.ok:
|
if not result.completion.ok:
|
||||||
raise RuntimeError(
|
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}"
|
f"{result.completion}"
|
||||||
)
|
)
|
||||||
kind, params = _PANEL_DISPATCH[panel]
|
kind, params = _PANEL_DISPATCH[panel]
|
||||||
@@ -296,25 +290,26 @@ def _run_panel(panel: str, topology: str) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
@bench(
|
@bench(
|
||||||
name="milestone-gqa-decode-4cases",
|
name="milestone-gqa-decode-long-ctx-4cases",
|
||||||
description=(
|
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)."
|
"LLaMA-3.1-70B single-KV-head group (8 cubes × 8 PEs)."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def run(torch) -> None:
|
def run(torch) -> None:
|
||||||
"""Drive the registered decode case panels; write sweep.json.
|
"""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)
|
_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(
|
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(
|
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]
|
rows = [_run_panel(panel, topology) for panel in _PANELS]
|
||||||
sweep = {
|
sweep = {
|
||||||
@@ -324,5 +319,5 @@ def run(torch) -> None:
|
|||||||
}
|
}
|
||||||
_SWEEP_JSON.write_text(json.dumps(sweep, indent=2))
|
_SWEEP_JSON.write_text(json.dumps(sweep, indent=2))
|
||||||
print(
|
print(
|
||||||
f" milestone-gqa-decode-4cases: {len(rows)} rows -> {_SWEEP_JSON}"
|
f" milestone-gqa-decode-long-ctx-4cases: {len(rows)} rows -> {_SWEEP_JSON}"
|
||||||
)
|
)
|
||||||
+72
-87
@@ -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
|
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
|
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 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
|
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
|
Deviation from slide 13: slide prescribes AllReduce on (m,ℓ,O); the
|
||||||
kernel does reduce-to-root (only the lrab center cube has the answer)
|
kernel does reduce-to-root (only the lrab center cube has the answer)
|
||||||
per ADR-0060 §4. Treated as the kernbench Case-4 baseline.
|
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
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
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.bench_runner import run_bench
|
||||||
from kernbench.runtime_api.types import resolve_device
|
from kernbench.runtime_api.types import resolve_device
|
||||||
from kernbench.sim_engine.engine import GraphEngine
|
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"
|
TOPOLOGY_DEFAULT = Path(__file__).resolve().parents[2] / "topology.yaml"
|
||||||
|
|
||||||
_CASE4_PANEL = "single_kv_group_decode_gqa_cube_sp_pe_sp"
|
_CASE4_PANEL = "single_kv_group_decode_long_ctx_gqa_cube_sp_pe_sp"
|
||||||
_CASE3_PANEL = "single_kv_group_decode_gqa_cube_repl_pe_sp"
|
_CASE3_PANEL = "single_kv_group_decode_long_ctx_gqa_cube_repl_pe_sp"
|
||||||
_CASE2_PANEL = "single_kv_group_decode_gqa_cube_repl_pe_tp"
|
_CASE2_PANEL = "single_kv_group_decode_long_ctx_gqa_cube_repl_pe_tp"
|
||||||
_CASE1_PANEL = "single_kv_group_decode_gqa_cube_sp_pe_tp"
|
_CASE1_PANEL = "single_kv_group_decode_long_ctx_gqa_cube_sp_pe_tp"
|
||||||
_CUBE_RE = re.compile(r"\bcube(\d+)\b")
|
_CUBE_RE = re.compile(r"\bcube(\d+)\b")
|
||||||
|
|
||||||
|
|
||||||
@@ -64,20 +51,26 @@ def _dma_write_cubes(op_log) -> list[int]:
|
|||||||
return cubes
|
return cubes
|
||||||
|
|
||||||
|
|
||||||
|
# ── Case 4 (Cube-SP × PE-SP) — ★ optimal ────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
def _run_case4_smoke(*, S_kv: int):
|
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
|
Uses ``S_kv=8192`` (smoke) to keep test time bounded; the headline
|
||||||
``S_kv=128K`` runs come from ``kernbench run --bench
|
``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))
|
topo = resolve_topology(str(TOPOLOGY_DEFAULT))
|
||||||
|
|
||||||
def _bench_fn(ctx):
|
def _bench_fn(ctx):
|
||||||
_run_decode_panel(
|
_run_decode_panel_long_ctx_cube_sp_pe_sp(
|
||||||
ctx, panel=_CASE4_PANEL,
|
ctx, panel=_CASE4_PANEL,
|
||||||
C=8, P=8, sub_w=4,
|
C=8, P=8,
|
||||||
S_kv=S_kv,
|
T_q=1, S_kv=S_kv,
|
||||||
d_head=128, h_q=8, h_kv=1,
|
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():
|
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.
|
``_PANEL_DISPATCH`` with the expected LLaMA-3.1-70B target dims.
|
||||||
|
|
||||||
Headline config:
|
Headline config:
|
||||||
@@ -103,10 +96,9 @@ def test_case4_panel_registered():
|
|||||||
d_head = 128, h_q = 8, h_kv = 1
|
d_head = 128, h_q = 8, h_kv = 1
|
||||||
|
|
||||||
The lrab sub_w=4 / sub_h=2 geometry is baked into the Case 4
|
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
|
wrapper kernel; it is not a panel parameter.
|
||||||
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,
|
_PANEL_DISPATCH,
|
||||||
_PANELS,
|
_PANELS,
|
||||||
)
|
)
|
||||||
@@ -115,8 +107,8 @@ def test_case4_panel_registered():
|
|||||||
)
|
)
|
||||||
assert _CASE4_PANEL in _PANEL_DISPATCH
|
assert _CASE4_PANEL in _PANEL_DISPATCH
|
||||||
kind, params = _PANEL_DISPATCH[_CASE4_PANEL]
|
kind, params = _PANEL_DISPATCH[_CASE4_PANEL]
|
||||||
assert kind == "decode_cube_sp_pe_sp", (
|
assert kind == "decode_long_ctx_cube_sp_pe_sp", (
|
||||||
f"kind={kind!r}, expected 'decode_cube_sp_pe_sp'"
|
f"kind={kind!r}, expected 'decode_long_ctx_cube_sp_pe_sp'"
|
||||||
)
|
)
|
||||||
assert params.get("C") == 8
|
assert params.get("C") == 8
|
||||||
assert params.get("P") == 8
|
assert params.get("P") == 8
|
||||||
@@ -127,26 +119,19 @@ def test_case4_panel_registered():
|
|||||||
assert params.get("h_kv") == 1
|
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():
|
def test_case4_runner_smoke():
|
||||||
"""``_run_decode_panel`` must accept the new ``sub_w``,
|
"""Case 4 runner drives the new kernel to completion at smoke S_kv."""
|
||||||
``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``.
|
|
||||||
"""
|
|
||||||
result = _run_case4_smoke(S_kv=8192)
|
result = _run_case4_smoke(S_kv=8192)
|
||||||
assert result.completion.ok, (
|
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}"
|
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():
|
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):
|
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
|
slide-11 memory waste); for B=1 only one rank does the work; no
|
||||||
inter-rank comm.
|
inter-rank comm.
|
||||||
"""
|
"""
|
||||||
from kernbench.benches.milestone_gqa_decode_4cases import (
|
from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import (
|
||||||
_run_decode_panel_cube_repl_pe_tp,
|
_run_decode_panel_long_ctx_cube_repl_pe_tp,
|
||||||
)
|
)
|
||||||
topo = resolve_topology(str(TOPOLOGY_DEFAULT))
|
topo = resolve_topology(str(TOPOLOGY_DEFAULT))
|
||||||
|
|
||||||
def _bench_fn(ctx):
|
def _bench_fn(ctx):
|
||||||
_run_decode_panel_cube_repl_pe_tp(
|
_run_decode_panel_long_ctx_cube_repl_pe_tp(
|
||||||
ctx, panel=_CASE2_PANEL,
|
ctx, panel=_CASE2_PANEL,
|
||||||
C=8, P=8,
|
C=8, P=8,
|
||||||
T_q=1, S_kv=S_kv,
|
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
|
For B=1 only one rank works (PEs 1-7 idle — slide-11 calls
|
||||||
out this PE-TP waste).
|
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,
|
_PANEL_DISPATCH,
|
||||||
_PANELS,
|
_PANELS,
|
||||||
)
|
)
|
||||||
@@ -216,7 +231,7 @@ def test_case2_panel_registered():
|
|||||||
)
|
)
|
||||||
assert _CASE2_PANEL in _PANEL_DISPATCH
|
assert _CASE2_PANEL in _PANEL_DISPATCH
|
||||||
kind, params = _PANEL_DISPATCH[_CASE2_PANEL]
|
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("C") == 8
|
||||||
assert params.get("P") == 8
|
assert params.get("P") == 8
|
||||||
assert params.get("T_q") == 1
|
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
|
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).
|
(m, ℓ, O); no inter-CUBE comm (every cube ends with full answer).
|
||||||
"""
|
"""
|
||||||
from kernbench.benches.milestone_gqa_decode_4cases import (
|
from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import (
|
||||||
_run_decode_panel_cube_repl_pe_sp,
|
_run_decode_panel_long_ctx_cube_repl_pe_sp,
|
||||||
)
|
)
|
||||||
topo = resolve_topology(str(TOPOLOGY_DEFAULT))
|
topo = resolve_topology(str(TOPOLOGY_DEFAULT))
|
||||||
|
|
||||||
def _bench_fn(ctx):
|
def _bench_fn(ctx):
|
||||||
_run_decode_panel_cube_repl_pe_sp(
|
_run_decode_panel_long_ctx_cube_repl_pe_sp(
|
||||||
ctx, panel=_CASE3_PANEL,
|
ctx, panel=_CASE3_PANEL,
|
||||||
C=8, P=8,
|
C=8, P=8,
|
||||||
T_q=1, S_kv=S_kv,
|
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
|
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.
|
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,
|
_PANEL_DISPATCH,
|
||||||
_PANELS,
|
_PANELS,
|
||||||
)
|
)
|
||||||
@@ -320,7 +335,7 @@ def test_case3_panel_registered():
|
|||||||
)
|
)
|
||||||
assert _CASE3_PANEL in _PANEL_DISPATCH
|
assert _CASE3_PANEL in _PANEL_DISPATCH
|
||||||
kind, params = _PANEL_DISPATCH[_CASE3_PANEL]
|
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("C") == 8
|
||||||
assert params.get("P") == 8
|
assert params.get("P") == 8
|
||||||
assert params.get("T_q") == 1
|
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
|
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.
|
lrab-adapted center-root pattern (root cube 6); no intra-CUBE comm.
|
||||||
"""
|
"""
|
||||||
from kernbench.benches.milestone_gqa_decode_4cases import (
|
from kernbench.benches.milestone_gqa_decode_long_ctx_4cases import (
|
||||||
_run_decode_panel_cube_sp_pe_tp,
|
_run_decode_panel_long_ctx_cube_sp_pe_tp,
|
||||||
)
|
)
|
||||||
topo = resolve_topology(str(TOPOLOGY_DEFAULT))
|
topo = resolve_topology(str(TOPOLOGY_DEFAULT))
|
||||||
|
|
||||||
def _bench_fn(ctx):
|
def _bench_fn(ctx):
|
||||||
_run_decode_panel_cube_sp_pe_tp(
|
_run_decode_panel_long_ctx_cube_sp_pe_tp(
|
||||||
ctx, panel=_CASE1_PANEL,
|
ctx, panel=_CASE1_PANEL,
|
||||||
C=8, P=8,
|
C=8, P=8,
|
||||||
T_q=1, S_kv=S_kv,
|
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).
|
batch. At B=1 only PE 0 of each cube works (PE-TP waste).
|
||||||
Inter-CUBE lrab AR; no intra-CUBE comm.
|
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,
|
_PANEL_DISPATCH,
|
||||||
_PANELS,
|
_PANELS,
|
||||||
)
|
)
|
||||||
@@ -441,7 +456,7 @@ def test_case1_panel_registered():
|
|||||||
)
|
)
|
||||||
assert _CASE1_PANEL in _PANEL_DISPATCH
|
assert _CASE1_PANEL in _PANEL_DISPATCH
|
||||||
kind, params = _PANEL_DISPATCH[_CASE1_PANEL]
|
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("C") == 8
|
||||||
assert params.get("P") == 8
|
assert params.get("P") == 8
|
||||||
assert params.get("T_q") == 1
|
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"Case 1 root must be the lrab center cube 6; "
|
||||||
f"got cubes={sorted(distinct)}"
|
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}"
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user