perf(modules): b12x MoE wrapper 를 geometry 별로 공유 — 층마다 541 MiB 를 중복으로 들고 있었다 - #80
Conversation
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_a92f1f9e-805f-4873-be86-685517ec316d) |
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. |
… 들고 있었다 층마다 B12xMoEWrapper 를 새로 만든다. 각 wrapper 는 geometry 로 크기가 정해지는 graph-stable 스크래치를 든다. 이 배치에서 실측했다(288 experts, top_k 8, 4096/2048, max_num_tokens 2048): wrapper 1 개 : allocated +541.1 MiB MoE 층 43 개 : 22.72 GiB (랭크마다) 공유 시 절감 : 22.19 GiB GLM-5.3-Flash 의 43 개 MoE 층은 geometry 가 전부 같다. 즉 GMU 예산의 4분의 1이 중복 버퍼였다. 엔진이 보고한 수치와도 맞는다: 가중치 45.8 GiB + wrapper 22.7 GiB 를 GMU 0.73 의 87.4 GiB 예산에서 빼면 KV 가 ~16 GiB 남고, 엔진 로그가 16.52 GiB 였다. 오늘 하루 메모리로 겪은 것들 — 워커 OOM, GMU 를 올려도 내려도 죽던 것, KV 가 16 GiB 를 못 넘던 것 — 의 상당 부분이 여기서 나온다. 공유가 안전한 이유: MoE 층은 같은 스트림에서 차례로 돈다. wrapper 는 호출마다 자기 버퍼에 쓰고 호출 밖으로 남기는 것이 없다. 값은 약참조라 마지막 층이 놓으면 같이 사라진다. vllm-project/vllm#48698 과 같은 발상을 이 이미지가 싣는 파일에 맞춰 쓴 것이다. (#53081 은 wrapper 대신 workspace 를 공유하지만 FlashInfer 의 shared_static_workspace(flashinfer-ai/flashinfer#4603)가 필요하고, 이 빌드 0.6.18.dev20260819 에는 없다.) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
f117dea to
772e0ba
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_111d8cd4-16cb-4cc8-94b2-cc94072cf13d) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f117dead1e
ℹ️ 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".
| swiglu_limit=key.swiglu_limit, | ||
| ) | ||
| _B12X_WRAPPERS[key] = w | ||
| logger.info_once( |
There was a problem hiding this comment.
Define the logger before creating the shared wrapper
With the glm53 profile enabled, the first MoE apply() always takes this cache-miss path; after allocating and caching the wrapper, it calls logger.info_once, but this module never defines or imports logger. That raises NameError before _shared_wrapper() can return, so the first model execution fails instead of realizing the memory-saving shared wrapper.
Useful? React with 👍 / 👎.
| # Two of their three files are byte-identical to what v13 ships and the third | ||
| # would drop thirty lines v13 has. They remain in overlay/modules for a v9 image. | ||
| MODULES="glm53_tail_slot_persistent glm53_kpool_tail_select glm53_drop_audit moe_gate_sm121 glm53_model_wiring tp_oneshot_ar glm53_oneshot_wiring fp8_lm_head glm53_dflash2_fp8_head glm53_dflash_loader_fp8" | ||
| MODULES="b12x_shared_workspace glm53_tail_slot_persistent glm53_kpool_tail_select glm53_drop_audit moe_gate_sm121 glm53_model_wiring tp_oneshot_ar glm53_oneshot_wiring fp8_lm_head glm53_dflash2_fp8_head glm53_dflash_loader_fp8" |
There was a problem hiding this comment.
Regenerate the committed glm53 manifest
When a consumer uses the committed build/glm53 output without rerunning the composer, this newly enabled module is not applied: build/glm53/manifest.tsv still contains only the previous 12 rows and has no entry for flashinfer_b12x_moe.py. Deployment and launcher mounting enumerate files exclusively from that manifest, so the newly committed build file is ignored; regenerate the build manifest so the versioned composed output matches this MODULES list.
Useful? React with 👍 / 👎.
#80 이 logger.info_once 로 공유 발동을 남기는데, 이 파일의 원본에는 logger 가 아예 없다. py_compile 은 통과하고 부팅이 죽었다: RuntimeError: Worker failed with error 'name 'logger' is not defined' 로그 자체는 지우지 않는다 — 측정 스크립트가 그 줄로 공유가 실제로 걸렸는지 판정하고, 그게 없으면 직전 측정처럼 "아무것도 안 바뀐 상태"를 결론으로 삼게 된다. 컴파일이 아니라 컨테이너에서 실제 임포트로 확인했다: _shared_wrapper·logger· _B12X_WRAPPERS 전부 존재. py_compile 이 못 잡는 자리였다. Co-authored-by: choiceoh <choiceoh@srv4.tail7fec17.ts.net> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>


Summary
층마다
B12xMoEWrapper를 새로 만듭니다. 각 wrapper 는 geometry 로 크기가 정해지는 graph-stable 스크래치를 듭니다. 이 배치에서 실측:GLM-5.3-Flash 의 43 개 MoE 층은 geometry 가 전부 같습니다 — 즉 GMU 예산의 4분의 1이 중복 버퍼였습니다.
엔진이 보고한 수치와 맞습니다
오늘 메모리로 겪은 것들 — 워커 OOM, GMU 를 올려도 내려도 죽던 것, KV 가 16 GiB 를 못 넘던 것 — 의 상당 부분이 여기서 나옵니다.
안전성
MoE 층은 같은 스트림에서 차례로 돕니다. wrapper 는 호출마다 자기 버퍼에 쓰고 호출 밖으로 남기는 것이 없습니다. 값은 약참조라 마지막 층이 놓으면 같이 사라집니다.
출처
vllm-project/vllm#48698 과 같은 발상을 이 이미지가 싣는 파일에 맞춰 쓴 것입니다. (#53081 은 wrapper 대신 workspace 를 공유하지만 FlashInfer 의
shared_static_workspace(flashinfer-ai/flashinfer#4603)가 필요하고, 이 빌드0.6.18.dev20260819에는 없습니다.)Verification
tests/test_logic.py— all OK (666 checks)compose-overlays.sh glm53— 13 overlays from 11 modules86dfe87e…)🤖 Generated with Claude Code
Note
Medium Risk
Shared mutable GPU scratch assumes strictly sequential MoE execution on one stream; wrong overlap or future parallelism could cause cross-layer corruption. The patch calls
logger.info_oncewithout an obvious import in the shown file, which could fail on first wrapper creation if not provided by the base module.Overview
Adds a
b12x_shared_workspaceoverlay that patchesflashinfer_b12x_moe.pysoB12xMoEWrapperis created once per MoE geometry (experts, top_k, hidden/intermediate sizes, activation/SwiGLU params) instead of once per layer. Layers with identical geometry—e.g. 43 GLM-5.3-Flash MoE blocks—reuse the same wrapper via a thread-lockedWeakValueDictionary, with each layer still holding a strong ref in_ensure_wrapper.The intent is to drop ~22 GiB per rank of duplicate graph-stable scratch (~541 MiB per wrapper) so more GMU budget is available for KV cache. Wiring: new overlay
manifest.tsv, duplicate underbuild/glm53/, andb12x_shared_workspaceprepended toMODULESinprofiles/glm53.env.Reviewed by Cursor Bugbot for commit 772e0ba. Bugbot is set up for automated code reviews on this repo. Configure here.