"""Phase 1a smoke test for the Case 4 d_head-TP decode kernel. Runs `gqa_attention_decode_long_ctx_cube_sp_pe_tp_dhead_kernel` at small S_kv (2K) to verify: 1. it imports cleanly, 2. it runs without error under the same harness as Case 6, 3. captures op_log_summary (gemm/ipcq/dma counts), 4. compares vs analytical predictions and vs Case 6 (same memory tier). Usage: python scripts/verify_case4_dhead_tp.py """ from __future__ import annotations import os import sys from pathlib import Path from kernbench.benches.gqa_helpers.long_ctx._gqa_attention_decode_long_ctx_cube_sp_pe_sp import ( gqa_attention_decode_long_ctx_cube_sp_pe_sp_kernel as _case6_kernel, ) from kernbench.benches.gqa_helpers.long_ctx._gqa_attention_decode_long_ctx_cube_sp_pe_tp_dhead import ( gqa_attention_decode_long_ctx_cube_sp_pe_tp_dhead_kernel as _case4_kernel, ) from kernbench.benches.gqa_helpers.long_ctx._gqa_attention_decode_long_ctx_cube_tp_dhead_pe_sp import ( gqa_attention_decode_long_ctx_cube_tp_dhead_pe_sp_kernel as _case5_kernel, ) from kernbench.benches.gqa_helpers.shared._gqa_panel_helpers import ( _ccl_cfg, _summarize_op_log, ) from kernbench.ccl.sfr_config import configure_sfr_intercube_multisip from kernbench.policy.placement.dp import DPPolicy from kernbench.runtime_api.bench_runner import run_bench from kernbench.runtime_api.types import resolve_device from kernbench.sim_engine.engine import GraphEngine from kernbench.topology.builder import resolve_topology # Small smoke-test params (S_kv=2K is enough to exercise tile-loop + AR). _PARAMS = dict(C=8, P=8, T_q=1, S_kv=2_048, d_head=128, h_q=8, h_kv=1) def _bench_fn_case4(ctx): p = _PARAMS configure_sfr_intercube_multisip(ctx.engine, ctx.spec, _ccl_cfg()) dp_full = DPPolicy(cube="replicate", pe="column_wise", num_cubes=p["C"], num_pes=p["P"]) dp_kv = DPPolicy(cube="row_wise", pe="column_wise", num_cubes=p["C"], num_pes=p["P"]) q = ctx.zeros((p["T_q"], p["h_q"] * p["d_head"]), dtype="f16", dp=dp_full, name="q_c4") k = ctx.zeros((p["S_kv"], p["h_kv"] * p["d_head"]), dtype="f16", dp=dp_kv, name="k_c4") v = ctx.zeros((p["S_kv"], p["h_kv"] * p["d_head"]), dtype="f16", dp=dp_kv, name="v_c4") o = ctx.empty((p["T_q"], p["h_q"] * p["d_head"]), dtype="f16", dp=dp_full, name="o_c4") ctx.launch("case4_dhead_tp", _case4_kernel, q, k, v, o, p["T_q"], p["S_kv"], p["h_q"], p["h_kv"], p["d_head"], p["C"], p["P"], _auto_dim_remap=False) def _bench_fn_case5(ctx): p = _PARAMS configure_sfr_intercube_multisip(ctx.engine, ctx.spec, _ccl_cfg()) dp_q = DPPolicy(cube="column_wise", pe="replicate", num_cubes=p["C"], num_pes=p["P"]) dp_kv = DPPolicy(cube="column_wise", pe="row_wise", num_cubes=p["C"], num_pes=p["P"]) q = ctx.zeros((p["T_q"], p["h_q"] * p["d_head"]), dtype="f16", dp=dp_q, name="q_c5") k = ctx.zeros((p["S_kv"], p["h_kv"] * p["d_head"]), dtype="f16", dp=dp_kv, name="k_c5") v = ctx.zeros((p["S_kv"], p["h_kv"] * p["d_head"]), dtype="f16", dp=dp_kv, name="v_c5") o = ctx.empty((p["T_q"], p["h_q"] * p["d_head"]), dtype="f16", dp=dp_q, name="o_c5") ctx.launch("case5_dhead_tp_inter", _case5_kernel, q, k, v, o, p["T_q"], p["S_kv"], p["h_q"], p["h_kv"], p["d_head"], p["C"], p["P"], _auto_dim_remap=False) def _bench_fn_case6(ctx): p = _PARAMS configure_sfr_intercube_multisip(ctx.engine, ctx.spec, _ccl_cfg()) dp_full = DPPolicy(cube="replicate", pe="replicate", num_cubes=p["C"], num_pes=p["P"]) dp_kv = DPPolicy(cube="row_wise", pe="row_wise", num_cubes=p["C"], num_pes=p["P"]) q = ctx.zeros((p["T_q"], p["h_q"] * p["d_head"]), dtype="f16", dp=dp_full, name="q_c6") k = ctx.zeros((p["S_kv"], p["h_kv"] * p["d_head"]), dtype="f16", dp=dp_kv, name="k_c6") v = ctx.zeros((p["S_kv"], p["h_kv"] * p["d_head"]), dtype="f16", dp=dp_kv, name="v_c6") o = ctx.empty((p["T_q"], p["h_q"] * p["d_head"]), dtype="f16", dp=dp_full, name="o_c6") ctx.launch("case6_sp_sp", _case6_kernel, q, k, v, o, p["T_q"], p["S_kv"], p["h_q"], p["h_kv"], p["d_head"], p["C"], p["P"], _auto_dim_remap=False) def main() -> int: topology = os.environ.get("GQA_1H_TOPOLOGY", "topology.yaml") topo = resolve_topology(topology) print(f"Smoke params: {_PARAMS}") print() for label, bench_fn in ( ("Case 4 (Cube-SP × PE-TP d_head)", _bench_fn_case4), ("Case 5 (Cube-TP d_head × PE-SP)", _bench_fn_case5), ("Case 6 (Cube-SP × PE-SP S_kv)", _bench_fn_case6), ): try: res = run_bench( topology=topo, bench_fn=bench_fn, device=resolve_device(None), engine_factory=lambda t, d: GraphEngine( getattr(t, "topology_obj", t), enable_data=True, ), ) except Exception as e: print(f" {label:<42} FAIL: {type(e).__name__}: {e}") continue if not res.completion.ok: print(f" {label:<42} ENGINE FAIL: {res.completion}") continue s = _summarize_op_log(res.engine.op_log) lat = (res.engine.op_log[-1].t_end if res.engine.op_log else 0.0) print(f" {label:<42} " f"gemm={s['gemm_count']:>4} " f"ipcq={s['ipcq_copy_count']:>4} " f"dma_r={s['dma_read_count']:>4} " f"dma_w={s['dma_write_count']:>3} " f"latency={lat:.1f} ns " f"(n_ops={len(res.engine.op_log)})") return 0 if __name__ == "__main__": sys.exit(main())