cc1bbd0ab7
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>
134 lines
6.4 KiB
Markdown
134 lines
6.4 KiB
Markdown
# 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.py`와 `tests/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.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<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의 `256`은
|
||
`burst_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 임베드로 재배선할 것인가?
|