Files
kernbench2/docs/adr-ko/ADR-0044-eval-gemm-harness.md
mukesh cc1bbd0ab7 eval: fold GEMM/allreduce harnesses into self-contained milestone benches
Move the GEMM + allreduce sweep/render logic out of scripts/ and tests/
into two self-contained eval benches so a user can regenerate every
result + figure with one command:

  kernbench run --bench milestone-1h-gemm   (MILESTONE_FAST=1 reuses JSON)
  kernbench run --bench milestone-1h-ccl

- benches/milestone_1h_{gemm,ccl}.py: single home for each domain; the
  run(torch) entry drives the sweeps and writes figures into
  benches/1H_milestone_output/{gemm,ccl}/ (gitignored), then submits a
  sentinel tensor to satisfy the run_bench contract.
- tests/gemm + tests/sccl helpers and scripts/gemm_sweep.py become thin
  re-export/wrapper shims over the benches (single source preserved); the
  pytest-only param builders + _run_distributed wrapper stay in the shim.
- eval-bench pattern: a bench may drive many configs + build its own
  per-config engines (extends ADR-0045 D5; reverses ADR-0044 D1/D2).

ADR-0054 (EN+KO) records the design; ADR-0043/0044/0045 + CLAUDE.md CLI
Semantics amended; ADR INDEX regenerated. Verified: milestone benches run
clean (ok=True, all artifacts), full suite 67 passed, lang-pairs OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 15:19:52 -07:00

6.4 KiB
Raw Permalink Blame History

ADR-0044: GEMM 평가 하니스 — scripts/gemm_sweep.py + tests/gemm/

Status

Accepted

GEMM 평가/특성화 하니스를 문서화한다; 구현과 대조 검증 완료 (상수, tile 크기, figure 집합, script↔test 분할을 교차 확인). D5/D6 caveat은 부정확이 아니라 기록된 한계다.

ADR-0054로 개정됨: sweep + renderer가 milestone-1h-gemm bench(단일 home)로 이동했다; scripts/gemm_sweep.pytests/gemm/는 이제 거기서 re-export한다. D1/D2의 "데이터 생성은 수동 script / 무거운 작업은 opt-in"은 평가-bench 패턴으로 대체된다(하나의 bench가 전부 재생성; MILESTONE_FAST=1은 committed JSON 재사용).

Context

ADR-0014(PE pipeline)와 ADR-0042(tile-plan generator)는 GEMM 구현을 정의하고, ADR-0033은 latency 모델을 정의한다. 그러나 어느 것도 GEMM 성능을 어떻게 스윕하고 특성화하는가 — 타이밍 데이터를 만드는 shape/variant 스윕과 이를 해석하는 figure — 는 기술하지 않는다. 본 ADR이 그 하니스를 고정한다.

allreduce 하니스(ADR-0043)와 달리 GEMM 스윕은 무겁다(24 sim 실행: 8 shape × 3 operand-staging variant; 512 shape 하나가 2048 tile). 이 무게가 아래 분할을 결정한다.

Decision

D1. 두 계층 분할 — 무거운 데이터 생성(script) vs. 빠른 figure(test)

  • 데이터 생성은 수동 script로 유지: scripts/gemm_sweep.pymatmul-composite(ADR-0042 plan)를 CLI와 동일한 run_bench 경로로 shape × variant에 걸쳐 실행하고, result.engine.op_log를 수확하여 docs/diagrams/gemm_sweep.json(stage별/engine별 wall-clock + occupancy
    • record count + pe/composite window)을 쓴다.
  • figure 렌더링은 test 생성: tests/gemm/이 committed gemm_sweep.json을 읽어 matplotlib PNG를 docs/diagrams/gemm_plots/에 렌더링한다. 이 테스트는 빠르고 기본 실행된다.

근거: 슬라이드덱 규모의 sim 스윕은 매 pytest 실행에 속하지 않지만, figure(저렴·결정적)는 자유롭게 재생성되고 CI로 가드되어야 한다. 이는 CLAUDE.md의 script-vs-test 분할(무거운/수동 생성은 script; 빠른 assertion은 test)을 반영한다.

D2. Slow regenerator 테스트가 script를 감싼다

tests/gemm/test_gemm_sweep.py@pytest.mark.slow로 표시된다(기본 addopts: -m "not slow"에서 제외). 이는 scripts/gemm_sweep.py를 subprocess로 호출하여 gemm_sweep.json을 on-demand로 재생성한다 (pytest -m slow tests/gemm/test_gemm_sweep.py). 스윕 로직은 단일 home(script)을 가지며 테스트는 이를 감싸기만 하므로 sim 구동 코드의 중복이 없다.

D3. Figure 집합 (3개 차트, load_ref variant)

테스트 PNG 내용
test_plot_gemm_stage_breakdown.py gemm_stage_breakdown.png stage별 engine wall-clock (DMA in / Fetch / GEMM / DMA out)
test_plot_gemm_mac_utilization.py gemm_mac_utilization_measured.png GEMM util % + useful eff %
test_plot_gemm_mac_utilization.py gemm_mac_utilization_theoretical_vs_measured.png theoretical vs 시뮬레이터-measured util/eff

tests/gemm/_gemm_plot_helpers.py가 공유 renderer를 보유한다(시리즈 로직은 scripts/build_overview_slides.py의 GEMM _render_* 함수를 미러링하며, 그쪽은 여전히 PPTX에 네이티브로 그린다). 수집되지 않음(test_ 접두사 없음). 각 test_plot_*gemm_sweep.json이 없으면 skip한다.

D4. Tile 크기는 데이터 기반; under-tile shape는 표시

Tile 크기는 gemm_sweep.json(tile_sizes)에서 읽으며, 이는 스윕이 PeSchedulerComponent.TILE_M/K/N = 32/64/32 — 권위 소스 — 에서 기록한 값이다. M<TILE_M K<TILE_K N<TILE_N인 shape는 차트에 ("under-tile") 표시된다. 512³ shape는 figure에서 제외된다 (EXCLUDED_SHAPES).

D5. Theoretical 모델 — 상속된 상수, 아직 ADR-미검증

"theoretical" 곡선은 scripts/build_overview_slides.py에서 그대로 복사한 상수로 해석적 ideal-pipeline 모델을 사용한다:

HBM_GBS = 256.0   # GB/s        T_STAGE = 16.0 ns
D_STAGES = 3                    BPE = 2

이 값들은 아직 ADR과 대조 소싱되지 않았다. 특히 ADR-0033의 256burst_bytes(256 B)로 이 256 GB/s다른 양이며, ADR-0033은 대역폭을 pc_bw_gbs = hbm_to_router_bw_gbs / num_pcs로 도출한다. T_STAGE/stage 수도 여기서 ADR-0014로 추적되지 않았다. 따라서 모델은 기존 deck script와 일관할 뿐 ADR과 검증되지 않았고, 상수가 중복된다 (deck + helper). 이를 조정(topology/ADR-0033/0014에서 소싱, 중복 제거)하는 것은 보류 — Open questions 참조.

D6. 알려진 네이밍 caveat — _measured 차트

gemm_mac_utilization_measured.png는 현재 theoretical ideal-pipeline 수치를 그린다(footnote가 그렇게 명시). 파일명만 "measured"라고 한다. 이는 그 내용을 시뮬레이터-measured 시리즈로 재지정할지 또는 제목을 바꿀지 결정을 보류 중인 알려진 misnomer다.

Consequences

Positive

  • GEMM figure가 allreduce처럼 test 생성·CI 가드된다.
  • 무거운 스윕은 opt-in으로 유지되어 기본 테스트 실행이 빠르다.
  • 스윕 로직의 단일 소스(script)를 slow 테스트가 재사용.

Negative / limitations

  • theoretical 모델 상수(D5)는 미검증·중복이다.
  • _measured figure는 misnomer(D6).
  • build_overview_slides.py는 여전히 이 PNG를 임베드하지 않고 gemm_sweep.json에서 GEMM 막대를 네이티브로 그린다 — test 아티팩트를 소비하도록 deck를 재배선하는 작업은 미완.

Dependencies

  • ADR-0013: verification strategy.
  • ADR-0014 / ADR-0042: PE pipeline + tile-plan generator — 스윕이 측정하는 GEMM 구현; D4의 stage record count는 ADR-0042 D2/D3에서 온다.
  • ADR-0033: latency 모델 — D5 상수가 (아직은 아니지만) 추적되어야 할 소스.
  • ADR-0043: 형제 격인 allreduce 평가 하니스.

Open questions

  • D5 상수를 topology.yaml / ADR-0033 / ADR-0014와 대조 조정하고 중복 제거할 것인가(모델 파라미터의 단일 소스)?
  • D6 _measured 네이밍 해결(내용 재지정 vs. 제목 변경)?
  • build_overview_slides.py를 네이티브 막대 그리기 대신 gemm_plots/ PNG 임베드로 재배선할 것인가?