fix(glm53): split-K head gate 가 block_k 로 K 를 못 나누면 조용한 오답 대신 실패 - #233
Conversation
부분합 커널은 w 행을 [0, split*block_k) 에 걸쳐 마스크 없이 읽는다 — block_k 가 K 를 나누지 않으면 꼬리 행이 조용히 빠진 채 곱이 나온다 (v1 의 교훈: 조용한 형상 미스는 죽은 노브). head_gate_splitk 진입에서 큰 소리로 죽인다. 계약 검사 1건 추가 (2664 -> 2665).
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
🟡 Changes recommended
The new guard still allows block_k<=0 to raise ZeroDivisionError / produce invalid launch shapes instead of a clear ValueError, so input validation needs to be completed to ensure consistent fail-fast behavior.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR hardens the glm53 split-K head-gate fast path by adding a fail-fast guard when block_k does not tile K, preventing silently wrong matmul results due to unmasked weight-row reads in the partial kernel.
Changes:
- Add
ValueErrorguard inhead_gate_splitkwhenK % block_k != 0(kept in sync across overlay + build twin). - Add a contract test asserting the kernel source includes the new loud-failure guard.
File summaries
| File | Description |
|---|---|
overlay/modules/glm53_indexer_gate_splitk/glm53_indexer_gate.py |
Adds a tiling validation guard for block_k in head_gate_splitk. |
build/glm53/glm53_indexer_gate.py |
Mirrors the same tiling guard in the build twin to keep artifacts in sync. |
tests/test_logic.py |
Adds a string-contract assertion that the guard exists in the kernel source. |
Review details
- Files reviewed: 3/3 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.
| if K % block_k: | ||
| # The partial kernel reads w rows unmasked over [0, split*block_k): a K | ||
| # the block does not tile would drop the tail and answer quietly wrong. | ||
| raise ValueError( | ||
| f"head_gate_splitk: K={K} is not a multiple of block_k={block_k}") |
| if K % block_k: | ||
| # The partial kernel reads w rows unmasked over [0, split*block_k): a K | ||
| # the block does not tile would drop the tail and answer quietly wrong. | ||
| raise ValueError( | ||
| f"head_gate_splitk: K={K} is not a multiple of block_k={block_k}") |


무엇
#231 리뷰의 잔여 결함 1건.
head_gate_splitk(x, w, block_k=…)의 노출된block_k인자가 K 를 나누지 않으면, 부분합 커널이 w 행을[0, split*block_k)에 걸쳐 마스크 없이 읽는 구조라 꼬리 행이 조용히 빠진 채 곱이 나왔다. 현재 호출부는 전부 디폴트(128 — K=4096 을 나눔)라 오늘 위험은 없지만, v1 의 교훈(조용한 형상 미스 = 죽은 노브) 그대로의 지뢰라 진입에서 큰 소리로 죽인다.변경 (3파일, +12)
head_gate_splitk:K % block_k시ValueError(overlay + build 쌍둥이 동기화)tests/test_logic.py: 계약 검사 1건 추가 — 커널에 가드가 있는 문자열 계약게이트
tests/test_logic.py2665 검사 전부 OK (기존 2664 + 신규 1)Note
Low Risk
Defensive validation on an optional split-K fast path; default callers are unaffected and invalid configurations fail fast instead of returning wrong numerics.
Overview
head_gate_splitknow raisesValueErrorwhen inner dimensionKis not divisible byblock_k, instead of producing silently wrong matmul results. The split-K partial Triton kernel loads weight rows over[0, split·block_k)without masking the tail; a mismatchedblock_kwould drop trailingKrows from the product.The guard is applied in both
build/glm53/glm53_indexer_gate.pyand the overlay twin so they stay in sync.tests/test_logic.pyadds a string contract check that the kernel source includesK % block_kandraise ValueError.Production routing via
head_gatestill uses the defaultblock_k=128, which tilesK=4096; behavior on the supported decode path is unchanged.Reviewed by Cursor Bugbot for commit c52ae93. Bugbot is set up for automated code reviews on this repo. Configure here.