Skip to content

feat(prep-fused): 디코드 입력 준비를 Triton 발사 하나로 (EXP-7, 기본 off) - #221

Merged
choiceoh merged 1 commit into
mainfrom
feat/glm53-prep-fused
Sep 2, 2026
Merged

feat(prep-fused): 디코드 입력 준비를 Triton 발사 하나로 (EXP-7, 기본 off)#221
choiceoh merged 1 commit into
mainfrom
feat/glm53-prep-fused

Conversation

@choiceoh

@choiceoh choiceoh commented Sep 2, 2026

Copy link
Copy Markdown
Owner

무엇

overlay/modules/glm53_prep_fused: GLM-5.3 디코드 스텝의 호스트 쪽 입력 준비 구간(prepare_inputs + prepare_attn + KV 그룹 7개 빌더, 스텝당 aten ~1,000 호출 · memcpy 45 · 커널 ~100)을 pinned H2D 1회 + Triton 발사 1회 + deep_gemm 스케줄 1회로 접는다. 균일 spec-verify + FULL 그래프 + 요청 패딩 없음일 때만 적용, 나머지는 stock.

9월 1일 트레이스 재분석: 스텝의 12%(8.9 ms/72 ms, 프로파일러 없이 45 ms)가 GPU 유휴이고 그 대부분이 이 구간이다(dflash 가 async scheduling 을 끄므로 호스트 준비가 임계경로). 그래프 안 elementwise 글루 605개 전체(2.7 ms, CUPTI)보다 크다. 천장 = 준비 구간 자체, 스텝의 46%. STEP_KERNEL_MAP 보충 분해 2 참조.

안전장치

  • 기본값 VLLM_GLM53_PREP_FUSED=0; shadow = fused 뒤 stock 을 같은 버퍼에 돌려 전부 diff(stock 이 진실); 1 = arm.
  • 러너 파일을 덮지 않고 메서드 패치. 설치 시 러너/빌더 파일 17개 preimage 고정(glm53:v13-b12x + 마운트된 tail 인덱서), 드리프트 → DISARM 로그.
  • plan 은 그래프 캡처 직후 live 러너에서 생성, 기하가 다르면 그 부팅은 stock(로그).

게이트

  • python3 tests/test_logic.py 41,009 checks OK (test_glm53_prep_fused_contracts 포함).
  • 오프라인(srv4, glm53:sm121-fi618, IMAGE=... bash probes/run_prep_fused_check.sh --trials 60): stock 빌딩블록 vs fused, 프로덕션 기하 무작위 배치 60/60 bit-exact(46 텐서); C=1 스텝당 빌딩블록 2,556 us → 201 us(커널 88 + deep_gemm 스케줄 64).
  • 서빙 미측정: 섀도 부팅(EXTRA_ENV="VLLM_GLM53_PREP_FUSED=shadow", [prep-fused] shadow ... drift=0) → RUNBOOK EXP-7 브래킷(C=1 step/s). 플릿 부팅은 운영자 결정.

부수 발견(미조치, 원장 기록)

kpool tail 원형 슬롯 매핑이 positions 미전달로 잠들어 있음(C>=2 수치 축); 인덱서 fp32 head-gate torch.mm gemmSN 2블록 86 us × 11층(glm53_prefill_fastpath.py:402 소유); 드래프터 커널 합 ~3 ms(CUPTI) 와 원장 D≈0 의 긴장.

🤖 Generated with Claude Code


Note

Medium Risk
Patches the decode-step input and KV metadata path that CUDA graphs consume; wrong buffers would break inference, though eligibility gates, shadow bit-exact checks, and preimage DISARM keep it off by default until validated.

Overview
Adds glm53_prep_fused (EXP-7) to collapse the host-heavy gap between drafter and target CUDA graphs—prepare_inputs, prepare_attn, and seven KV metadata builders—into one pinned H2D copy, one _glm53_prep_fused_kernel Triton launch, and the existing deep_gemm schedule metadata, for uniform spec-verify steps on FULL cudagraph with no request padding.

Integration patches GPUModelRunner / MambaHybridModelState (no runner file overwrites), builds a PrepPlan from live buffers after capture, caches attention metadata per shape, and arms only when VLLM_GLM53_PREP_FUSED is set (shadow runs fused then stock and diffs buffers; default 0 in profiles/glm53.env). 17 runner/builder preimages must match or install DISARMs to stock.

Also ships offline proof (probes/prep_fused_check.py / run_prep_fused_check.sh), test_glm53_prep_fused_contracts, module overlay manifest, and runbook/measurement/kernel-map notes for the ~4–6% step ceiling; serving bracket still pending after clean shadow boot.

Reviewed by Cursor Bugbot for commit 454efe4. Bugbot is set up for automated code reviews on this repo. Configure here.

…P-7)

9월 1일 트레이스(rank 3, 229 스텝)를 스트림 합집합으로 다시 읽으면 스텝의
12%(8.9 ms/72 ms, 프로파일러 없이 4~5 ms)가 GPU 유휴이고, 그 자리가 드래프터
그래프와 타깃 그래프 사이의 eager 입력 준비다: prepare_inputs + prepare_attn +
KV 그룹 7개의 메타데이터 빌더가 스텝마다 aten ~1,000 호출, memcpy 45, 1~3 us
커널 ~100개를 내고 dflash 는 스케줄러가 동기라 그 시간 내내 GPU 가 빈다.

새 모듈 glm53_prep_fused 는 균일 spec-verify 스텝(전 요청 드래프트 7개, FULL
그래프, 요청 패딩 없음)에서 그 구간 전체를 pinned H2D 1회 + Triton 발사 1회 +
deep_gemm 스케줄 1회로 접는다. 러너 파일은 덮지 않고 메서드를 패치하며, 설치
시 러너/빌더 파일 17개의 preimage 를 고정하고(드리프트 -> DISARM), plan 은
캡처 직후 live 러너에서 만들어 커널을 미리 컴파일한다. 메타데이터 dict 는
형상별 캐시(FULL 리플레이는 버퍼만 읽고, dict 는 드래프터에 넘어가 무시된다).

계약은 stock 버퍼와 bit-exact: shadow 모드는 fused 뒤에 stock 을 같은 버퍼에
돌려 전부 diff 하고 stock 이 진실이다. 오프라인 게이트(srv4 새 컨테이너,
probes/run_prep_fused_check.sh): 프로덕션 기하의 무작위 배치 60/60 이 46개
텐서 bit-exact, C=1 스텝당 빌딩블록 2,556 us -> 201 us(커널 88 + deep_gemm
스케줄 64). 서빙 수치는 없다 -- 섀도 부팅 drift=0 뒤 EXP-7 브래킷.

기본값 0. 부수 발견은 원장에: kpool tail 원형 매핑이 positions 미전달로
잠들어 있음(C>=2 수치 축), 인덱서 fp32 head-gate gemmSN 86 us x 11층,
드래프터 커널 합 ~3 ms 와 D≈0 의 긴장.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 2, 2026 08:40
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-02T08:48:43.151477Z 454efe4 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A couple of verified issues (brittle regex in the new logic test and unsafe argument handling in the new probe wrapper script) should be addressed before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds an EXP-7 “prep fused” overlay module for GLM-5.3 that collapses the decode-step host-side input/attention/KV-metadata preparation into a single pinned H2D copy + single Triton kernel launch (+ deep_gemm schedule), guarded by strict eligibility checks and a kill-switch (VLLM_GLM53_PREP_FUSED, default off) with shadow diffing and preimage drift DISARM.

Changes:

  • Introduces overlay/modules/glm53_prep_fused (kernel + runner patching + preimage drift guard) and wires installer into glm53_model_wiring.
  • Adds offline numerics/launch-count probe (probes/prep_fused_check.py + wrapper script) and a logic-level contract test in tests/test_logic.py.
  • Updates runbook/measurement/kernel-map documentation and enables mounting the module in profiles/glm53.env while keeping it disabled by default.
File summaries
File Description
tests/test_logic.py Adds a contract test validating wiring, env knobs, preimage pins, and key kernel invariants.
STEP_KERNEL_MAP.md Documents updated trace decomposition and where prep-fused fits.
RUNBOOK_KERNEL_CAMPAIGN2.md Adds EXP-7 operational ladder (logic → probe → shadow boot → bracket).
profiles/glm53.env Mounts glm53_prep_fused and ships VLLM_GLM53_PREP_FUSED=0 default.
probes/run_prep_fused_check.sh Wrapper to run the offline probe in a fresh container with full overlay mounts.
probes/prep_fused_check.py Offline bit-exact verification + timing comparison between stock blocks and fused kernel.
overlay/modules/glm53_prep_fused/requires Declares dependent overlays the module was read/tested against.
overlay/modules/glm53_prep_fused/README.md Explains trace findings, behavior, guards, and arming procedure.
overlay/modules/glm53_prep_fused/manifest.tsv Binds the new module file into the container at the vLLM model path.
overlay/modules/glm53_prep_fused/glm53_prep_fused.py Implements Triton kernel, plan building, eligibility gating, shadow diffing, and runtime patching.
overlay/modules/glm53_model_wiring/glm5next_model.py Imports and conditionally runs installer (stock-safe when absent / off).
MEASUREMENTS.md Records the trace-driven rationale and offline probe results for EXP-7.
build/glm53/manifest.tsv Adds built artifact entry for glm53_prep_fused.py.
build/glm53/glm5next_model.py Mirrors wiring change in the composed build output.
build/glm53/glm53_prep_fused.py Mirrors the module source in the composed build output.
Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

--mount "type=bind,src=$REPO,dst=/repo,readonly" \
"${envs[@]}" \
"${mounts[@]}" \
"$IMAGE" -lc "python3 /repo/probes/prep_fused_check.py $*" _ "$@"
Comment thread tests/test_logic.py
Comment on lines +6732 to +6733
profile = open(os.path.join(REPO, "profiles", "glm53.env"), encoding="utf-8").read()
modules = re.search(r'^MODULES="([^"]+)"', profile, re.M).group(1).split()

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 454efe4a7b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +122 to +125
try:
from .glm53_prep_fused import install_glm53_prep_fused
except ImportError:
install_glm53_prep_fused = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Distinguish missing module from failed module imports

When the mounted module exists but one of its transitive imports raises ImportError—for example after a vLLM/Triton API change—this handler treats it exactly like an absent optional file, emits no log, and leaves an explicitly enabled VLLM_GLM53_PREP_FUSED boot on the stock path. That can invalidate shadow or armed experiment results despite the stated fail-loud contract; only suppress the error when the missing name is the sibling module itself, and log or propagate other import failures.

Useful? React with 👍 / 👎.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot did not reach a terminal check state within 8 minutes, so this automation is not approving. Human review is needed; a reviewer was assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 454efe4. Configure here.

except Exception:
st.plan_failed = True
logger.exception("[prep-fused] plan build failed -> stock path for this boot")
return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recoverable plan failure permanently disarms

Medium Severity

build_plan raises when indexer_decode_block_table_buffer is still None, and _eligible latches that into plan_failed for the whole boot. That buffer is allocated only later, inside the indexer's first decode build(), which runs after prepare_inputs. Any eligible capture or live step that hits this ordering then skips the post-capture rebuild, so VLLM_GLM53_PREP_FUSED=1 stays on the stock path even after the buffer exists.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 454efe4. Configure here.

@choiceoh
choiceoh merged commit 0b2f179 into main Sep 2, 2026
4 checks passed
choiceoh pushed a commit that referenced this pull request Sep 2, 2026
PR #221 은 09:46Z 머지됐으나 PR #224(e76452f) 가 언급 없이 18개 파일 변경을
전부 되돌려 main 에서 사라졌다. 이 브랜치는 #221·#223 을 main 위에 다시 올리고
(cherry-pick), 10 관점 리뷰 + 검증 14건에서 확인된 결함을 고친다.

CONFIRMED 결함과 수정:
- plan 이 prefill_len.gpu / num_blocks.gpu 를 캐시: 둘은 UvaBackedTensor 라
  copy_to_uva() 마다 라운드로빈 풀의 다른 버퍼로 재바인딩된다(num_blocks 는
  매 스텝 apply_staged_writes 로 회전). 격 스텝마다 한 스텝 stale -> 새 블록으로
  넘어가는 스텝에 gather 가 한 블록 짧아 어텐션이 잘못된 블록을 읽음. 이미지
  코드로 재현. 수정: 소유 객체(BlockTables, UvaBackedTensor)를 plan 에 두고 발사
  시점에 .gpu / 포인터 텐서를 읽는다(wake-up 재생성도 자동 반영).
- 드래프터 KV 그룹(7번째)에 타깃 쪽 FlashInfer 빌더가 붙어 있어 build_plan 이
  모든 실제 부팅에서 실패 -> 모듈 inert. 수정: 드래프터 그룹을 레이어 소속
  (draft_attn_layer_names / draft_kv_cache_group_ids)으로 식별해 gather+slot 만.
- pinned 스테이징 버퍼 1개 재사용이 async scheduling 아래에서 이전 스텝 DMA 와
  경합(GB10 재현). 수정: 이미지의 UvaBufferPool(동시 배치 수 라운드로빈).
- Q 가 2의 거듭제곱이 아니면 tl.arange 컴파일 실패가 첫 적격 스텝에서 엔진을
  죽임. 수정: plan 가드, warmup 실패 DISARM, 발사 예외 시 stock 폴백.
- shadow 가 stock 배치를 반환해 armed 분기를 한 번도 실행 안 함. 수정: fused 뒤
  stock 사슬 전체(prepare_inputs·gather/slot·빌더)를 돌려 diff 하고 깨끗하면
  fused 배치를 흘린다; armed 도 64 fused 스텝마다 self-check, drift 면 DISARM.
- kpool tail 원형 버퍼 휴면을 가정만 함. 수정: plan 생성·검증마다 assert.
- 메타데이터 캐시는 dflash 가 dict 를 무시할 때만 안전. 수정: speculator 타입 게이트.
- 노브 오타가 arm 으로. 수정: 0/off/false/no, shadow, 1 만 인정, 나머지 DISARM.
- 런북·README 의 EXTRA_ENV="VLLM_GLM53_..." 는 프로필 선언 키라 런처가 ABORT
  (EXP-6 도 동일). 수정: caller env 형식 + 문서 lint 테스트.
- 프로브 래퍼가 preimage 검증 없이 전 행을 마운트(fi618 위에 v13 오버레이 5개).
  수정: 런처와 같은 base contract 검증, 프로필 이미지 기본.
- "88/64 us GPU" 는 호스트 발사 시간(실제 커널 ~23 us). 원장·README 정정, 하네스는
  CUDA 그래프 리플레이로 GPU 시간을 잰다.
- warmup 이 돌려주는 컴파일 커널로 직접 발사(Triton 디스패처 ~12 us/스텝 절감,
  검증에서 bit-exact); _load_ptr·PAD_SLOT_ID 재사용; 행 복사 2D 브로드캐스트;
  와이어링 훅은 "미마운트" 와 "모듈 내부 ImportError" 를 구분해 후자를 로그.

오프라인 게이트(srv2, glm53:v13-b12x, 31개 행 preimage 검증): 무작위 배치 60/60
bit-exact(UVA 핸들 회전 포함), C=1 스텝당 stock 2,469 us vs fused 184 us
(호스트+GPU), 실제 GPU 24.4 us(그래프 리플레이). tests/test_logic.py 통과.
서빙 미측정: EXP-7 섀도 부팅 -> 브래킷.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
choiceoh pushed a commit that referenced this pull request Sep 2, 2026
PR #221 은 09:46Z 머지됐으나 PR #224(e76452f) 가 언급 없이 18개 파일 변경을
전부 되돌려 main 에서 사라졌다. 이 브랜치는 #221·#223 을 main 위에 다시 올리고
(cherry-pick), 10 관점 리뷰 + 검증 14건에서 확인된 결함을 고친다.

CONFIRMED 결함과 수정:
- plan 이 prefill_len.gpu / num_blocks.gpu 를 캐시: 둘은 UvaBackedTensor 라
  copy_to_uva() 마다 라운드로빈 풀의 다른 버퍼로 재바인딩된다(num_blocks 는
  매 스텝 apply_staged_writes 로 회전). 격 스텝마다 한 스텝 stale -> 새 블록으로
  넘어가는 스텝에 gather 가 한 블록 짧아 어텐션이 잘못된 블록을 읽음. 이미지
  코드로 재현. 수정: 소유 객체(BlockTables, UvaBackedTensor)를 plan 에 두고 발사
  시점에 .gpu / 포인터 텐서를 읽는다(wake-up 재생성도 자동 반영).
- 드래프터 KV 그룹(7번째)에 타깃 쪽 FlashInfer 빌더가 붙어 있어 build_plan 이
  모든 실제 부팅에서 실패 -> 모듈 inert. 수정: 드래프터 그룹을 레이어 소속
  (draft_attn_layer_names / draft_kv_cache_group_ids)으로 식별해 gather+slot 만.
- pinned 스테이징 버퍼 1개 재사용이 async scheduling 아래에서 이전 스텝 DMA 와
  경합(GB10 재현). 수정: 이미지의 UvaBufferPool(동시 배치 수 라운드로빈).
- Q 가 2의 거듭제곱이 아니면 tl.arange 컴파일 실패가 첫 적격 스텝에서 엔진을
  죽임. 수정: plan 가드, warmup 실패 DISARM, 발사 예외 시 stock 폴백.
- shadow 가 stock 배치를 반환해 armed 분기를 한 번도 실행 안 함. 수정: fused 뒤
  stock 사슬 전체(prepare_inputs·gather/slot·빌더)를 돌려 diff 하고 깨끗하면
  fused 배치를 흘린다; armed 도 64 fused 스텝마다 self-check, drift 면 DISARM.
- kpool tail 원형 버퍼 휴면을 가정만 함. 수정: plan 생성·검증마다 assert.
- 메타데이터 캐시는 dflash 가 dict 를 무시할 때만 안전. 수정: speculator 타입 게이트.
- 노브 오타가 arm 으로. 수정: 0/off/false/no, shadow, 1 만 인정, 나머지 DISARM.
- 런북·README 의 EXTRA_ENV="VLLM_GLM53_..." 는 프로필 선언 키라 런처가 ABORT
  (EXP-6 도 동일). 수정: caller env 형식 + 문서 lint 테스트.
- 프로브 래퍼가 preimage 검증 없이 전 행을 마운트(fi618 위에 v13 오버레이 5개).
  수정: 런처와 같은 base contract 검증, 프로필 이미지 기본.
- "88/64 us GPU" 는 호스트 발사 시간(실제 커널 ~23 us). 원장·README 정정, 하네스는
  CUDA 그래프 리플레이로 GPU 시간을 잰다.
- warmup 이 돌려주는 컴파일 커널로 직접 발사(Triton 디스패처 ~12 us/스텝 절감,
  검증에서 bit-exact); _load_ptr·PAD_SLOT_ID 재사용; 행 복사 2D 브로드캐스트;
  와이어링 훅은 "미마운트" 와 "모듈 내부 ImportError" 를 구분해 후자를 로그.

오프라인 게이트(srv2, glm53:v13-b12x, 31개 행 preimage 검증): 무작위 배치 60/60
bit-exact(UVA 핸들 회전 포함), C=1 스텝당 stock 2,469 us vs fused 184 us
(호스트+GPU), 실제 GPU 24.4 us(그래프 리플레이). tests/test_logic.py 통과.
서빙 미측정: EXP-7 섀도 부팅 -> 브래킷.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants