docs(adr): ADR-075 — MoE expert-offload priority (Metal)#727
Conversation
Fifth sequencing ADR in the bundle set (siblings ADR-071/072/073/074). Verdict NEEDS-EXPERIMENT, reframed: ranking expert-offload presupposes a working, measured, resident MoE serving path to offload from, and that precondition is false on the current head. The single MoE preset (qwen36_35b_a3b) is source-verified not loadable on any consumer Apple Silicon today; its Metal dispatch (ADR-053/#57) is wired but has zero test/bench/measurement and runs only at f16 (Q4/Q8 all refuse MoE at three enforcement points). Records a measured correction of ADR-053: its "~15 GiB @ Q4" resident figure is 4x under — the real f16 footprint is 60 GiB — because the Q4 MoE basis was never implemented. Gates the whole offload family behind a minimal synthetic-MoE dispatch bench (first real MoE tok/s on this engine) plus a loader-sequencing confirmation, before any offload code. Untrusted external survey folded (repo-blind, scoped to DeepSeek-V4-Flash, arithmetic unranked until re-derived on real numbers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…E2 fallback, source-derived wording Applies codex R1 (APPROVE-WITH-FIXES) findings: - M1: narrow "not loadable on any consumer Apple Silicon" → the 32-128 GB M-series/M-Max class; Ultra-class desktops (192-512 GB) could hold the ~180 GiB peak, unproven until Step 0 measures it (3 sites). - M2: E2 "every binary falls back to qwen36_27b" → path-specific dense defaults (Q4→27b, safetensors→2b, benches→0.8b); MoE preset selected by no default (verified vs origin/main lattice.rs:1061/1076, model.rs:37-42). - M3: survey repo-blindness reframed onto repository-verifiable absences (no crates/engine, no GGUF, no such binaries — grep-confirmable); packet quotes demoted to corroboration. - minor: "measured correction" → "source-derived correction" (the 60/120 GiB figures are derived arithmetic, not runtime-measured). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ohdearquant
left a comment
There was a problem hiding this comment.
SPEC-GATE: SIGNED (Leo). The reframe is the honest verdict: 'gated, not ranked' is correct when the resident path beneath every offload lever has never produced a token, and refusing to rank on a repo-blind survey scoped to a different model family is exactly right. The ADR-053 amendment is the house pattern done well — immutable record untouched, only the memory arithmetic and 32GB-feasibility corrected, with the causal mechanism (ADR-044 deferral enforced in the converter, no MoE quantizer ever landed) rather than a bare number. The codex-narrowed loadability claim (not loadable on 32-128 GB M-series/M-Max; Ultra-class unproven pending Step 0) survives my read at all three sites. Rider: Step 0's result lands as a new S-row on this ADR whichever way it goes — if from_safetensors turns out to stream internally, the 120 GiB peak claim gets corrected the same way this ADR corrected ADR-053. Proceed to G on merge.
ADR-075 — MoE expert-offload priority (Metal)
Fifth sequencing ADR in the bundle set, after ADR-071 (GDN-state), ADR-072 (weight-quant), ADR-073 (KV-quant), ADR-074 (MTP). Docs-only.
Verdict: NEEDS-EXPERIMENT, reframed — gated, not ranked
The question as commissioned — rank the open MoE expert-offload levers — presupposes a working, measured, resident MoE serving path whose next optimization is offload. That precondition is false on the current head, and the reasons are the finding.
Load-bearing facts (all verified against
origin/main @ c9ae21a9):qwen36_35b_a3b). The large model it actually serves and has measured (~4 tok/s) isqwen36_27b, which is dense — so no measured number this engine has ever produced touches MoE.encode_moe_ffnhas one production call site, appears in no test), and runs only at f16 — Q4/QuaRot, Q8-CPU, and Q8-NEON all three explicitly refuse MoE.&ModelWeights, so the CPU loader materializes the full model as f32 (~120 GiB) before any Metal buffer is built — a loader-sequencing ceiling that makes the model not loadable on any consumer Apple Silicon today, independent of offload.Measured correction of a merged ADR (ADR-053)
ADR-053 quotes "~15 GiB" resident routed-expert weights and reasons its 32 GB feasibility from it — but it says "At Q4 with the current config dimensions," and Q4 was never implemented for MoE (the three refusal points above). The only precision that runs is f16, so the real resident footprint is 60 GiB — 4× the ADR-053 figure. This is recorded as an amendment here (ADR-053 stays an immutable record); its dispatch/routing design is unaffected, only its resident-memory arithmetic and the "borderline on 32 GB" claim are corrected (it's not borderline — it doesn't fit).
Structure
A Measured / source-verified reality table (E1–E12, each tagged source-read / unit-test-pinned / runtime-measured with a durable pointer) plus a derived memory-arithmetic table, held apart from an untrusted external prior-art survey that is confirmed repo-blind (targets a nonexistent
crates/enginecrate and a GGUF loader lattice doesn't have) and scoped to a different model family (DeepSeek-V4-Flash). The survey's arithmetic is unranked until re-derived on lattice's real 6.0 MiB/expert f16 numbers; its one convergent conclusion (build and measure the resident dispatch before adding disk streaming) matches the source-read verdict.Decision
Gates the whole offload family (#682 the literal lever, #686 the epic, FP4 #683 / FP8 #684 adjacent) behind a minimal experiment:
MetalQwen35Enginefor the first-ever measured MoE dispatch correctness + latency, under GPU flock, committed as an artifact.Honest framing: this is not "REFUTED — wrong architecture" (MoE exists and is wired); it's "the lever is real, but the measurement floor beneath it does not exist yet." Includes a forward instruction (mirroring ADR-074's rider): when Step 1's bench lands, its numbers amend both this ADR's table and ADR-053's corrected figure with runtime-measured rows.
Testing
Docs-only. No executable behavior changes.