gqa(adr-0065): P2 — softmax_merge recipe + TLContext prologue lowering
New triton_emu/tl_recipes.py: RecipeDescriptor/EngineOp/PrimaryOutSpec + RECIPE_DESCRIPTORS['softmax_merge'] (8-step engine_seq). PE_SCHEDULER does not import it (ADR-0065 D5 boundary). TLContext.composite(): add prologue=[...] + out=TensorHandle kwargs, a optional. _expand_prologue lowers a recipe into flat MATH OpSpecs (scope=KERNEL), allocates TCM scratch, derives the primary-out slot 'P' and auto-binds it into the head GEMM a (D6.6 conflict check); rw_handles=(m,l,O). decode-opt2 #2 lowers to 10 ops [rmax,max_elem,exp_diff,exp_diff,rsum,fma,mul_bcast,copy,gemm,add]. D6.7 (MATH operand TCM-only) scoped to prologue recipe ops only — the head op (gemm or math) keeps existing DMA-staged-from-HBM behavior. D6.1 (GEMM count <=1) on the whole composite. Host-side lowering only; PE_SCHEDULER position-scan is P3. Also commit the ADR-0064 Rev2 promotion content that the prior commit's git mv dropped: Status Proposed->Accepted + D7 amended to hard-cap ValueError (no segmentation), EN+KO. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
## Status
|
||||
|
||||
Proposed (Revision 2)
|
||||
Accepted (Revision 2)
|
||||
|
||||
> **ADR-0060** (AHBM GQA Fused Attention) 와 **ADR-0065** (flat-ops
|
||||
> composite + 첫 stateful recipe) 의 보조 ADR. 그 hybrid 의 핵심 — "GEMM 은
|
||||
@@ -219,20 +219,14 @@ issue cost 를 0 → non-zero 로 바꾸면 **모든** bench 의 latency 변화.
|
||||
이 ADR land 시 골든 latency **한 번** 재생성 — ADR-0062 D3 lazy-load 와
|
||||
같은 패턴. 재생성 후 동일 calibration 이 ADR-0065 opt2 측정에 적용.
|
||||
|
||||
### D7. Composite 크기 cap (deterministic segmentation)
|
||||
### D7. Composite 크기 cap (하드 제한 — validation error)
|
||||
|
||||
각 `CompositeCmd` 의 `logical_bytes` 가 **`MAX_COMPOSITE_LOGICAL_BYTES`**
|
||||
(default **1024 bytes**, D4 로 override) 로 제한. 초과하는 cmd 는
|
||||
*emitter* (host-side TLContext, ADR-0065 D5) 가 N 개 연속 `CompositeCmd`
|
||||
로 deterministic 하게 **segment** — 각 ≤ cap.
|
||||
|
||||
- 각 segment 가 자기 `completion: CompletionHandle` 보유.
|
||||
- 각 segment 가 자기 dispatch cost — `total = sum(FIXED + bytes_i × R) =
|
||||
N × FIXED + total_bytes × R`. FIXED 항이 segment 당.
|
||||
- segment 가 `rw_handles` 공유 — **strict FIFO** (ADR-0065 D6.3) 가
|
||||
write-after-write 순서 자동 보존.
|
||||
- segmentation 알고리즘 결정적 (emit 순서로 op 인덱스 greedy); host
|
||||
emitter 의 일부, PE_SCHEDULER 가 아님.
|
||||
각 `CompositeCmd` 의 `logical_bytes` 가 **`max_composite_logical_bytes`**
|
||||
(default **1024 bytes**, D4 로 override) 로 제한. `logical_bytes` 가 cap
|
||||
을 초과하는 composite 는 host-side TLContext 가 emit 시점에 `ValueError`
|
||||
로 **거부** — **자동 segmentation 없음**. 커널 작성자가 각 `CompositeCmd`
|
||||
가 descriptor capacity 에 맞도록 recipe 를 재구성(예: 여러 개의 더 작은
|
||||
composite 로 명시적으로 분할)해야 함.
|
||||
|
||||
**cap 이 필요한 이유.** 실제 하드웨어는 descriptor queue entry 크기,
|
||||
scheduler parser buffer, command SRAM, firmware 입력의 하드 제한 보유.
|
||||
@@ -248,18 +242,15 @@ composite (가장 큰 것이 decode opt2 의 `#2` ~322 bytes) 보다 훨씬 위
|
||||
이 default 의 역할은 cap 을 *원칙으로 존재시키는 것*, 특정 HW 에 맞추는
|
||||
것이 아님.
|
||||
|
||||
**segment 간 순서 — strict FIFO 가 주체, `rw_handles` 아님.** segment 들은
|
||||
emit 순서로 PE_CPU → PE_SCHEDULER 큐에 들어감. strict-FIFO dispatch
|
||||
(ADR-0065 D6.3) 가 *순서의 주체* — segment 가 큐 진입 순서로 실행. 각
|
||||
segment 의 `rw_handles` block 은 cross-composite 해저드 추적기의 **의존성
|
||||
메타데이터** — 그 자체로 inter-segment 순서를 보장하지 **않음**. 미래
|
||||
scheduler 가 FIFO 를 완화 (예: RW-aware reorder, ADR-0065 A4) 한다면
|
||||
segmenter 는 (a) segment 를 단일 CompositeCmd 로 merge 또는
|
||||
(b) 명시적 completion-handle 의존 체인 도입 필요. Phase 1 에선 무관 —
|
||||
strict FIFO 가 유효.
|
||||
**자동 segmentation 대신 하드 에러를 택한 근거.** 초과 composite 를 자동
|
||||
분할(원래 Revision 2 제안)하는 것은 inter-segment 순서, `rw_handles`
|
||||
공유, completion 체이닝 등 emitter 복잡도를 추가하면서, 실질적으로는
|
||||
하드웨어가 허용하는 것보다 큰 descriptor 를 요청한 커널을 덮어주는
|
||||
것일 뿐. 명시적 에러로 표면화하면 emitter 가 단순해지고, HW 제약이
|
||||
작업을 어떻게 분할할지 가장 잘 아는 커널 작성자에게 보임.
|
||||
|
||||
Decode opt2 의 `#2` composite (10 ops, ~322 bytes) 는 1024 cap 안에
|
||||
편안히 — GQA workload 에 segmentation 없음.
|
||||
편안히 — GQA workload 에 에러 없음.
|
||||
|
||||
## Alternatives
|
||||
|
||||
@@ -350,10 +341,8 @@ calibration 이 바뀌거나 OpSpec/CompositeCmd 필드가 추가되어도 유
|
||||
7. **경로 parity.** greenlet 과 replay 가 동일 커널에 대해 동일
|
||||
dispatch-cycle 회계.
|
||||
8. **Composite 크기 cap (D7).** `logical_bytes >
|
||||
MAX_COMPOSITE_LOGICAL_BYTES` 가 될 recipe 가 N 개 연속 `CompositeCmd`
|
||||
로 segment; `sum(segment.logical_bytes) == original logical_bytes`;
|
||||
총 dispatch = segment dispatch 의 합 (FIXED 가 segment 당 지불);
|
||||
inter-segment 순서 strict FIFO 로 보존 (`rw_handles` 단독 아님).
|
||||
max_composite_logical_bytes` 가 될 composite 는 emit 시점에 `ValueError`
|
||||
(segmentation 없음). cap 이내 composite 는 정상 emit.
|
||||
9. **민감도 (정성적).** `R ∈ {0.25, 0.0625, 0.03125}` cycles/byte 에서
|
||||
3 지점 모두 `opt3 > opt2`. 방향 (R 감소 시 ratio 단조 증가) 도 단언,
|
||||
단 절대 ratio 값은 *불필요*.
|
||||
@@ -366,11 +355,11 @@ ADR-0064 Revision 2 는 단일 PR 로 land:
|
||||
- `pe_cpu.py` dispatch 경로의 공식 적용
|
||||
- PE_CPU init 의 `pe_cost_model:` override read (cycle-domain knob +
|
||||
`max_composite_logical_bytes`)
|
||||
- **composite 크기 cap (D7)** — TLContext-side segmentation 로직,
|
||||
`MAX_COMPOSITE_LOGICAL_BYTES` default 1024; 기존 bench 에 필요 없음
|
||||
(현재 최대 composite 가 200 bytes 훨씬 아래), 하지만 ADR-0065 의 10-op
|
||||
decode-opt2 composite (~310 bytes) + 더 큰 recipe 가 나타날 때를 위해
|
||||
메커니즘 land.
|
||||
- **composite 크기 cap (D7)** — TLContext-side 하드 cap,
|
||||
`max_composite_logical_bytes` default 1024: cap 초과 composite 는 emit
|
||||
시점에 `ValueError` (자동 segmentation 없음). 기존 bench 는 트리거
|
||||
안 됨 (현재 최대 composite 가 ~322 bytes), 하지만 recipe 가 커질 때
|
||||
descriptor-capacity 제한이 강제되도록 체크 land.
|
||||
- 일회성 골든 재생성
|
||||
|
||||
land 후 ADR-0065 가 위에 쌓임 — 기존 bench 추가 골든 churn 없음
|
||||
|
||||
Reference in New Issue
Block a user