Repository navigation
bloomery-serve, hf, gpu, model-hf: -m <folder> and --hf serve a Qwen3.8 NVFP4 checkpoint folder as downloaded, with no prepare step - #635
Conversation
…r without a file (Split::header_only), its tokenizer from header keys, its stored rows as file runs (RunTable) and its pages released after a copy
…ned and checked first, then staged through one ring with one synchronize; GLM's tensor-parallel load passes its rank rule
…) on the planning prepare shares; its PLE rows where the folder stores them
…header plans, its parts fill the card, its PLE table is read from the folder on the NVMe tier
… set, and resolves it to the checkpoint's folder (hf_checkpoint record)
…r as downloaded, with no prepare step; gate_qwen4exp_nvfp4 loads one
There was a problem hiding this comment.
Verdict: CLEAN: No must-fix behavior or quality defect survived the code checks.
Optimization headroom
- E. Less work: crates/engram/src/rows.rs:417. Iterate run spans without materializing nested vectors. On folder decoding with
FillMode::Touchand classification off, prefetch and copy each rebuild these groups. Removing that materialization saves at least2 × (S + 1)heap allocations per token for S > 0 run stretches, before vector growth [derived].
Checked
Duplicates: 92 added/changed definitions checked, including moved helpers; no proven duplicate. Dryer reported 0 pairs. Its excluded gpu and gpu-gates crates were checked by Grep.
Complexity: ple_from_keys (23) and plan_tensors (20) rename/move existing logic; load_placed_from (17) relocates orchestration. Serve run (+6), open_with (+6), resolve_drafts (+4), PleHost::new (+3), and Q38::open (+2) add source selection/refusals. Draft38Off::fmt (+1) adds one match arm.
Silent failure: 5 fallback sites followed. Inverted ranges return an error; absent format overrides select the type's format; cache index paths have a parent; scale stems retain their names; absent optional BOS/EOS flags mean false.
Tests: Static mutation checks covered run-boundary comparisons, header-only tensor reads, whole-card/draft/residency refusals, PLE scale/width/row-count checks, online/offline checkpoint selection, and the file-mapping guard; their assertions reject those mutants. Renamed hash and tokenizer tests retain their reference assertions. The release/reread assertion checks byte preservation; a no-op release still passes it.
Gates: No tolerance moved. Three unsafe-count increases carry dated PIN reasons. No changed kernel or float reduction.
Adversarial checks: Boundary row ids, partial expert placement, missing stored PLE rows, and header-only page release reach named refusals.
Escape catalog: C1–C4 have no new matches.
Notes
This was a static review. Builds, tests, and GPU gates were not rerun here. The PR includes a GB10 gate run with the required evidence.
Card check: gpu-evidence. This pull request changes crates/gpu-gates/Cargo.toml, crates/gpu-gates/src/bin/bloomery_serve.rs, crates/gpu-gates/src/bin/bloomery_serve_qwen38.rs … and carries a gate run on the author's card, which counts as verified.
🔨 Shingler, bloomery's review bot: approves a clean pull request and requests changes on a must-fix (how it works)
|
The review is done and the contribution check passed, so I'm merging this. |
bloomery-serve가 받은 NVIDIA Qwen3.8 NVFP4 체크포인트 폴더를 prepare 없이 그대로 한 대의 DGX Spark에서 띄우게 합니다.
Part of #565.
What and why
bloomery-servenow serves NVIDIA'sQwen3.8-Flash-Next-NVFP4checkpoint folder exactly as downloaded, on one DGX Spark.-m <folder>takes the folder, and--hf <repo>takes a safetensors repository and resolves it to its folder.mainrefuses such a repository as holding no GGUF model, and the folder has to be converted byprepareinto a GGUF split of 129211441440 B first. The prepared split is still accepted and its plan is unchanged.Every part is loaded in its stored format, with no Q8_0 rewrite. The folder load serves only what this checkpoint needs on one card. Every other case is refused by name (see "What I ran into").
crates/gpu/src/parts.rs):parts::loadis the one owner of loading a source's parts. It plans and checks every part first, then stages them through one pinned ring with one synchronize. GLM's tensor-parallel load (crates/gpu-glm5next/src/tp/mod.rs) now calls it and passes only its rank rule. The folder path uses the same source seam at one rank.crates/model-hf/src/arch/qwen35moe/folder.rs):folder::openopens the folder for a load and forprepare, which now calls it.crates/safetensors,crates/gguf,crates/tokenizerandcrates/engramgain a header-only split, a tokenizer built from header keys, and a run table that reads the PLE rows (the per-layer embedding rows) where the folder stores them.crates/gpu/src/arch/qwen3moe/body38.rs):Model38andFolder38take a folder next to a split. The PLE table is read from the folder on the NVMe tier.--hf(crates/hf): a repository that holds a safetensors checkpoint and no GGUF set resolves to the checkpoint's folder, and the newhf_checkpointrecord names it.crates/gpu-gates/src/bin/shared/serve_seats/):qwen38_folder.rsis the one place that opens a folder, and the seat is chosen from the path's header.checkpointcargo feature (crates/gpu-gates/Cargo.toml): it carriesbloomery-model-hffor the folder path, so the recipes that do not reach that code keep their key and reach pin at zero gap. The release feature list and the recipes that buildbloomery-serveturn it on. A build without it refuses a folder by name. The per-modelbloomery-serve-qwen38recipe stays onhf, so that binary refuses a folder until it is built withcheckpoint.crates/model/src/placement/host_lock.rs): releasing a file's pages is refused for a shard that holds only a header, because a page release must nevermadvisea heap copy. The test isa_header_alone_releases_no_page.README.md,docs/serving.md,docs/BUILD.mdanddocs/contrib/dgx-spark.md.Release notes: Added: bloomery-serve serves NVIDIA's Qwen3.8 NVFP4 checkpoint folder as downloaded on one DGX Spark, from
-m <folder>or--hf <repo>, with no prepare step.Code shape
parts::load, and GLM uses it. The check "this load carries no draft" has one owner in the serve seat,draft_off_for, which the media path and the folder path share. Finding a shard by name has one function,Folder::shardincrates/safetensors/src/lib.rs, whichfile_range,mappedand upstream'srawall use.prepareand the folder load sharefolder::open,served_as_hfandplan_tensors, which moved out ofprepare.rswith their refusals unchanged.parts::loadcarry no model name. The folder reader names only Qwen3.8's tensors and its PLE rows.tp::loadandprepare's own copies of the folder checks are replaced by the owners above.checkpoint, a repository of another quant, a PLE row that is not F8, a PLE table on the host tier, a tensor that does not sit whole on the card, a folder with residency on,BLOOMERY_DRAFT=mtpon a folder, a run table with no rows, an empty row or a run past the end of its file, and a page release on a header-only shard.engram, one block and one function inmodel, and one block inmodel-hf, each with a datedPINline and aSAFETYline at its use.cargo fmtandcargo clippyare clean on what I touched; the lint count did not go up.Duplication found or removed (
path:line): the duplicate scan reported three candidates.crates/engram/src/hash.rs:660and:670read different types and share only a one-line lookup.crates/engram/src/rows.rs:457and:461are two trait methods that each delegate to their own method.crates/safetensors/src/lib.rs:475and:485shareFolder::shard, as above.What I ran
The PR head is
1bb657e852cd5e8a844c8496e91c44cd6719c374, on main58356c0039f1a707142e4ac2bb15677f2e1e7afe. It isc56ca5349517db0c9525255efe38436310ae681frebased onto that main with every commit unchanged; the only file both touch isREADME.md, where main changed other lines. The GPU, CPU and gate runs below ran on a commit whose non-test code is the same asc56ca534; the two differ only in two#[cfg(test)]test modules.The model is
nvidia/Qwen3.8-Flash-Next-NVFP4at revisionfc694b54fb0174e0913e6adf86691ef85a4ead47, 25 files, 132,734,505,212 bytes. The prepared split of the same checkpoint is the reference.Plan, folder against split (
bloomery-serve --plan, draft off): the planned bytes are equal.Serving, folder against split (context 8192, one slot, draft off):
need bytesis 84788613696 andresident_bytesis 81854312844 for both, and the captured graph has 1295 nodes for both. Greedy decoding gives identical ids and text for both prompts ("The capital of France is", 32 ids, and a Fibonacci function prompt, 64 ids), and the chat reply to "Name three primary colors in one short sentence." (64 tokens) is identical. The comparison is JSON equality over the saved responses.The correctness gate on the folder is under "GPU Evidence".
Residency and draft on a folder:
BLOOMERY_DRAFT=mtp bloomery-serve --plan -m <folder>exits 1 with a named refusal, and an unset draft is turned off by itself.Tests, on the PR head, on an x86_64 CPU host:
The fail-first run is under "GPU Evidence". The host crates (
model-hf,hf,safetensors,engram,gguf,tokenizer,model) pass 735 tests with 0 failures, and thegpu-gateslibrary tests forhf,record::andmodel_file::pass 32.GPU Evidence
The card is a DGX Spark (GB10) in the dev container image, driver 595.84, CUDA 13.3.
The serving build used
--features glm5next,clef,mimo2,solar2,minimaxm3,vision,gemma-embedding2,hf,checkpoint. The gate is built with--features gpu,checkpoint.Correctness gate, on the folder:
gate_qwen4exp_nvfp4uses the Hugging Face NVFP4 checkpoint itself as its oracle.gate_qwen4exp_e2eis not run on the folder because it compares against the Q8_0 split with routed experts on the host tier, and the folder load requires every tensor whole on the card.The folder and the prepared split have the same planned bytes, the same greedy ids and the same chat reply.
Fail-first, on the PR head on the same card: each of four mutants turned its test red (exit 101), and with the source restored all four tests passed.
The change adds no kernel and puts no launch, copy or synchronize on the decode path. The load path uses one pinned ring and one synchronize for the whole load, so no timed A/B is attached.
What I ran into
This does not block the PR. The folder load covers the NVFP4 checkpoint on one card and refuses the rest by name.
just contrib-check --tier t0was not run on this head.Hardware
A DGX Spark (GB10), driver 595.84, CUDA 13.3 in the dev container, for the serving runs, the gate and the fail-first run. An x86_64 CPU host ran the unit tests.
AI help
AI 코딩 에이전트가 코드를 작성한 후 설명을 썼고, 테스트를 마쳤습니다. diff 리뷰와 PR 초안 리뷰는 제가 직접 했습니다.