# ADR-0044: GEMM 평가 하니스 — `scripts/gemm_sweep.py` + `tests/gemm/` ## Status Accepted GEMM 평가/특성화 하니스를 문서화한다; 구현과 대조 검증 완료 (상수, tile 크기, figure 집합, script↔test 분할을 교차 확인). D5/D6 caveat은 부정확이 아니라 기록된 한계다. ## 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.py`가 `matmul-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