Repository navigation
Conversation
…ipelines; no host zero of new buffers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q5zTV27LbaVZFTjnkdmTjJ
…te_metal prints the open's split Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q5zTV27LbaVZFTjnkdmTjJ
…tes nothing; passes counted by StepStats Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q5zTV27LbaVZFTjnkdmTjJ
There was a problem hiding this comment.
Verdict: CLEAN: No must-fix defect remains after tracing allocation failures, pass bounds and checkpoint validity.
Non-blocking
⚠ Cover eager mark copies: crates/metal/src/arch/qwen3moe/session.rs:739
All end-to-end gate constructors use open or open_with; r_resident:61 uses the latter and runs an unmarked pass at line 80. Deleting the eager branch leaves those gates green.
Extend r_resident to exercise MarkCopies::AtOpen with a marked pass and assert unchanged device bytes and residency entries. This protects the server's allocation guarantee while its owning gate is being changed.
Checked
Duplicates: 4 new items and the renamed fresh checked; no duplicated owner found. Dryer reported 0 pairs.
Complexity: open_as (18) moves the existing open orchestration and adds timing and eager-copy selection; existing owners handle allocation and residency. r_resident (18→19) adds an equality check, harmless even growth.
Silent failure: 3 optional-copy branches followed; unavailable copies are refused by checkpoint_copy. Allocation and pipeline errors propagate.
Tests (static mutation review): r_resident protects crates/metal/src/arch/qwen3moe/session.rs:738; restoring lazy arena allocation makes its growth assertion red, as the body reports. q_short, q_state and q_mark_cut protect crates/metal/src/arch/qwen3moe/target.rs:207; forcing the opposite prompt path triggers a refusal or the pass-count assertions. q_layers changes only a comment.
Gates: no numeric pins moved; the changed first-pass allocation invariant has FAIL-first evidence.
Performance: prefill path; 15 buffer allocations and the arena's residency registration move to open. Host arena zeroing is removed; kernel launches and reduction order are unchanged.
Escape catalog: C1–C4 do not match.
Notes
Metal gates require Apple Silicon/macOS and were not run in this Linux environment. Attach exact measured base/after commit hashes and gate command output; the body currently supplies branch descriptions and summarized return codes.
🔨 Shingler, bloomery's review bot: approves a clean pull request and requests changes on a must-fix (how it works)
A Metal process's first prompt call costs what a later one does. Part of #593.
The first prompt call of a process was 85–101 ms slower than the same call warm (M4 Pro, 873 ids).
generate_metalmeasures one cold call per process, so this was in every prompt rate, and in the ~100–118 ms fixed part of a call on the contributor's M3 and M5 Ultra.Decomposition, predicted before the run, then measured (M4 Pro, 873 ids, timers only, two runs):
(c) was the wrong term: about twice the M1 Pro figure the prediction used.
Session::open_as: the rows arena is made there and wired by the open's one residency commit, and the prefill pipelines are built first, so a refused build fails the open before the load. Every session now holds the arena (464,863,776 bytes on this model, cap 2048 rows; a smaller ctx caps it).newBufferWithLength, which Metal clears to zero, and no kernel of a pass reads a cell an earlier op of that pass did not write. The arena was zeroed only at its open before, so no pass sees other bits.MarkCopies { AtOpen, OnFirstMark }: the server opens the mark copies (metal: message marks kept inside one prompt call (prefill_marked) #792, 147,456,000 bytes) with its session; other sessions keep them lazy.generate_metalprintsopen_load_s,open_rows_ms,open_residency_ms,open_pipelines_msand alwaysrows_arena_bytes.Gates:
r_residentnow holds that the first pass allocates nothing on the device and adds nothing to the residency set (the open's set check covers the arena). FAIL-first, the arena opened lazily again: "FAIL (the first pass moved the device's bytes by 14532608 and the residency set from 125 buffers of 2769174528 bytes to 140 of 2783707136…)".q_short,q_stateandq_mark_cutused "the rows arena is open" as proof a pass ran; they now readStepStats::passes, the same fact counted directly.Gates (M1 Pro, fixture), each rc 0:
cargo fmt --all --check,check-unsafe,check-comments,just check-recipes,just mac-metal-lint,just lab-metal(114 mutants, each red on its clause),just lab-metal-e2e(11 mutants, each red on its clause).M4 Pro 48 GB, Qwen3.6-35B-A3B MLX 4-bit, development-loop numbers (not public).
generate_metal --prompt "$(cat p.txt)" -n 8 --ctx 8192, base and after interleaved, arm order rotated, two runs each:The open's added work is inside its noise (±0.5 s). After: rows 0.08–0.21 ms, residency 2500–2713 ms (the 20 GB of weights with it), pipelines 3.0–3.6 ms.
Evidence: base = #792's branch head before its review fix (which touches only the ring copy near the last u32 position); after = this change before a
usecleanup andcargo fmt. macOS 27.0.1, Apple M4 Pro 48 GB; model fileQwen3.6-35B-A3B-mlx4-00001-of-00001.gguf; release builds, one process per run. Load (vm.loadavg, 1 min) 2.8–5.1.The code and gates were written with Claude Code rounds and reviewed by the maintainer.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Q5zTV27LbaVZFTjnkdmTjJ